From 39408fd3b1f39c6799caf9d214cc3dd613d4824c Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 31 Mar 2025 05:50:53 -0500 Subject: [PATCH 001/238] Disable network config for non-eth_gateway nrf52 and non-W RP2040 targets (#6462) * Disable network config for non-eth_gateway nrf52 and non-W RP2040 targets * Use HAS_ETHERNET logic --- src/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 59cd6d8e9..f8443f9e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1274,6 +1274,12 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG; #endif +#if defined(ARCH_NRF52) && !HAS_ETHERNET // nrf52 doesn't have network unless it's a RAK ethernet gateway currently + deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_NETWORK_CONFIG; // No network on nRF52 +#elif defined(ARCH_RP2040) && !HAS_WIFI && !HAS_ETHERNET + deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_NETWORK_CONFIG; // No network on RP2040 +#endif + #if !(MESHTASTIC_EXCLUDE_PKI) deviceMetadata.hasPKC = true; #endif From 886bffe8f3b1e27b087c7f866129d7d763bc22de Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Tue, 1 Apr 2025 00:03:44 +1300 Subject: [PATCH 002/238] fix: honor user button customization (#6400) Co-authored-by: Ben Meadors --- src/graphics/niche/Inputs/TwoButton.cpp | 38 ++++++++++++++++++- src/graphics/niche/Inputs/TwoButton.h | 4 +- .../heltec_vision_master_e213/nicheGraphics.h | 2 +- .../heltec_vision_master_e290/nicheGraphics.h | 4 +- .../heltec_wireless_paper/nicheGraphics.h | 2 +- variants/t-echo/nicheGraphics.h | 2 +- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/graphics/niche/Inputs/TwoButton.cpp b/src/graphics/niche/Inputs/TwoButton.cpp index 10d89ef41..b270d56cf 100644 --- a/src/graphics/niche/Inputs/TwoButton.cpp +++ b/src/graphics/niche/Inputs/TwoButton.cpp @@ -2,6 +2,7 @@ #include "./TwoButton.h" +#include "NodeDB.h" // For the helper function TwoButton::getUserButtonPin #include "PowerFSM.h" #include "sleep.h" @@ -57,14 +58,47 @@ void TwoButton::stop() detachInterrupt(buttons[1].pin); } +// Attempt to resolve a GPIO pin for the user button, honoring userPrefs.jsonc and device settings +// This helper method isn't used by the TweButton class itself, it could be moved elsewhere. +// Intention is to pass this value to TwoButton::setWiring in the setupNicheGraphics method. +uint8_t TwoButton::getUserButtonPin() +{ + uint8_t pin = 0xFF; // Unset + + // Use default pin for variant, if no better source +#ifdef BUTTON_PIN + pin = BUTTON_PIN; +#endif + + // From userPrefs.jsonc, if set +#ifdef USERPREFS_BUTTON_PIN + pin = USERPREFS_BUTTON_PIN; +#endif + + // From user's override in device settings, if set + if (config.device.button_gpio) + pin = config.device.button_gpio; + + return pin; +} + // Configures the wiring and logic of either button // Called when outlining your NicheGraphics implementation, in variant/nicheGraphics.cpp void TwoButton::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup) { + // Prevent the same GPIO being assigned to multiple buttons + // Allows an edge case when the user remaps hardware buttons using device settings, due to a broken user button + for (uint8_t i = 0; i < whichButton; i++) { + if (buttons[i].pin == pin) { + LOG_WARN("Attempted reuse of GPIO %d. Ignoring assignment whichButton=%d", pin, whichButton); + return; + } + } + assert(whichButton < 2); buttons[whichButton].pin = pin; - buttons[whichButton].activeLogic = LOW; - buttons[whichButton].mode = internalPullup ? INPUT_PULLUP : INPUT; // fix me + buttons[whichButton].activeLogic = LOW; // Unimplemented + buttons[whichButton].mode = internalPullup ? INPUT_PULLUP : INPUT; pinMode(buttons[whichButton].pin, buttons[whichButton].mode); } diff --git a/src/graphics/niche/Inputs/TwoButton.h b/src/graphics/niche/Inputs/TwoButton.h index 1e1576256..f1e18dd89 100644 --- a/src/graphics/niche/Inputs/TwoButton.h +++ b/src/graphics/niche/Inputs/TwoButton.h @@ -30,6 +30,8 @@ class TwoButton : protected concurrency::OSThread public: typedef std::function Callback; + static uint8_t getUserButtonPin(); // Resolve the GPIO, considering the various possible source of definition + static TwoButton *getInstance(); // Create or get the singleton instance void start(); // Start handling button input void stop(); // Stop handling button input (disconnect ISRs for sleep) @@ -62,7 +64,7 @@ class TwoButton : protected concurrency::OSThread public: // Per-button config uint8_t pin = 0xFF; // 0xFF: unset - bool activeLogic = LOW; // Active LOW by default. Todo: remove, unused + bool activeLogic = LOW; // Active LOW by default. Currently unimplemented. uint8_t mode = INPUT; // Whether to use internal pull up / pull down resistors uint32_t debounceLength = 50; // Minimum length for shortpress, in ms uint32_t longpressLength = 500; // How long after button down to fire longpress, in ms diff --git a/variants/heltec_vision_master_e213/nicheGraphics.h b/variants/heltec_vision_master_e213/nicheGraphics.h index 75e4423be..d6983bafe 100644 --- a/variants/heltec_vision_master_e213/nicheGraphics.h +++ b/variants/heltec_vision_master_e213/nicheGraphics.h @@ -95,7 +95,7 @@ void setupNicheGraphics() constexpr uint8_t AUX_BUTTON = 1; // Setup the main user button - buttons->setWiring(MAIN_BUTTON, BUTTON_PIN); + buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); diff --git a/variants/heltec_vision_master_e290/nicheGraphics.h b/variants/heltec_vision_master_e290/nicheGraphics.h index 2674436b8..c2f26c7ff 100644 --- a/variants/heltec_vision_master_e290/nicheGraphics.h +++ b/variants/heltec_vision_master_e290/nicheGraphics.h @@ -19,7 +19,7 @@ Different NicheGraphics UIs and different hardware variants will each have their // InkHUD-specific components // --------------------------- -#include "graphics/niche/InkHUD/WindowManager.h" +#include "graphics/niche/InkHUD/InkHUD.h" // Applets #include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h" @@ -113,7 +113,7 @@ void setupNicheGraphics() Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // A shared NicheGraphics component // Setup the main user button (0) - buttons->setWiring(0, BUTTON_PIN); + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); buttons->setHandlerShortPress(0, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); buttons->setHandlerLongPress(0, []() { InkHUD::InkHUD::getInstance()->longpress(); }); diff --git a/variants/heltec_wireless_paper/nicheGraphics.h b/variants/heltec_wireless_paper/nicheGraphics.h index ece4225d0..5e938fa64 100644 --- a/variants/heltec_wireless_paper/nicheGraphics.h +++ b/variants/heltec_wireless_paper/nicheGraphics.h @@ -93,7 +93,7 @@ void setupNicheGraphics() constexpr uint8_t MAIN_BUTTON = 0; // Setup the main user button - buttons->setWiring(MAIN_BUTTON, BUTTON_PIN); + buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); diff --git a/variants/t-echo/nicheGraphics.h b/variants/t-echo/nicheGraphics.h index e8a9232f1..f5dde6b19 100644 --- a/variants/t-echo/nicheGraphics.h +++ b/variants/t-echo/nicheGraphics.h @@ -104,7 +104,7 @@ void setupNicheGraphics() constexpr uint8_t TOUCH_BUTTON = 1; // Setup the main user button - buttons->setWiring(MAIN_BUTTON, BUTTON_PIN, LOW); + buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); buttons->setTiming(MAIN_BUTTON, 75, 500); buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); From a5efbfccd784f77784ec429794378b599476935e Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 31 Mar 2025 06:32:54 -0500 Subject: [PATCH 003/238] Disable bluetooth config on rp2040, portduino (for now), and stm32 (#6465) * Disable bluetooth config on rp2040, portduino (for now), and stm32 * Add comments and exclude C6 --- src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index f8443f9e9..05eeef2ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1274,6 +1274,13 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG; #endif +// No bluetooth on these targets (yet): +// Pico W / 2W may get it at some point +// Portduino and ESP32-C6 are excluded because we don't have a working bluetooth stacks integrated yet. +#if defined(ARCH_RP2040) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL) || defined(CONFIG_IDF_TARGET_ESP32C6) + deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_BLUETOOTH_CONFIG; +#endif + #if defined(ARCH_NRF52) && !HAS_ETHERNET // nrf52 doesn't have network unless it's a RAK ethernet gateway currently deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_NETWORK_CONFIG; // No network on nRF52 #elif defined(ARCH_RP2040) && !HAS_WIFI && !HAS_ETHERNET From 2c01fad798e17bcc5e6feb4644ba15c12e32fffa Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 31 Mar 2025 08:31:54 -0400 Subject: [PATCH 004/238] meshtasticd: Add FrequencyLabs MeshAdv-Mini Hat (#6458) --- bin/config.d/lora-MeshAdv-900M30S.yaml | 4 +++- bin/config.d/lora-MeshAdv-Mini-900M22S.yaml | 11 +++++++++++ src/platform/portduino/PortduinoGlue.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 bin/config.d/lora-MeshAdv-Mini-900M22S.yaml diff --git a/bin/config.d/lora-MeshAdv-900M30S.yaml b/bin/config.d/lora-MeshAdv-900M30S.yaml index 113901d5e..5c148bf68 100644 --- a/bin/config.d/lora-MeshAdv-900M30S.yaml +++ b/bin/config.d/lora-MeshAdv-900M30S.yaml @@ -1,3 +1,5 @@ +# MeshAdv-Pi E22-900M30S +# https://github.com/chrismyers2000/MeshAdv-Pi-Hat Lora: Module: sx1262 CS: 21 @@ -9,4 +11,4 @@ Lora: DIO3_TCXO_VOLTAGE: true # Only for E22-900M33S: # Limit the output power to 8 dBm - # SX126X_MAX_POWER: 8 \ No newline at end of file + # SX126X_MAX_POWER: 8 diff --git a/bin/config.d/lora-MeshAdv-Mini-900M22S.yaml b/bin/config.d/lora-MeshAdv-Mini-900M22S.yaml new file mode 100644 index 000000000..554116b57 --- /dev/null +++ b/bin/config.d/lora-MeshAdv-Mini-900M22S.yaml @@ -0,0 +1,11 @@ +# MeshAdv Mini E22-900M22S +# https://github.com/chrismyers2000/MeshAdv-Mini +Lora: + Module: sx1262 # Ebyte E22-900M22S + CS: 8 + IRQ: 16 + Busy: 20 + Reset: 24 + TXen: 13 + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index a7aea1c3e..4e074be71 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -11,6 +11,7 @@ inline const std::unordered_map configProducts = {{"MESHTOAD", "lora-usb-meshtoad-e22.yaml"}, {"MESHSTICK", "lora-meshstick-1262.yaml"}, {"MESHADV-PI", "lora-MeshAdv-900M30S.yaml"}, + {"MESHADV-MINI", "lora-MeshAdv-Mini-900M22S.yaml"}, {"POWERPI", "lora-MeshAdv-900M30S.yaml"}}; enum configNames { From ae887590594de8e573ca2ce16334f5534ce34155 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Tue, 1 Apr 2025 13:08:23 +1300 Subject: [PATCH 005/238] draft an InkHUD variant for Elecrow Thinknode M1 (#6473) Only an initial guess. No hardware here yet for testing. Button assignments are largely placeholder. Co-authored-by: Ben Meadors --- variants/ELECROW-ThinkNode-M1/nicheGraphics.h | 119 ++++++++++++++++++ variants/ELECROW-ThinkNode-M1/platformio.ini | 22 +++- variants/ELECROW-ThinkNode-M1/variant.h | 2 - 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 variants/ELECROW-ThinkNode-M1/nicheGraphics.h diff --git a/variants/ELECROW-ThinkNode-M1/nicheGraphics.h b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h new file mode 100644 index 000000000..f68ac9edd --- /dev/null +++ b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h @@ -0,0 +1,119 @@ +#pragma once + +#include "configuration.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +// InkHUD-specific components +// --------------------------- +#include "graphics/niche/InkHUD/InkHUD.h" + +// Applets +#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h" +#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h" +#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" +#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" + +// Shared NicheGraphics components +// -------------------------------- +#include "graphics/niche/Drivers/Backlight/LatchingBacklight.h" +#include "graphics/niche/Drivers/EInk/GDEY0154D67.h" +#include "graphics/niche/Inputs/TwoButton.h" + +#include "graphics/niche/Fonts/FreeSans6pt7b.h" +#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" +#include + +void setupNicheGraphics() +{ + using namespace NicheGraphics; + + // SPI + // ----------------------------- + + // For NRF52 platforms, SPI pins are defined in variant.h, not passed to begin() + SPI1.begin(); + + // Driver + // ----------------------------- + + // Use E-Ink driver + Drivers::EInk *driver = new Drivers::GDEY0154D67; // Todo: confirm display model + driver->begin(&SPI1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); + + // InkHUD + // ---------------------------- + + InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); + + // Set the driver + inkhud->setDriver(driver); + + // Set how many FAST updates per FULL update + // Set how unhealthy additional FAST updates beyond this number are + // Todo: observe the display's performance in-person and adjust accordingly. + // Currently set to the values given by Elecrow for EInkDynamicDisplay. + inkhud->setDisplayResilience(10, 1.5); + + // Prepare fonts + InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); + /* + // Font localization demo: Cyrillic + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); + InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); + */ + + // Customize default settings + inkhud->persistence->settings.userTiles.maxCount = 2; // Two applets side-by-side + inkhud->persistence->settings.rotation = 0; // To be confirmed? + inkhud->persistence->settings.optionalFeatures.batteryIcon = true; // Device definitely has a battery + + // Setup backlight + // Note: button mapping for this configured further down + Drivers::LatchingBacklight *backlight = Drivers::LatchingBacklight::getInstance(); + backlight->setPin(PIN_EINK_EN); + + // Pick applets + // Note: order of applets determines priority of "auto-show" feature + inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown + inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, no autoshow, default on tile 0 + + // Start running InkHUD + inkhud->begin(); + + // Buttons + // -------------------------- + + Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component + + // As labeled on Elecrow diagram: https://www.elecrow.com/download/product/CIL12901M/ThinkNode-M1_User_Manual.pdf + constexpr uint8_t PAGE_TURN_BUTTON = 0; + constexpr uint8_t FUNCTION_BUTTON = 1; + + // Setup the main user button + buttons->setWiring(PAGE_TURN_BUTTON, PIN_BUTTON2); + buttons->setTiming(PAGE_TURN_BUTTON, 50, 500); // Todo: confirm 50ms is adequate debounce + buttons->setHandlerShortPress(PAGE_TURN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); + buttons->setHandlerLongPress(PAGE_TURN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + + // Setup the aux button + // Initial testing only: mapped to the backlight + // Todo: additional features + buttons->setWiring(FUNCTION_BUTTON, PIN_BUTTON1); + buttons->setTiming(FUNCTION_BUTTON, 50, 500); // 500ms before latch + buttons->setHandlerDown(FUNCTION_BUTTON, [backlight]() { backlight->peek(); }); + buttons->setHandlerLongPress(FUNCTION_BUTTON, [backlight]() { backlight->latch(); }); + buttons->setHandlerShortPress(FUNCTION_BUTTON, [backlight]() { backlight->off(); }); + + buttons->start(); +} + +#endif \ No newline at end of file diff --git a/variants/ELECROW-ThinkNode-M1/platformio.ini b/variants/ELECROW-ThinkNode-M1/platformio.ini index f37f6d310..86fbde398 100644 --- a/variants/ELECROW-ThinkNode-M1/platformio.ini +++ b/variants/ELECROW-ThinkNode-M1/platformio.ini @@ -10,6 +10,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1 -DELECROW_ThinkNode_M1 -DGPS_POWER_TOGGLE -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -DUSE_EINK -DEINK_DISPLAY_MODEL=GxEPD2_154_D67 -DEINK_WIDTH=200 -DEINK_HEIGHT=200 @@ -26,4 +27,23 @@ lib_deps = https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip lewisxhe/PCF8563_Library@^1.0.1 khoih-prog/nRF52_PWM@^1.0.1 -;upload_protocol = fs \ No newline at end of file +;upload_protocol = fs + +[env:thinknode_m1-inkhud] +extends = nrf52840_base, inkhud +board = ThinkNode-M1 +board_check = true +debug_tool = jlink +build_flags = + ${nrf52840_base.build_flags} + ${inkhud.build_flags} + -I variants/ELECROW-ThinkNode-M1 + -D ELECROW_ThinkNode_M1 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" +build_src_filter = + ${nrf52_base.build_src_filter} + ${inkhud.build_src_filter} +lib_deps = + ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX + ${nrf52840_base.lib_deps} + lewisxhe/PCF8563_Library@^1.0.1 \ No newline at end of file diff --git a/variants/ELECROW-ThinkNode-M1/variant.h b/variants/ELECROW-ThinkNode-M1/variant.h index 3bfa360f6..fc2fddbdf 100644 --- a/variants/ELECROW-ThinkNode-M1/variant.h +++ b/variants/ELECROW-ThinkNode-M1/variant.h @@ -140,8 +140,6 @@ External serial flash WP25R1635FZUIL0 // Controls power for all peripherals (eink + GPS + LoRa + Sensor) #define PIN_POWER_EN (0 + 12) -#define USE_EINK - #define PIN_SPI1_MISO (32 + 7) #define PIN_SPI1_MOSI PIN_EINK_MOSI #define PIN_SPI1_SCK PIN_EINK_SCLK From 128c347c645d64497b5f024364e44c5884079b12 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Tue, 1 Apr 2025 23:26:46 +1300 Subject: [PATCH 006/238] fix: T-Echo frontlight on at boot when using OLED UI (#6474) --- src/graphics/EInkDisplay2.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 96c6b44c1..27117641e 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -128,11 +128,7 @@ bool EInkDisplay::connect() #ifdef PIN_EINK_EN // backlight power, HIGH is backlight on, LOW is off pinMode(PIN_EINK_EN, OUTPUT); -#ifdef ELECROW_ThinkNode_M1 digitalWrite(PIN_EINK_EN, LOW); -#else - digitalWrite(PIN_EINK_EN, HIGH); -#endif #endif #if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) From ea4ce8d827d45e82e7ce5b377d956e324f80733c Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:53:15 +0200 Subject: [PATCH 007/238] MUI unPhone-tft: fix defaults (#6477) --- src/mesh/NodeDB.cpp | 2 +- variants/unphone/platformio.ini | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 3f79d18e6..9bb63652a 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -689,7 +689,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(MESH_TAB) || defined(RAK14014) +#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; diff --git a/variants/unphone/platformio.ini b/variants/unphone/platformio.ini index 18efbb157..399d65b03 100644 --- a/variants/unphone/platformio.ini +++ b/variants/unphone/platformio.ini @@ -35,19 +35,19 @@ lib_deps = ${esp32s3_base.lib_deps} extends = env:unphone build_flags = ${env:unphone.build_flags} + -D CONFIG_DISABLE_HAL_LOCKS=1 -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 - -D MESHTASTIC_EXCLUDE_BLUETOOTH=1 -D MESHTASTIC_EXCLUDE_WEBSERVER=1 -D MESHTASTIC_EXCLUDE_SERIAL=1 -D MESHTASTIC_EXCLUDE_SOCKETAPI=1 -D INPUTDRIVER_BUTTON_TYPE=21 - -D MAX_THREADS=40 -D HAS_SCREEN=0 -D HAS_TFT=1 -D HAS_SDCARD -D DISPLAY_SET_RESOLUTION - -D RAM_SIZE=3072 + -D RAM_SIZE=6144 + -D LV_CACHE_DEF_SIZE=2097152 -D LV_LVGL_H_INCLUDE_SIMPLE -D LV_CONF_INCLUDE_SIMPLE -D LV_COMP_CONF_INCLUDE_SIMPLE @@ -63,6 +63,7 @@ build_flags = -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_UNPHONE.h\" -D VIEW_320x240 -D USE_PACKET_API + -D MAP_FULL_REDRAW lib_deps = ${env:unphone.lib_deps} From 644849126ca179ee52f31133cc62e72142dde8f7 Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Tue, 1 Apr 2025 10:50:10 -0700 Subject: [PATCH 008/238] Fixes #6315 (#6475) * Fixed Canned Messages send to non broadcast * Small fix * Fix formatting for singular canned message * Trunk fmt --------- Co-authored-by: Ben Meadors --- src/modules/CannedMessageModule.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 2a5ec00ab..c16c0e4b3 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -483,7 +483,7 @@ int32_t CannedMessageModule::runOnce() #if defined(USE_VIRTUAL_KEYBOARD) sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true); #else - sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true); + sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true); #endif } this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE; @@ -1114,20 +1114,19 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest)); int lines = (display->getHeight() / FONT_HEIGHT_SMALL) - 1; if (lines == 3) { - // static (old) behavior for small displays - display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage()); display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL); display->setColor(BLACK); display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage()); display->setColor(WHITE); - display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage()); + if (this->messagesCount > 1) { + display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage()); + display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage()); + } } else { - // use entire display height for larger displays int topMsg = (messagesCount > lines && currentMessageIndex >= lines - 1) ? currentMessageIndex - lines + 2 : 0; for (int i = 0; i < std::min(messagesCount, lines); i++) { if (i == currentMessageIndex - topMsg) { #ifdef USE_EINK - // Avoid drawing solid black with fillRect: harder to clear for E-Ink display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), ">"); display->drawString(12 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), cannedMessageModule->getCurrentMessage()); @@ -1138,7 +1137,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), cannedMessageModule->getCurrentMessage()); display->setColor(WHITE); #endif - } else { + } else if (messagesCount > 1) { // Only draw others if there are multiple messages display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), cannedMessageModule->getMessageByIndex(topMsg + i)); } From f6ed10f3298abf6896892ca7906d3231c8b3f567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hampa=C3=AF?= Date: Tue, 1 Apr 2025 22:39:40 +0200 Subject: [PATCH 009/238] Added initial support for Texas Instruments LP5562 (#6381) * Added initial support for Texas Instrument LP5562 * Added proper support for Ambient Lighting * Code merge for all RBG_LED enabled devices * Fixed forgotten log_info & added firstRGBLED() --- src/AmbientLightingThread.h | 43 +++++++++++++++++----- src/configuration.h | 6 +++ src/detect/ScanI2C.cpp | 6 +++ src/detect/ScanI2C.h | 3 ++ src/detect/ScanI2CTwoWire.cpp | 3 ++ src/graphics/NomadStarLED.h | 5 +++ src/main.cpp | 8 ++-- src/modules/ExternalNotificationModule.cpp | 29 +++++++++++++-- 8 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 src/graphics/NomadStarLED.h diff --git a/src/AmbientLightingThread.h b/src/AmbientLightingThread.h index c487f9d53..bff8846d6 100644 --- a/src/AmbientLightingThread.h +++ b/src/AmbientLightingThread.h @@ -6,6 +6,11 @@ NCP5623 rgb; #endif +#ifdef HAS_LP5562 +#include +LP5562 rgbw; +#endif + #ifdef HAS_NEOPIXEL #include Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE); @@ -26,7 +31,7 @@ class AmbientLightingThread : public concurrency::OSThread notifyDeepSleepObserver.observe(¬ifyDeepSleep); // Let us know when shutdown() is issued. // Enables Ambient Lighting by default if conditions are meet. -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#ifdef HAS_RGB_LED #ifdef ENABLE_AMBIENTLIGHTING moduleConfig.ambient_lighting.led_state = true; #endif @@ -39,7 +44,7 @@ class AmbientLightingThread : public concurrency::OSThread // moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8; // moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF; -#ifdef HAS_NCP5623 +#if defined(HAS_NCP5623) || defined(HAS_LP5562) _type = type; if (_type == ScanI2C::DeviceType::NONE) { LOG_DEBUG("AmbientLighting Disable due to no RGB leds found on I2C bus"); @@ -47,17 +52,21 @@ class AmbientLightingThread : public concurrency::OSThread return; } #endif -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#ifdef HAS_RGB_LED if (!moduleConfig.ambient_lighting.led_state) { LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF"); disable(); return; } LOG_DEBUG("AmbientLighting init"); -#ifdef HAS_NCP5623 +#if defined(HAS_NCP5623) || defined(HAS_LP5562) if (_type == ScanI2C::NCP5623) { rgb.begin(); #endif +#ifdef HAS_LP5562 + } else if (_type == ScanI2C::LP5562) { + rgbw.begin(); +#endif #ifdef RGBLED_RED pinMode(RGBLED_RED, OUTPUT); pinMode(RGBLED_GREEN, OUTPUT); @@ -70,7 +79,7 @@ class AmbientLightingThread : public concurrency::OSThread #endif setLighting(); #endif -#ifdef HAS_NCP5623 +#if defined(HAS_NCP5623) || defined(HAS_LP5562) } #endif } @@ -78,13 +87,13 @@ class AmbientLightingThread : public concurrency::OSThread protected: int32_t runOnce() override { -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) -#ifdef HAS_NCP5623 - if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) { +#ifdef HAS_RGB_LED +#if defined(HAS_NCP5623) || defined(HAS_LP5562) + if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) { #endif setLighting(); return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification -#ifdef HAS_NCP5623 +#if defined(HAS_NCP5623) || defined(HAS_LP5562) } #endif #endif @@ -108,6 +117,14 @@ class AmbientLightingThread : public concurrency::OSThread rgb.setBlue(0); LOG_INFO("OFF: NCP5623 Ambient lighting"); #endif +#ifdef HAS_LP5562 + rgbw.setCurrent(0); + rgbw.setRed(0); + rgbw.setGreen(0); + rgbw.setBlue(0); + rgbw.setWhite(0); + LOG_INFO("OFF: LP5562 Ambient lighting"); +#endif #ifdef HAS_NEOPIXEL pixels.clear(); pixels.show(); @@ -141,6 +158,14 @@ class AmbientLightingThread : public concurrency::OSThread LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); #endif +#ifdef HAS_LP5562 + rgbw.setCurrent(moduleConfig.ambient_lighting.current); + rgbw.setRed(moduleConfig.ambient_lighting.red); + rgbw.setGreen(moduleConfig.ambient_lighting.green); + rgbw.setBlue(moduleConfig.ambient_lighting.blue); + LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current, + moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); +#endif #ifdef HAS_NEOPIXEL pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue), diff --git a/src/configuration.h b/src/configuration.h index fd4a5b196..ba6066896 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -170,6 +170,7 @@ along with this program. If not, see . // LED // ----------------------------------------------------------------------------- #define NCP5623_ADDR 0x38 +#define LP5562_ADDR 0x30 // ----------------------------------------------------------------------------- // Security @@ -295,6 +296,11 @@ along with this program. If not, see . #error HW_VENDOR must be defined #endif +// Support multiple RGB LED configuration +#if defined(HAS_NCP5623) || defined(HAS_LP5562) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#define HAS_RGB_LED +#endif + // ----------------------------------------------------------------------------- // Global switches to turn off features for a minimized build // ----------------------------------------------------------------------------- diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index 4caa0f730..b88843a78 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -41,6 +41,12 @@ ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const return firstOfOrNONE(8, types); } +ScanI2C::FoundDevice ScanI2C::firstRGBLED() const +{ + ScanI2C::DeviceType types[] = {NCP5623, LP5562}; + return firstOfOrNONE(2, types); +} + ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const { return DEVICE_NONE; diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 5b6bbe629..cfa3ea9cd 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -49,6 +49,7 @@ class ScanI2C VEML7700, RCWL9620, NCP5623, + LP5562, TSL2591, OPT3001, MLX90632, @@ -121,6 +122,8 @@ class ScanI2C FoundDevice firstAccelerometer() const; + FoundDevice firstRGBLED() const; + virtual FoundDevice find(DeviceType) const; virtual bool exists(DeviceType) const; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 8b779277d..82fcda480 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -218,6 +218,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) #ifdef HAS_NCP5623 SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address); #endif +#ifdef HAS_LP5562 + SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address); +#endif #ifdef HAS_PMU SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address) #endif diff --git a/src/graphics/NomadStarLED.h b/src/graphics/NomadStarLED.h new file mode 100644 index 000000000..0633a577e --- /dev/null +++ b/src/graphics/NomadStarLED.h @@ -0,0 +1,5 @@ +#ifdef HAS_LP5562 +#include +extern LP5562 rgbw; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 05eeef2ae..4b098b3f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -602,9 +602,9 @@ void setup() * "found". */ -// Only one supported RGB LED currently -#ifdef HAS_NCP5623 - rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623); +// Two supported RGB LED currently +#ifdef HAS_RGB_LED + rgb_found = i2cScanner->firstRGBLED(); #endif #ifdef HAS_TPS65233 @@ -1270,7 +1270,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() #ifndef ARCH_ESP32 deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG; #endif -#if !defined(HAS_NCP5623) && !defined(RGBLED_RED) && !defined(HAS_NEOPIXEL) && !defined(UNPHONE) && !RAK_4631 +#if !defined(HAS_RGB_LED) && !RAK_4631 deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG; #endif diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index bbb3f90e0..dc17460f6 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -28,6 +28,10 @@ #include #endif +#ifdef HAS_LP5562 +#include +#endif + #ifdef HAS_NEOPIXEL #include #endif @@ -37,10 +41,11 @@ extern unPhone unphone; #endif -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#if defined(HAS_RGB_LED) uint8_t red = 0; uint8_t green = 0; uint8_t blue = 0; +uint8_t white = 0; uint8_t colorState = 1; uint8_t brightnessIndex = 0; uint8_t brightnessValues[] = {0, 10, 20, 30, 50, 90, 160, 170}; // blue gets multiplied by 1.5 @@ -128,15 +133,21 @@ int32_t ExternalNotificationModule::runOnce() millis()); setExternalState(2, !getExternal(2)); } -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#if defined(HAS_RGB_LED) red = (colorState & 4) ? brightnessValues[brightnessIndex] : 0; // Red enabled on colorState = 4,5,6,7 green = (colorState & 2) ? brightnessValues[brightnessIndex] : 0; // Green enabled on colorState = 2,3,6,7 blue = (colorState & 1) ? (brightnessValues[brightnessIndex] * 1.5) : 0; // Blue enabled on colorState = 1,3,5,7 + white = (colorState & 12) ? brightnessValues[brightnessIndex] : 0; #ifdef HAS_NCP5623 if (rgb_found.type == ScanI2C::NCP5623) { rgb.setColor(red, green, blue); } #endif +#ifdef HAS_LP5562 + if (rgb_found.type == ScanI2C::LP5562) { + rgbw.setColor(red, green, blue, white); + } +#endif #ifdef RGBLED_CA analogWrite(RGBLED_RED, 255 - red); // CA type needs reverse logic analogWrite(RGBLED_GREEN, 255 - green); @@ -233,11 +244,12 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on) break; } -#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) +#if defined(HAS_RGB_LED) if (!on) { red = 0; green = 0; blue = 0; + white = 0; } #endif @@ -246,6 +258,11 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on) rgb.setColor(red, green, blue); } #endif +#ifdef HAS_LP5562 + if (rgb_found.type == ScanI2C::LP5562) { + rgbw.setColor(red, green, blue, white); + } +#endif #ifdef RGBLED_CA analogWrite(RGBLED_RED, 255 - red); // CA type needs reverse logic analogWrite(RGBLED_GREEN, 255 - green); @@ -365,6 +382,12 @@ ExternalNotificationModule::ExternalNotificationModule() rgb.setCurrent(10); } #endif +#ifdef HAS_LP5562 + if (rgb_found.type == ScanI2C::LP5562) { + rgbw.begin(); + rgbw.setCurrent(20); + } +#endif #ifdef RGBLED_RED pinMode(RGBLED_RED, OUTPUT); // set up the RGB led pins pinMode(RGBLED_GREEN, OUTPUT); From 67fddcc2142bed7e6748d0a5485d4848f32856fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 05:41:36 -0500 Subject: [PATCH 010/238] Upgrade trunk (#6480) Co-authored-by: sachaw <11172820+sachaw@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 4c570c856..b89f1f835 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -12,7 +12,7 @@ lint: - trufflehog@3.88.20 - yamllint@1.37.0 - bandit@1.8.3 - - checkov@3.2.394 + - checkov@3.2.395 - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 @@ -22,7 +22,7 @@ lint: - oxipng@9.1.4 - svgo@3.3.2 - actionlint@1.7.7 - - flake8@7.1.2 + - flake8@7.2.0 - hadolint@2.12.1-beta - shfmt@3.6.0 - shellcheck@0.10.0 From ef18a9b5b5a2a756ad15009ce9cd7e0b7717d077 Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 2 Apr 2025 07:55:14 -0400 Subject: [PATCH 011/238] meshtasticd: Set available.d dir in yaml (#6481) --- bin/config-dist.yaml | 3 ++- src/platform/portduino/PortduinoGlue.cpp | 4 +++- src/platform/portduino/PortduinoGlue.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 722f80fae..9238d0e56 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -197,5 +197,6 @@ General: MaxNodes: 200 MaxMessageQueue: 100 ConfigDirectory: /etc/meshtasticd/config.d/ + AvailableDirectory: /etc/meshtasticd/available.d/ # MACAddress: AA:BB:CC:DD:EE:FF -# MACAddressSource: eth0 \ No newline at end of file +# MACAddressSource: eth0 diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index a4050e702..6d0972dc3 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -247,7 +247,7 @@ void portduinoSetup() std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl; exit(EXIT_FAILURE); } - if (loadConfig(("/etc/meshtasticd/available.d/" + product_config).c_str())) { + if (loadConfig((settingsStrings[available_directory] + product_config).c_str())) { std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl; } else { std::cerr << "autoconf: Unable to use " << product_config << " as config file for " << autoconf_product @@ -602,6 +602,8 @@ bool loadConfig(const char *configPath) settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as(""); + settingsStrings[available_directory] = + (yamlConfig["General"]["AvailableDirectory"]).as("/etc/meshtasticd/available.d/"); if ((yamlConfig["General"]["MACAddress"]).as("") != "" && (yamlConfig["General"]["MACAddressSource"]).as("") != "") { std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl; diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 4e074be71..f7239cb73 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -99,6 +99,7 @@ enum configNames { maxnodes, ascii_logs, config_directory, + available_directory, mac_address }; enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; From 594cb0cc1e94b478aac755025f0912b452aa2845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 3 Apr 2025 02:15:12 +0200 Subject: [PATCH 012/238] reinstate M1 Backlight (#6484) --- src/graphics/EInkDisplay2.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 27117641e..d2d373d24 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -128,8 +128,13 @@ bool EInkDisplay::connect() #ifdef PIN_EINK_EN // backlight power, HIGH is backlight on, LOW is off pinMode(PIN_EINK_EN, OUTPUT); +#ifdef ELECROW_ThinkNode_M1 + // ThinkNode M1 has a hardware dimmable backlight. Start enabled + digitalWrite(PIN_EINK_EN, HIGH); +#else digitalWrite(PIN_EINK_EN, LOW); #endif +#endif #if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) { From 31130fd49e732bdd813492e8155e71605275595c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 06:52:39 -0500 Subject: [PATCH 013/238] Upgrade trunk to 1.22.12 (#6487) Co-authored-by: sachaw <11172820+sachaw@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 b89f1f835..aeb0a1b43 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,6 +1,6 @@ version: 0.1 cli: - version: 1.22.11 + version: 1.22.12 plugins: sources: - id: trunk @@ -12,7 +12,7 @@ lint: - trufflehog@3.88.20 - yamllint@1.37.0 - bandit@1.8.3 - - checkov@3.2.395 + - checkov@3.2.396 - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 From 11bafae2872c244dd821ce0b6273e699f55cfae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 3 Apr 2025 16:02:46 +0200 Subject: [PATCH 014/238] update OLED library (#6489) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 010aea90f..377635873 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,7 +56,7 @@ build_flags = -Wno-missing-field-initializers monitor_speed = 115200 monitor_filters = direct lib_deps = - https://github.com/meshtastic/esp8266-oled-ssd1306/archive/e16cee124fe26490cb14880c679321ad8ac89c95.zip + https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip mathertel/OneButton@2.6.1 https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip From 1017f6af355f6e531d76578118b59bb4c9bee41b Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Thu, 3 Apr 2025 07:07:43 -0700 Subject: [PATCH 015/238] remove very long slow (#6486) --- src/DisplayFormatters.cpp | 3 --- src/mesh/RadioInterface.cpp | 5 ----- 2 files changed, 8 deletions(-) diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index 0718ffcbd..44bc0897b 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -27,9 +27,6 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: return useShortName ? "LongM" : "LongMod"; break; - case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW: - return useShortName ? "VeryL" : "VLongSlow"; - break; default: return useShortName ? "Custom" : "Invalid"; break; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 2e50c0168..86903153b 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -488,11 +488,6 @@ void RadioInterface::applyModemConfig() cr = 8; sf = 12; break; - case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW: - bw = (myRegion->wideLora) ? 203.125 : 62.5; - cr = 8; - sf = 12; - break; } } else { sf = loraConfig.spread_factor; From 06658028234b86dc9cb7055f6f57ce6fd5a417fd Mon Sep 17 00:00:00 2001 From: "Jason B. Cox" Date: Thu, 3 Apr 2025 12:17:36 -0700 Subject: [PATCH 016/238] Improve PKC unit test coverage (#6485) * Cleanup PKC unit test a bit * Add unit test coverage for encryptCurve25519 --------- Co-authored-by: Ben Meadors --- test/test_crypto/test_main.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/test/test_crypto/test_main.cpp b/test/test_crypto/test_main.cpp index ac507116c..36dc37b9d 100644 --- a/test/test_crypto/test_main.cpp +++ b/test/test_crypto/test_main.cpp @@ -110,7 +110,7 @@ void test_DH25519(void) TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 32); } -void test_PKC_Decrypt(void) +void test_PKC(void) { uint8_t private_key[32]; meshtastic_UserLite_public_key_t public_key; @@ -120,7 +120,8 @@ void test_PKC_Decrypt(void) uint8_t decrypted[128] __attribute__((__aligned__)); uint8_t expected_nonce[16]; - uint32_t fromNode; + uint32_t fromNode = 0x0929; + uint64_t packetNum = 0x13b2d662; HexToBytes(public_key.bytes, "db18fc50eea47f00251cb784819a3cf5fc361882597f589f0d7ff820e8064457"); public_key.size = 32; HexToBytes(private_key, "a00330633e63522f8a4d81ec6d9d1e6617f6c8ffd3a4c698229537d44e522277"); @@ -128,14 +129,26 @@ void test_PKC_Decrypt(void) HexToBytes(expected_decrypted, "08011204746573744800"); HexToBytes(radioBytes, "8c646d7a2909000062d6b2136b00000040df24abfcc30a17a3d9046726099e796a1c036a792b"); HexToBytes(expected_nonce, "62d6b213036a792b2909000000"); - fromNode = 0x0929; crypto->setDHPrivateKey(private_key); - // TEST_ASSERT(crypto->setDHPublicKey(public_key)); - // crypto->hash(crypto->shared_key, 32); - crypto->decryptCurve25519(fromNode, public_key, 0x13b2d662, 22, radioBytes + 16, decrypted); + + TEST_ASSERT(crypto->decryptCurve25519(fromNode, public_key, packetNum, 22, radioBytes + 16, decrypted)); TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 8); TEST_ASSERT_EQUAL_MEMORY(expected_nonce, crypto->nonce, 13); + TEST_ASSERT_EQUAL_MEMORY(expected_decrypted, decrypted, 10); + uint32_t toNode = 0; // Only impacts logging + uint8_t encrypted[128] __attribute__((__aligned__)); + TEST_ASSERT(crypto->encryptCurve25519(toNode, fromNode, public_key, packetNum, 10, decrypted, encrypted)); + TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 8); + // The extraNonce is random, so skip checking the nonce and encrypted output here + + // Copy the nonce to check it after encryption + memcpy(expected_nonce, crypto->nonce, 16); + + // Decrypt the re-encrypted bytes and check they are the same as what we expect + TEST_ASSERT(crypto->decryptCurve25519(fromNode, public_key, packetNum, 22, encrypted, decrypted)); + TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 8); + TEST_ASSERT_EQUAL_MEMORY(expected_nonce, crypto->nonce, 13); TEST_ASSERT_EQUAL_MEMORY(expected_decrypted, decrypted, 10); } @@ -178,7 +191,7 @@ void setup() RUN_TEST(test_ECB_AES256); RUN_TEST(test_DH25519); RUN_TEST(test_AES_CTR); - RUN_TEST(test_PKC_Decrypt); + RUN_TEST(test_PKC); exit(UNITY_END()); // stop unit testing } From 749410617007319e995f5014329bc5f2c31e8a9e Mon Sep 17 00:00:00 2001 From: Nasimovy Date: Thu, 3 Apr 2025 19:18:18 +0000 Subject: [PATCH 017/238] TCA8418 initial config + basic 3x4 keypad config (#6422) * TCA8418 with base config for 3x4 keypad * replaced k with uppercase K * change detection method * reflect changes #6381 --------- Co-authored-by: Ben Meadors --- src/configuration.h | 1 + src/detect/ScanI2C.cpp | 4 +- src/detect/ScanI2C.h | 3 +- src/detect/ScanI2CTwoWire.cpp | 20 +- src/input/TCA8418Keyboard.cpp | 561 ++++++++++++++++++++++++++++++++++ src/input/TCA8418Keyboard.h | 83 +++++ src/input/cardKbI2cImpl.cpp | 8 +- src/input/kbI2cBase.cpp | 68 +++++ src/input/kbI2cBase.h | 2 + src/main.cpp | 4 + 10 files changed, 742 insertions(+), 12 deletions(-) create mode 100644 src/input/TCA8418Keyboard.cpp create mode 100644 src/input/TCA8418Keyboard.h diff --git a/src/configuration.h b/src/configuration.h index ba6066896..d319ddb0a 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -152,6 +152,7 @@ along with this program. If not, see . #define MLX90614_ADDR_DEF 0x5A #define CGRADSENS_ADDR 0x66 #define LTR390UV_ADDR 0x53 +#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418 // ----------------------------------------------------------------------------- // ACCELEROMETER diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index b88843a78..5bd5c0d12 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const { - ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB}; - return firstOfOrNONE(5, types); + ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB, TCA8418KB}; + return firstOfOrNONE(6, types); } ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index cfa3ea9cd..c363db1b5 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -18,7 +18,7 @@ class ScanI2C TDECKKB, BBQ10KB, RAK14004, - PMU_AXP192_AXP2101, + PMU_AXP192_AXP2101, // has the same adress as the TCA8418KB BME_680, BME_280, BMP_280, @@ -70,6 +70,7 @@ class ScanI2C DFROBOT_RAIN, DPS310, LTR390UV, + TCA8418KB, } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 82fcda480..230271b94 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -10,11 +10,6 @@ #include "meshUtils.h" // vformat #endif -// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp -#ifndef XPOWERS_AXP192_AXP2101_ADDRESS -#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 -#endif - bool in_array(uint8_t *array, int size, uint8_t lookfor) { int i; @@ -221,8 +216,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) #ifdef HAS_LP5562 SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address); #endif -#ifdef HAS_PMU - SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address) + case XPOWERS_AXP192_AXP2101_ADDRESS: + // Do we have the axp2101/192 or the TCA8418 + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x90), 1); + if (registerValue == 0x0) { + logFoundDevice("TCA8418", (uint8_t)addr.address); + type = TCA8418KB; + } else { + logFoundDevice("AXP192/AXP2101", (uint8_t)addr.address); + type = PMU_AXP192_AXP2101; + } + break; +#ifdef HAS_LP5562 + SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address); #endif case BME_ADDR: case BME_ADDR_ALTERNATE: diff --git a/src/input/TCA8418Keyboard.cpp b/src/input/TCA8418Keyboard.cpp new file mode 100644 index 000000000..21cd7b2d5 --- /dev/null +++ b/src/input/TCA8418Keyboard.cpp @@ -0,0 +1,561 @@ +// Based on the MPR121 Keyboard and Adafruit TCA8418 library + +#include "TCA8418Keyboard.h" +#include "configuration.h" + +#include + +// REGISTERS +// #define _TCA8418_REG_RESERVED 0x00 +#define _TCA8418_REG_CFG 0x01 // Configuration register +#define _TCA8418_REG_INT_STAT 0x02 // Interrupt status +#define _TCA8418_REG_KEY_LCK_EC 0x03 // Key lock and event counter +#define _TCA8418_REG_KEY_EVENT_A 0x04 // Key event register A +#define _TCA8418_REG_KEY_EVENT_B 0x05 // Key event register B +#define _TCA8418_REG_KEY_EVENT_C 0x06 // Key event register C +#define _TCA8418_REG_KEY_EVENT_D 0x07 // Key event register D +#define _TCA8418_REG_KEY_EVENT_E 0x08 // Key event register E +#define _TCA8418_REG_KEY_EVENT_F 0x09 // Key event register F +#define _TCA8418_REG_KEY_EVENT_G 0x0A // Key event register G +#define _TCA8418_REG_KEY_EVENT_H 0x0B // Key event register H +#define _TCA8418_REG_KEY_EVENT_I 0x0C // Key event register I +#define _TCA8418_REG_KEY_EVENT_J 0x0D // Key event register J +#define _TCA8418_REG_KP_LCK_TIMER 0x0E // Keypad lock1 to lock2 timer +#define _TCA8418_REG_UNLOCK_1 0x0F // Unlock register 1 +#define _TCA8418_REG_UNLOCK_2 0x10 // Unlock register 2 +#define _TCA8418_REG_GPIO_INT_STAT_1 0x11 // GPIO interrupt status 1 +#define _TCA8418_REG_GPIO_INT_STAT_2 0x12 // GPIO interrupt status 2 +#define _TCA8418_REG_GPIO_INT_STAT_3 0x13 // GPIO interrupt status 3 +#define _TCA8418_REG_GPIO_DAT_STAT_1 0x14 // GPIO data status 1 +#define _TCA8418_REG_GPIO_DAT_STAT_2 0x15 // GPIO data status 2 +#define _TCA8418_REG_GPIO_DAT_STAT_3 0x16 // GPIO data status 3 +#define _TCA8418_REG_GPIO_DAT_OUT_1 0x17 // GPIO data out 1 +#define _TCA8418_REG_GPIO_DAT_OUT_2 0x18 // GPIO data out 2 +#define _TCA8418_REG_GPIO_DAT_OUT_3 0x19 // GPIO data out 3 +#define _TCA8418_REG_GPIO_INT_EN_1 0x1A // GPIO interrupt enable 1 +#define _TCA8418_REG_GPIO_INT_EN_2 0x1B // GPIO interrupt enable 2 +#define _TCA8418_REG_GPIO_INT_EN_3 0x1C // GPIO interrupt enable 3 +#define _TCA8418_REG_KP_GPIO_1 0x1D // Keypad/GPIO select 1 +#define _TCA8418_REG_KP_GPIO_2 0x1E // Keypad/GPIO select 2 +#define _TCA8418_REG_KP_GPIO_3 0x1F // Keypad/GPIO select 3 +#define _TCA8418_REG_GPI_EM_1 0x20 // GPI event mode 1 +#define _TCA8418_REG_GPI_EM_2 0x21 // GPI event mode 2 +#define _TCA8418_REG_GPI_EM_3 0x22 // GPI event mode 3 +#define _TCA8418_REG_GPIO_DIR_1 0x23 // GPIO data direction 1 +#define _TCA8418_REG_GPIO_DIR_2 0x24 // GPIO data direction 2 +#define _TCA8418_REG_GPIO_DIR_3 0x25 // GPIO data direction 3 +#define _TCA8418_REG_GPIO_INT_LVL_1 0x26 // GPIO edge/level detect 1 +#define _TCA8418_REG_GPIO_INT_LVL_2 0x27 // GPIO edge/level detect 2 +#define _TCA8418_REG_GPIO_INT_LVL_3 0x28 // GPIO edge/level detect 3 +#define _TCA8418_REG_DEBOUNCE_DIS_1 0x29 // Debounce disable 1 +#define _TCA8418_REG_DEBOUNCE_DIS_2 0x2A // Debounce disable 2 +#define _TCA8418_REG_DEBOUNCE_DIS_3 0x2B // Debounce disable 3 +#define _TCA8418_REG_GPIO_PULL_1 0x2C // GPIO pull-up disable 1 +#define _TCA8418_REG_GPIO_PULL_2 0x2D // GPIO pull-up disable 2 +#define _TCA8418_REG_GPIO_PULL_3 0x2E // GPIO pull-up disable 3 +// #define _TCA8418_REG_RESERVED 0x2F + +// FIELDS CONFIG REGISTER 1 +#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write +#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config +#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable +#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config +#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable +#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable +#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable +#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable + +// FIELDS INT_STAT REGISTER 2 +#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status +#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status +#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status +#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status +#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status + +// FIELDS KEY_LCK_EC REGISTER 3 +#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable +#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2 +#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1 +#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3 +#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2 +#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1 +#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0 + +// Pin IDs for matrix rows/columns +enum { + _TCA8418_ROW0, // Pin ID for row 0 + _TCA8418_ROW1, // Pin ID for row 1 + _TCA8418_ROW2, // Pin ID for row 2 + _TCA8418_ROW3, // Pin ID for row 3 + _TCA8418_ROW4, // Pin ID for row 4 + _TCA8418_ROW5, // Pin ID for row 5 + _TCA8418_ROW6, // Pin ID for row 6 + _TCA8418_ROW7, // Pin ID for row 7 + _TCA8418_COL0, // Pin ID for column 0 + _TCA8418_COL1, // Pin ID for column 1 + _TCA8418_COL2, // Pin ID for column 2 + _TCA8418_COL3, // Pin ID for column 3 + _TCA8418_COL4, // Pin ID for column 4 + _TCA8418_COL5, // Pin ID for column 5 + _TCA8418_COL6, // Pin ID for column 6 + _TCA8418_COL7, // Pin ID for column 7 + _TCA8418_COL8, // Pin ID for column 8 + _TCA8418_COL9 // Pin ID for column 9 +}; + +#define _TCA8418_COLS 3 +#define _TCA8418_ROWS 4 +#define _TCA8418_NUM_KEYS 12 + +uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7, + 9, 7, 9, 2, 2, 2}; // Num chars per key, Modulus for rotating through characters + +unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = { + {'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1 + {'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2 + {'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3 + {'4', 'g', 'h', 'i', 'G', 'H', 'I'}, // 4 + {'5', 'j', 'k', 'l', 'J', 'K', 'L'}, // 5 + {'6', 'm', 'n', 'o', 'M', 'N', 'O'}, // 6 + {'7', 'p', 'q', 'r', 's', 'P', 'Q', 'R', 'S'}, // 7 + {'8', 't', 'u', 'v', 'T', 'U', 'V'}, // 8 + {'9', 'w', 'x', 'y', 'z', 'W', 'X', 'Y', 'Z'}, // 9 + {'*', '+'}, // * + {'0', ' '}, // 0 + {'#', '@'}, // # +}; + +unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = { + _TCA8418_ESC, // 1 + _TCA8418_UP, // 2 + _TCA8418_NONE, // 3 + _TCA8418_LEFT, // 4 + _TCA8418_NONE, // 5 + _TCA8418_RIGHT, // 6 + _TCA8418_NONE, // 7 + _TCA8418_DOWN, // 8 + _TCA8418_NONE, // 9 + _TCA8418_BSP, // * + _TCA8418_NONE, // 0 + _TCA8418_NONE, // # +}; + +#define _TCA8418_LONG_PRESS_THRESHOLD 2000 +#define _TCA8418_MULTI_TAP_THRESHOLD 750 + +TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) +{ + state = Init; + last_key = -1; + next_key = -1; + should_backspace = false; + last_tap = 0L; + char_idx = 0; + tap_interval = 0; + backlight_on = true; + queue = ""; +} + +void TCA8418Keyboard::begin(uint8_t addr, TwoWire *wire) +{ + m_addr = addr; + m_wire = wire; + + m_wire->begin(); + + reset(); +} + +void TCA8418Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr) +{ + m_addr = addr; + m_wire = nullptr; + writeCallback = w; + readCallback = r; + reset(); +} + +void TCA8418Keyboard::reset() +{ + LOG_DEBUG("TCA8418 Reset"); + // GPIO + // set default all GIO pins to INPUT + writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00); + writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00); + // Set COL9 as GPIO output + writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02); + // Switch off keyboard backlight (COL9 = LOW) + writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00); + + // add all pins to key events + writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF); + writeRegister(_TCA8418_REG_GPI_EM_2, 0xFF); + writeRegister(_TCA8418_REG_GPI_EM_3, 0xFF); + + // set all pins to FALLING interrupts + writeRegister(_TCA8418_REG_GPIO_INT_LVL_1, 0x00); + writeRegister(_TCA8418_REG_GPIO_INT_LVL_2, 0x00); + writeRegister(_TCA8418_REG_GPIO_INT_LVL_3, 0x00); + + // add all pins to interrupts + writeRegister(_TCA8418_REG_GPIO_INT_EN_1, 0xFF); + writeRegister(_TCA8418_REG_GPIO_INT_EN_2, 0xFF); + writeRegister(_TCA8418_REG_GPIO_INT_EN_3, 0xFF); + + // Set keyboard matrix size + matrix(_TCA8418_ROWS, _TCA8418_COLS); + enableDebounce(); + flush(); + state = Idle; +} + +bool TCA8418Keyboard::matrix(uint8_t rows, uint8_t columns) +{ + if ((rows > 8) || (columns > 10)) + return false; + + // Skip zero size matrix + if ((rows != 0) && (columns != 0)) { + // Setup the keypad matrix. + uint8_t mask = 0x00; + for (int r = 0; r < rows; r++) { + mask <<= 1; + mask |= 1; + } + writeRegister(_TCA8418_REG_KP_GPIO_1, mask); + + mask = 0x00; + for (int c = 0; c < columns && c < 8; c++) { + mask <<= 1; + mask |= 1; + } + writeRegister(_TCA8418_REG_KP_GPIO_2, mask); + + if (columns > 8) { + if (columns == 9) + mask = 0x01; + else + mask = 0x03; + writeRegister(_TCA8418_REG_KP_GPIO_3, mask); + } + } + + return true; +} + +uint8_t TCA8418Keyboard::keyCount() const +{ + uint8_t eventCount = readRegister(_TCA8418_REG_KEY_LCK_EC); + eventCount &= 0x0F; // lower 4 bits only + return eventCount; +} + +bool TCA8418Keyboard::hasEvent() +{ + return queue.length() > 0; +} + +void TCA8418Keyboard::queueEvent(char next) +{ + if (next == _TCA8418_NONE) { + return; + } + queue.concat(next); +} + +char TCA8418Keyboard::dequeueEvent() +{ + if (queue.length() < 1) { + return _TCA8418_NONE; + } + char next = queue.charAt(0); + queue.remove(0, 1); + return next; +} + +void TCA8418Keyboard::trigger() +{ + if (keyCount() == 0) { + return; + } + if (state != Init) { + // Read the key register + uint8_t k = readRegister(_TCA8418_REG_KEY_EVENT_A); + uint8_t key = k & 0x7F; + if (k & 0x80) { + if (state == Idle) + pressed(key); + return; + } else { + if (state == Held) { + released(); + } + state = Idle; + return; + } + } else { + reset(); + } +} + +void TCA8418Keyboard::pressed(uint8_t key) +{ + if (state == Init || state == Busy) { + return; + } + uint8_t next_key = 0; + int row = (key - 1) / 10; + int col = (key - 1) % 10; + + if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) { + return; // Invalid key + } + + // Compute key index based on dynamic row/column + next_key = row * _TCA8418_COLS + col; + + // LOG_DEBUG("TCA8418: Key %u -> Next Key %u", key, next_key); + + state = Held; + uint32_t now = millis(); + tap_interval = now - last_tap; + if (tap_interval < 0) { + // Long running, millis has overflowed. + last_tap = 0; + state = Busy; + return; + } + + // Check if the key is the same as the last one or if the time interval has passed + if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) { + char_idx = 0; // Reset char index if new key or long press + should_backspace = false; // dont backspace on new key + } else { + char_idx += 1; // Cycle through characters if same key pressed + should_backspace = true; // allow backspace on same key + } + + // Store the current key as the last key + last_key = next_key; + last_tap = now; +} + +void TCA8418Keyboard::released() +{ + if (state != Held) { + return; + } + + if (last_key < 0 || last_key > _TCA8418_NUM_KEYS) { // reset to idle if last_key out of bounds + last_key = -1; + state = Idle; + return; + } + uint32_t now = millis(); + int32_t held_interval = now - last_tap; + last_tap = now; + if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) { + queueEvent(_TCA8418_BSP); + } + if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) { + queueEvent(TCA8418LongPressMap[last_key]); + // LOG_DEBUG("Long Press Key: %i Map: %i", last_key, TCA8418LongPressMap[last_key]); + } else { + queueEvent(TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]); + // LOG_DEBUG("Key Press: %i Index:%i if %i Map: %c", last_key, char_idx, TCA8418TapMod[last_key], + // TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]); + } +} + +uint8_t TCA8418Keyboard::flush() +{ + // Flush key events + uint8_t count = 0; + while (readRegister(_TCA8418_REG_KEY_EVENT_A) != 0) + count++; + // Flush gpio events + readRegister(_TCA8418_REG_GPIO_INT_STAT_1); + readRegister(_TCA8418_REG_GPIO_INT_STAT_2); + readRegister(_TCA8418_REG_GPIO_INT_STAT_3); + // Clear INT_STAT register + writeRegister(_TCA8418_REG_INT_STAT, 3); + return count; +} + +uint8_t TCA8418Keyboard::digitalRead(uint8_t pinnum) const +{ + if (pinnum > _TCA8418_COL9) + return 0xFF; + + uint8_t reg = _TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8; + uint8_t mask = (1 << (pinnum % 8)); + + // Level 0 = low other = high + uint8_t value = readRegister(reg); + if (value & mask) + return HIGH; + return LOW; +} + +bool TCA8418Keyboard::digitalWrite(uint8_t pinnum, uint8_t level) +{ + if (pinnum > _TCA8418_COL9) + return false; + + uint8_t reg = _TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8; + uint8_t mask = (1 << (pinnum % 8)); + + // Level 0 = low other = high + uint8_t value = readRegister(reg); + if (level == LOW) + value &= ~mask; + else + value |= mask; + writeRegister(reg, value); + return true; +} + +bool TCA8418Keyboard::pinMode(uint8_t pinnum, uint8_t mode) +{ + if (pinnum > _TCA8418_COL9) + return false; + + uint8_t idx = pinnum / 8; + uint8_t reg = _TCA8418_REG_GPIO_DIR_1 + idx; + uint8_t mask = (1 << (pinnum % 8)); + + // Mode 0 = input 1 = output + uint8_t value = readRegister(reg); + if (mode == OUTPUT) + value |= mask; + else + value &= ~mask; + writeRegister(reg, value); + + // Pullup 0 = enabled 1 = disabled + reg = _TCA8418_REG_GPIO_PULL_1 + idx; + value = readRegister(reg); + if (mode == INPUT_PULLUP) + value &= ~mask; + else + value |= mask; + writeRegister(reg, value); + + return true; +} + +bool TCA8418Keyboard::pinIRQMode(uint8_t pinnum, uint8_t mode) +{ + if (pinnum > _TCA8418_COL9) + return false; + if ((mode != RISING) && (mode != FALLING)) + return false; + + // Mode 0 = falling 1 = rising + uint8_t idx = pinnum / 8; + uint8_t reg = _TCA8418_REG_GPIO_INT_LVL_1 + idx; + uint8_t mask = (1 << (pinnum % 8)); + + uint8_t value = readRegister(reg); + if (mode == RISING) + value |= mask; + else + value &= ~mask; + writeRegister(reg, value); + + // Enable interrupt + reg = _TCA8418_REG_GPIO_INT_EN_1 + idx; + value = readRegister(reg); + value |= mask; + writeRegister(reg, value); + + return true; +} + +void TCA8418Keyboard::enableInterrupts() +{ + uint8_t value = readRegister(_TCA8418_REG_CFG); + value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN); + writeRegister(_TCA8418_REG_CFG, value); +}; + +void TCA8418Keyboard::disableInterrupts() +{ + uint8_t value = readRegister(_TCA8418_REG_CFG); + value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN); + writeRegister(_TCA8418_REG_CFG, value); +}; + +void TCA8418Keyboard::enableMatrixOverflow() +{ + uint8_t value = readRegister(_TCA8418_REG_CFG); + value |= _TCA8418_REG_CFG_OVR_FLOW_M; + writeRegister(_TCA8418_REG_CFG, value); +}; + +void TCA8418Keyboard::disableMatrixOverflow() +{ + uint8_t value = readRegister(_TCA8418_REG_CFG); + value &= ~_TCA8418_REG_CFG_OVR_FLOW_M; + writeRegister(_TCA8418_REG_CFG, value); +}; + +void TCA8418Keyboard::enableDebounce() +{ + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0x00); + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0x00); + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0x00); +} + +void TCA8418Keyboard::disableDebounce() +{ + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0xFF); + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0xFF); + writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0xFF); +} + +void TCA8418Keyboard::setBacklight(bool on) +{ + if (on) { + digitalWrite(_TCA8418_COL9, HIGH); + } else { + digitalWrite(_TCA8418_COL9, LOW); + } +} + +uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const +{ + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(reg); + m_wire->endTransmission(); + + m_wire->requestFrom(m_addr, (uint8_t)1); + if (m_wire->available() < 1) + return 0; + + return m_wire->read(); + } + if (readCallback) { + uint8_t data; + readCallback(m_addr, reg, &data, 1); + return data; + } + return 0; +} + +void TCA8418Keyboard::writeRegister(uint8_t reg, uint8_t value) +{ + uint8_t data[2]; + data[0] = reg; + data[1] = value; + + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(data, sizeof(uint8_t) * 2); + m_wire->endTransmission(); + } + if (writeCallback) { + writeCallback(m_addr, data[0], &(data[1]), 1); + } +} \ No newline at end of file diff --git a/src/input/TCA8418Keyboard.h b/src/input/TCA8418Keyboard.h new file mode 100644 index 000000000..c7f3c1f28 --- /dev/null +++ b/src/input/TCA8418Keyboard.h @@ -0,0 +1,83 @@ +// Based on the MPR121 Keyboard and Adafruit TCA8418 library +#include "configuration.h" +#include + +#define _TCA8418_NONE 0x00 +#define _TCA8418_REBOOT 0x90 +#define _TCA8418_LEFT 0xb4 +#define _TCA8418_UP 0xb5 +#define _TCA8418_DOWN 0xb6 +#define _TCA8418_RIGHT 0xb7 +#define _TCA8418_ESC 0x1b +#define _TCA8418_BSP 0x08 +#define _TCA8418_SELECT 0x0d + +class TCA8418Keyboard +{ + public: + typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); + + enum KeyState { Init = 0, Idle, Held, Busy }; + + KeyState state; + int8_t last_key; + int8_t next_key; + bool should_backspace; + uint32_t last_tap; + uint8_t char_idx; + int32_t tap_interval; + bool backlight_on; + + String queue; + + TCA8418Keyboard(); + + void begin(uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS, TwoWire *wire = &Wire); + void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS); + + void reset(void); + // Configure the size of the keypad. + // All other rows and columns are set as inputs. + bool matrix(uint8_t rows, uint8_t columns); + + // Flush all events in the FIFO buffer + GPIO events. + uint8_t flush(void); + + // Key events available in the internal FIFO buffer. + uint8_t keyCount(void) const; + + void trigger(void); + void pressed(uint8_t key); + void released(void); + bool hasEvent(void); + char dequeueEvent(void); + void queueEvent(char); + + uint8_t digitalRead(uint8_t pinnum) const; + bool digitalWrite(uint8_t pinnum, uint8_t level); + bool pinMode(uint8_t pinnum, uint8_t mode); + bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING + + // enable / disable interrupts for matrix and GPI pins + void enableInterrupts(); + void disableInterrupts(); + + // ignore key events when FIFO buffer is full or not. + void enableMatrixOverflow(); + void disableMatrixOverflow(); + + // debounce keys. + void enableDebounce(); + void disableDebounce(); + + void setBacklight(bool on); + + uint8_t readRegister(uint8_t reg) const; + void writeRegister(uint8_t reg, uint8_t value); + + private: + TwoWire *m_wire; + uint8_t m_addr; + i2c_com_fptr_t readCallback; + i2c_com_fptr_t writeCallback; +}; diff --git a/src/input/cardKbI2cImpl.cpp b/src/input/cardKbI2cImpl.cpp index eb9b07d6e..21ecf381a 100644 --- a/src/input/cardKbI2cImpl.cpp +++ b/src/input/cardKbI2cImpl.cpp @@ -12,8 +12,8 @@ void CardKbI2cImpl::init() #if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN) if (cardkb_found.address == 0x00) { LOG_DEBUG("Rescan for I2C keyboard"); - uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR}; - uint8_t i2caddr_asize = 4; + uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR, XPOWERS_AXP192_AXP2101_ADDRESS}; + uint8_t i2caddr_asize = 5; auto i2cScanner = std::unique_ptr(new ScanI2CTwoWire()); #if WIRE_INTERFACES_COUNT == 2 @@ -43,6 +43,10 @@ void CardKbI2cImpl::init() // assign an arbitrary value to distinguish from other models kb_model = 0x37; break; + case ScanI2C::DeviceType::TCA8418KB: + // assign an arbitrary value to distinguish from other models + kb_model = 0x84; + break; default: // use this as default since it's also just zero LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type); diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index 9b1a27745..70e9e4365 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -43,6 +43,9 @@ int32_t KbI2cBase::runOnce() if (cardkb_found.address == MPR121_KB_ADDR) { MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1); } + if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) { + TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire1); + } break; #endif case ScanI2C::WIRE: @@ -55,6 +58,9 @@ int32_t KbI2cBase::runOnce() if (cardkb_found.address == MPR121_KB_ADDR) { MPRkeyboard.begin(MPR121_KB_ADDR, &Wire); } + if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) { + TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire); + } break; case ScanI2C::NO_I2C: default: @@ -226,6 +232,68 @@ int32_t KbI2cBase::runOnce() } break; } + case 0x84: { // Adafruit TCA8418 + TCAKeyboard.trigger(); + InputEvent e; + while (TCAKeyboard.hasEvent()) { + char nextEvent = TCAKeyboard.dequeueEvent(); + e.inputEvent = ANYKEY; + e.kbchar = 0x00; + e.source = this->_originName; + switch (nextEvent) { + case _TCA8418_NONE: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.kbchar = 0x00; + break; + case _TCA8418_REBOOT: + e.inputEvent = ANYKEY; + e.kbchar = INPUT_BROKER_MSG_REBOOT; + break; + case _TCA8418_LEFT: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; + e.kbchar = 0x00; + break; + case _TCA8418_UP: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; + e.kbchar = 0x00; + break; + case _TCA8418_DOWN: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; + e.kbchar = 0x00; + break; + case _TCA8418_RIGHT: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; + e.kbchar = 0x00; + break; + case _TCA8418_BSP: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK; + e.kbchar = 0x08; + break; + case _TCA8418_SELECT: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; + e.kbchar = 0x0d; + break; + case _TCA8418_ESC: + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL; + e.kbchar = 0x1b; + break; + default: + if (nextEvent > 127) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.kbchar = 0x00; + break; + } + e.inputEvent = ANYKEY; + e.kbchar = nextEvent; + break; + } + if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) { + LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar); + this->notifyObservers(&e); + } + } + break; + } case 0x02: { // RAK14004 uint8_t rDataBuf[8] = {0}; diff --git a/src/input/kbI2cBase.h b/src/input/kbI2cBase.h index dc2414fc0..8193433fe 100644 --- a/src/input/kbI2cBase.h +++ b/src/input/kbI2cBase.h @@ -3,6 +3,7 @@ #include "BBQ10Keyboard.h" #include "InputBroker.h" #include "MPR121Keyboard.h" +#include "TCA8418Keyboard.h" #include "Wire.h" #include "concurrency/OSThread.h" @@ -21,5 +22,6 @@ class KbI2cBase : public Observable, public concurrency::OST BBQ10Keyboard Q10keyboard; MPR121Keyboard MPRkeyboard; + TCA8418Keyboard TCAKeyboard; bool is_sym = false; }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4b098b3f3..fd65830ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -587,6 +587,10 @@ void setup() // assign an arbitrary value to distinguish from other models kb_model = 0x37; break; + case ScanI2C::DeviceType::TCA8418KB: + // assign an arbitrary value to distinguish from other models + kb_model = 0x84; + break; default: // use this as default since it's also just zero LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type); From 4dfba503044d7d77bdd40f151aa95e6df80cb8bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:23:44 -0500 Subject: [PATCH 018/238] [create-pull-request] automated change (#6490) 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 484d002a5..13a3e5dce 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 484d002a52bc20fa9f91ebf1b216d585c5f93a1b +Subproject commit 13a3e5dcee25a2d2d4f1fbaba4c091c66d698ca5 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index defaaad28..191f9e121 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -237,6 +237,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_ETH_ELITE = 91, /* Heltec HRI-3621 industrial probe */ meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92, + /* Reserved Fried Chicken ID for future use */ + meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 01102754945ac2bc8d52062fcb2b4a446ea35b35 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 4 Apr 2025 04:59:31 -0500 Subject: [PATCH 019/238] Revert "Try-fix ESP32 wifi disconnects (#6363)" (#6493) This reverts commit a902776e578bc2574c95eff8c13402e8cb5f5fbd. --- src/mesh/wifi/WiFiAPClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index e050c2057..4d0b74f7c 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -163,7 +163,7 @@ static int32_t reconnectWiFi() delay(5000); if (!WiFi.isConnected()) { -#ifdef ARCH_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32C3 WiFi.mode(WIFI_MODE_NULL); WiFi.useStaticBuffers(true); WiFi.mode(WIFI_STA); From 25237a15ff68d482c16369b4b802a2931b733ab2 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 4 Apr 2025 23:53:54 +1300 Subject: [PATCH 020/238] feat: menu entry to send adhoc-ping (#6492) --- .../InkHUD/Applets/System/Menu/MenuAction.h | 3 +-- .../InkHUD/Applets/System/Menu/MenuApplet.cpp | 21 ++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuAction.h b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuAction.h index 4f8205647..f162aa385 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuAction.h +++ b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuAction.h @@ -18,8 +18,7 @@ namespace NicheGraphics::InkHUD enum MenuAction { NO_ACTION, - SEND_NODEINFO, - SEND_POSITION, + SEND_PING, SHUTDOWN, NEXT_TILE, TOGGLE_BACKLIGHT, diff --git a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp index f59579230..5ca9692c8 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp @@ -4,6 +4,7 @@ #include "RTC.h" +#include "MeshService.h" #include "airtime.h" #include "main.h" #include "power.h" @@ -144,6 +145,14 @@ void InkHUD::MenuApplet::execute(MenuItem item) inkhud->nextTile(); break; + case SEND_PING: + service->refreshLocalMeshNode(); + service->trySendPosition(NODENUM_BROADCAST, true); + + // Force the next refresh to use FULL, to protect the display, as some users will probably spam this button + inkhud->forceUpdate(Drivers::EInk::UpdateTypes::FULL); + break; + case ROTATE: inkhud->rotate(); break; @@ -242,7 +251,7 @@ void InkHUD::MenuApplet::showPage(MenuPage page) if (settings->optionalMenuItems.nextTile && settings->userTiles.count > 1) items.push_back(MenuItem("Next Tile", MenuAction::NEXT_TILE, MenuPage::ROOT)); // Only if multiple applets shown - // items.push_back(MenuItem("Send", MenuPage::SEND)); // TODO + items.push_back(MenuItem("Send", MenuPage::SEND)); items.push_back(MenuItem("Options", MenuPage::OPTIONS)); // items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN)); @@ -250,9 +259,8 @@ void InkHUD::MenuApplet::showPage(MenuPage page) break; case SEND: - items.push_back(MenuItem("Send Message", MenuPage::EXIT)); - items.push_back(MenuItem("Send NodeInfo", MenuAction::SEND_NODEINFO)); - items.push_back(MenuItem("Send Position", MenuAction::SEND_POSITION)); + items.push_back(MenuItem("Ping", MenuAction::SEND_PING, MenuPage::EXIT)); + // Todo: canned messages items.push_back(MenuItem("Exit", MenuPage::EXIT)); break; @@ -389,11 +397,14 @@ void InkHUD::MenuApplet::onRender() // Center-line for the text int16_t center = itemT + (itemH / 2); + // Box, if currently selected if (cursorShown && i == cursor) drawRect(itemL, itemT, itemW, itemH, BLACK); + + // Item's text printAt(itemL + X(padding), center, item.label, LEFT, MIDDLE); - // Testing only: circle instead of check box + // Checkbox, if relevant if (item.checkState) { const uint16_t cbWH = fontSmall.lineHeight(); // Checkbox: width / height const int16_t cbL = itemR - X(padding) - cbWH; // Checkbox: left From 1b33189fe62d57b067b98facd84656531903457b Mon Sep 17 00:00:00 2001 From: Nasimovy Date: Fri, 4 Apr 2025 13:35:15 +0000 Subject: [PATCH 021/238] remove duplicate HAS_LP5562 introduced by #6422 (#6494) --- src/detect/ScanI2CTwoWire.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 230271b94..9781cbf56 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -227,9 +227,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) type = PMU_AXP192_AXP2101; } break; -#ifdef HAS_LP5562 - SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address); -#endif case BME_ADDR: case BME_ADDR_ALTERNATE: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID From 56eb0c08b288b5b549399a5f441f07c51bc8d459 Mon Sep 17 00:00:00 2001 From: Chris LaFlash Date: Sat, 5 Apr 2025 20:49:01 -0700 Subject: [PATCH 022/238] Add support for Quectel-L96, a MT3333 module (#6498) --- src/gps/GPS.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 41a2ff980..a2e7ebbc7 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1206,7 +1206,8 @@ GnssModel_t GPS::probe(int serialSpeed) delay(20); std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, - {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}}; + {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, + {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}}; PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500); uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00}; From 2125c039745aa06248b2e76819303a9c99c4de63 Mon Sep 17 00:00:00 2001 From: Nasimovy Date: Mon, 7 Apr 2025 01:27:46 +0000 Subject: [PATCH 023/238] Fix for PSRAM detection on ESP32-S3R8 and t-beam (#6504) * remove duplicate HAS_LP5562 introduced by #6422 * T190 PSRAM fix * all the boards with a ESP32-S3R8 * T-beam V1.1 PSRAM --- boards/heltec_vision_master_e213.json | 4 +++- boards/heltec_vision_master_e290.json | 4 +++- boards/heltec_vision_master_t190.json | 4 +++- boards/seeed-sensecap-indicator.json | 1 + boards/seeed-xiao-s3.json | 1 + boards/t-watch-s3.json | 1 + variants/tbeam/platformio.ini | 2 ++ 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/boards/heltec_vision_master_e213.json b/boards/heltec_vision_master_e213.json index bf5fe15ad..152515cf3 100644 --- a/boards/heltec_vision_master_e213.json +++ b/boards/heltec_vision_master_e213.json @@ -2,7 +2,8 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ @@ -15,6 +16,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type": "opi", "hwids": [ ["0x303A", "0x1001"], ["0x303A", "0x0002"] diff --git a/boards/heltec_vision_master_e290.json b/boards/heltec_vision_master_e290.json index 70f7d5f02..b7cbac878 100644 --- a/boards/heltec_vision_master_e290.json +++ b/boards/heltec_vision_master_e290.json @@ -2,7 +2,8 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ @@ -15,6 +16,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type": "opi", "hwids": [ ["0x303A", "0x1001"], ["0x303A", "0x0002"] diff --git a/boards/heltec_vision_master_t190.json b/boards/heltec_vision_master_t190.json index 341e70218..440f76ad0 100644 --- a/boards/heltec_vision_master_t190.json +++ b/boards/heltec_vision_master_t190.json @@ -2,7 +2,8 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ @@ -15,6 +16,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type": "opi", "hwids": [ ["0x303A", "0x1001"], ["0x303A", "0x0002"] diff --git a/boards/seeed-sensecap-indicator.json b/boards/seeed-sensecap-indicator.json index 0a02fc882..03bff35b5 100644 --- a/boards/seeed-sensecap-indicator.json +++ b/boards/seeed-sensecap-indicator.json @@ -18,6 +18,7 @@ "f_boot": "120000000L", "boot": "qio", "flash_mode": "qio", + "psram_type": "opi", "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32s3", "variant": "esp32s3" diff --git a/boards/seeed-xiao-s3.json b/boards/seeed-xiao-s3.json index 0b7b432a0..6981085dd 100644 --- a/boards/seeed-xiao-s3.json +++ b/boards/seeed-xiao-s3.json @@ -15,6 +15,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type": "opi", "hwids": [["0x2886", "0x0059"]], "mcu": "esp32s3", "variant": "seeed-xiao-s3" diff --git a/boards/t-watch-s3.json b/boards/t-watch-s3.json index 5d4afd322..51bb7cf4b 100644 --- a/boards/t-watch-s3.json +++ b/boards/t-watch-s3.json @@ -16,6 +16,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "psram_type": "opi", "hwids": [ ["0x303A", "0x1001"], ["0x303A", "0x0002"] diff --git a/variants/tbeam/platformio.ini b/variants/tbeam/platformio.ini index 85e66c2dd..9049836a3 100644 --- a/variants/tbeam/platformio.ini +++ b/variants/tbeam/platformio.ini @@ -8,4 +8,6 @@ lib_deps = build_flags = ${esp32_base.build_flags} -D TBEAM_V10 -I variants/tbeam -DGPS_POWER_TOGGLE ; comment this line to disable double press function on the user button to turn off gps entirely. + -DBOARD_HAS_PSRAM + -mfix-esp32-psram-cache-issue upload_speed = 921600 \ No newline at end of file From 5a9d70b445930dec9e7175831e79c66d2f203f84 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:39:45 +0200 Subject: [PATCH 024/238] Upgrade trunk (#6509) Co-authored-by: sachaw <11172820+sachaw@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 aeb0a1b43..608045e45 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,14 +9,14 @@ plugins: lint: enabled: - prettier@3.5.3 - - trufflehog@3.88.20 + - trufflehog@3.88.22 - yamllint@1.37.0 - bandit@1.8.3 - checkov@3.2.396 - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 - - ruff@0.11.2 + - ruff@0.11.3 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.4 From 860e8eca5aab7a4586891b3218420624f7b30c31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:51:05 +0200 Subject: [PATCH 025/238] [create-pull-request] automated change (#6511) Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 14 ++++++++------ src/mesh/generated/meshtastic/telemetry.pb.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/protobufs b/protobufs index 13a3e5dce..5a5ab103d 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 13a3e5dcee25a2d2d4f1fbaba4c091c66d698ca5 +Subproject commit 5a5ab103d2f6aa071fca29417475681a2cec5dcf diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 848f8df86..edcd7b41c 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -180,14 +180,16 @@ typedef enum _meshtastic_Config_DisplayConfig_DisplayUnits { /* Override OLED outo detect with this if it fails. */ typedef enum _meshtastic_Config_DisplayConfig_OledType { - /* Default / Auto */ + /* Default / Autodetect */ meshtastic_Config_DisplayConfig_OledType_OLED_AUTO = 0, - /* Default / Auto */ + /* Default / Autodetect */ meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306 = 1, - /* Default / Auto */ + /* Default / Autodetect */ meshtastic_Config_DisplayConfig_OledType_OLED_SH1106 = 2, /* Can not be auto detected but set by proto. Used for 128x128 screens */ - meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3 + meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3, + /* Can not be auto detected but set by proto. Used for 128x64 screens */ + meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 = 4 } meshtastic_Config_DisplayConfig_OledType; typedef enum _meshtastic_Config_DisplayConfig_DisplayMode { @@ -639,8 +641,8 @@ extern "C" { #define _meshtastic_Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayUnits)(meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL+1)) #define _meshtastic_Config_DisplayConfig_OledType_MIN meshtastic_Config_DisplayConfig_OledType_OLED_AUTO -#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 -#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107+1)) +#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 +#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64+1)) #define _meshtastic_Config_DisplayConfig_DisplayMode_MIN meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT #define _meshtastic_Config_DisplayConfig_DisplayMode_MAX meshtastic_Config_DisplayConfig_DisplayMode_COLOR diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 69cdd33fe..dcc511ea6 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -242,7 +242,7 @@ typedef struct _meshtastic_AirQualityMetrics { /* 10.0um Particle Count */ bool has_particles_100um; uint32_t particles_100um; - /* 10.0um Particle Count */ + /* CO2 concentration in ppm */ bool has_co2; uint32_t co2; } meshtastic_AirQualityMetrics; From 606abfc1165711f57b12ee0a022660082ec18f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Mon, 7 Apr 2025 12:46:22 +0200 Subject: [PATCH 026/238] Fix several features of M1 and M2 (i know what the 7 is now ...) (#6507) * Fix several features of M1 and M2 (i know what the 7 is now ...) * 'THe' should be 'The'. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove floating definition --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ben Meadors --- src/ButtonThread.cpp | 138 ++++++++++++------------ src/ButtonThread.h | 13 +-- src/Power.cpp | 29 +++-- src/gps/GPS.cpp | 46 ++++++++ src/graphics/Screen.cpp | 3 + src/main.cpp | 70 ++++++++++-- src/mesh/NodeDB.cpp | 9 ++ src/platform/esp32/main-esp32.cpp | 5 +- src/platform/nrf52/main-nrf52.cpp | 6 +- src/power.h | 5 - variants/ELECROW-ThinkNode-M1/variant.h | 10 +- variants/ELECROW-ThinkNode-M2/variant.h | 11 +- 12 files changed, 221 insertions(+), 124 deletions(-) diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 2363f804c..375029c99 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -116,46 +116,55 @@ ButtonThread::ButtonThread() : OSThread("Button") #endif } +void ButtonThread::switchPage() +{ +#ifdef BUTTON_PIN +#if !defined(USERPREFS_BUTTON_PIN) + if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != + moduleConfig.canned_message.inputbroker_pin_press) || + !(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) || + !moduleConfig.canned_message.enabled) { + powerFSM.trigger(EVENT_PRESS); + } +#endif +#if defined(USERPREFS_BUTTON_PIN) + if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) != + moduleConfig.canned_message.inputbroker_pin_press) || + !(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) || + !moduleConfig.canned_message.enabled) { + powerFSM.trigger(EVENT_PRESS); + } +#endif + +#endif +#if defined(ARCH_PORTDUINO) + if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) && + (settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) || + !moduleConfig.canned_message.enabled) { + powerFSM.trigger(EVENT_PRESS); + } +#endif +} + +void ButtonThread::sendAdHocPosition() +{ + service->refreshLocalMeshNode(); + auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true); + if (screen) { + if (sentPosition) + screen->print("Sent ad-hoc position\n"); + else + screen->print("Sent ad-hoc nodeinfo\n"); + screen->forceDisplay(true); // Force a new UI frame, then force an EInk update + } +} + int32_t ButtonThread::runOnce() { // If the button is pressed we suppress CPU sleep until release canSleep = true; // Assume we should not keep the board awake #if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN) - // #if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2) - // buzzer_updata(); - // if (buttonPressed) { - // buttonPressed = false; // 清除标志 - // LOG_INFO("PIN_BUTTON2 pressed!"); // 串口打印信息 - // // off_currentTime = millis(); - // while (digitalRead(PIN_BUTTON2) == HIGH) { - // if (cont < 40) { - // // unsigned long currentTime = millis(); // 获取当前时间 - // // if (currentTime - off_currentTime >= 1000) { - // cont++; - // // off_currentTime = currentTime; - // // } - // delay(100); - // } else { - - // currentState = OFF; - // isBuzzing = false; - // cont = 0; - // BEEP_STATE = false; - // analogWrite(M2_buzzer, 0); - // pinMode(M2_buzzer, INPUT); - // screen->setOn(false); - // cont = 0; - // LOG_INFO("GGGGGGGGGGGGGGGGGGGGGGGGG"); - // pinMode(1, OUTPUT); - // digitalWrite(1, LOW); - // pinMode(6, OUTPUT); - // digitalWrite(6, LOW); - // } - // } - // } - - // #endif userButton.tick(); canSleep &= userButton.isIdle(); #elif defined(ARCH_PORTDUINO) @@ -180,32 +189,27 @@ int32_t ButtonThread::runOnce() // If a nag notification is running, stop it and prevent other actions if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) { externalNotificationModule->stopNow(); - return 50; - } -#ifdef BUTTON_PIN -#if !defined(USERPREFS_BUTTON_PIN) - if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != -#endif -#if defined(USERPREFS_BUTTON_PIN) - if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) != -#endif - moduleConfig.canned_message.inputbroker_pin_press) || - !(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) || - !moduleConfig.canned_message.enabled) { - powerFSM.trigger(EVENT_PRESS); - } -#endif -#if defined(ARCH_PORTDUINO) - if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) && - (settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) || - !moduleConfig.canned_message.enabled) { - powerFSM.trigger(EVENT_PRESS); + break; } +#ifdef ELECROW_ThinkNode_M1 + sendAdHocPosition(); + break; #endif + switchPage(); break; } case BUTTON_EVENT_PRESSED_SCREEN: { + LOG_BUTTON("AltPress!"); +#ifdef ELECROW_ThinkNode_M1 + // If a nag notification is running, stop it and prevent other actions + if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) { + externalNotificationModule->stopNow(); + break; + } + switchPage(); + break; +#endif // turn screen on or off screen_flag = !screen_flag; if (screen) @@ -215,22 +219,18 @@ int32_t ButtonThread::runOnce() case BUTTON_EVENT_DOUBLE_PRESSED: { LOG_BUTTON("Double press!"); - service->refreshLocalMeshNode(); - auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true); - if (screen) { - if (sentPosition) - screen->print("Sent ad-hoc position\n"); - else - screen->print("Sent ad-hoc nodeinfo\n"); - screen->forceDisplay(true); // Force a new UI frame, then force an EInk update - } +#ifdef ELECROW_ThinkNode_M1 + digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); + break; +#endif + sendAdHocPosition(); break; } case BUTTON_EVENT_MULTI_PRESSED: { LOG_BUTTON("Mulitipress! %hux", multipressClickCount); switch (multipressClickCount) { -#if HAS_GPS +#if HAS_GPS && !defined(ELECROW_ThinkNode_M1) // 3 clicks: toggle GPS case 3: if (!config.device.disable_triple_click && (gps != nullptr)) { @@ -239,17 +239,17 @@ int32_t ButtonThread::runOnce() screen->forceDisplay(true); // Force a new UI frame, then force an EInk update } break; -#elif defined(ELECROW_ThinkNode_M2) +#elif defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2) case 3: LOG_INFO("3 clicks: toggle buzzer"); buzzer_flag = !buzzer_flag; - if (buzzer_flag) { - playBeep(); - } + if (!buzzer_flag) + noTone(PIN_BUZZER); break; + #endif -#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo +#if defined(USE_EINK) && defined(PIN_EINK_EN) && !defined(ELECROW_ThinkNode_M1) // i.e. T-Echo // 4 clicks: toggle backlight case 4: digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); diff --git a/src/ButtonThread.h b/src/ButtonThread.h index a8f1f77c3..3af700dd0 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -37,6 +37,9 @@ class ButtonThread : public concurrency::OSThread void attachButtonInterrupts(); void detachButtonInterrupts(); void storeClickCount(); + bool isBuzzing() { return buzzer_flag; } + void setScreenFlag(bool flag) { screen_flag = flag; } + bool getScreenFlag() { return screen_flag; } // Disconnect and reconnect interrupts for light sleep #ifdef ARCH_ESP32 @@ -72,14 +75,12 @@ class ButtonThread : public concurrency::OSThread static void wakeOnIrq(int irq, int mode); + static void sendAdHocPosition(); + static void switchPage(); + // IRQ callbacks static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; } - static void userButtonPressedScreen() - { - if (millis() > c_holdOffTime) { - btnEvent = BUTTON_EVENT_PRESSED_SCREEN; - } - } + static void userButtonPressedScreen() { btnEvent = BUTTON_EVENT_PRESSED_SCREEN; } static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; } static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid static void userButtonPressedLongStart(); diff --git a/src/Power.cpp b/src/Power.cpp index 0dec0fc21..f11f8eac3 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -380,6 +380,20 @@ class AnalogBatteryLevel : public HasBatteryLevel // if we have a integrated device with a battery, we can assume that the battery is always connected #ifdef BATTERY_IMMUTABLE virtual bool isBatteryConnect() override { return true; } +#elif defined(ADC_V) + virtual bool isBatteryConnect() override + { + int lastReading = digitalRead(ADC_V); + // 判断值是否变化 + for (int i = 2; i < 500; i++) { + int reading = digitalRead(ADC_V); + if (reading != lastReading) { + return false; // 有变化,USB供电, 没接电池 + } + } + + return true; + } #else virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; } #endif @@ -533,9 +547,6 @@ Power::Power() : OSThread("Power") { statusHandler = {}; low_voltage_counter = 0; -#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG) - low_voltage_counter_led3 = 0; -#endif #ifdef DEBUG_HEAP lastheap = memGet.getFreeHeap(); #endif @@ -716,9 +727,6 @@ void Power::readPowerStatus() const PowerStatus powerStatus2 = PowerStatus(hasBattery, usbPowered, isChargingNow, batteryVoltageMv, batteryChargePercent); LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d", powerStatus2.getHasUSB(), powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent()); -#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG) - power_num = powerStatus2.getBatteryVoltageMv(); -#endif newStatus.notifyObservers(&powerStatus2); #ifdef DEBUG_HEAP if (lastheap != memGet.getFreeHeap()) { @@ -766,9 +774,6 @@ void Power::readPowerStatus() if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) { if (batteryLevel->getBattVoltage() < OCV[NUM_OCV_POINTS - 1]) { low_voltage_counter++; -#if defined(ELECROW_ThinkNode_M1) - low_voltage_counter_led3 = low_voltage_counter; -#endif LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter); if (low_voltage_counter > 10) { #ifdef ARCH_NRF52 @@ -781,13 +786,7 @@ void Power::readPowerStatus() } } else { low_voltage_counter = 0; -#if defined(ELECROW_ThinkNode_M1) - low_voltage_counter_led3 = low_voltage_counter; -#endif } -#ifdef POWER_CFG - low_voltage_counter_led3 = low_voltage_counter; -#endif } } diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index a2e7ebbc7..689f5e204 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -12,6 +12,7 @@ #include "RTC.h" #include "Throttle.h" #include "buzz.h" +#include "concurrency/Periodic.h" #include "meshUtils.h" #include "main.h" // pmu_found @@ -89,6 +90,45 @@ static const char *getGPSPowerStateString(GPSPowerState state) } } +#ifdef PIN_GPS_SWITCH +// If we have a hardware switch, define a periodic watcher outside of the GPS runOnce thread, since this can be sleeping +// idefinitely + +int lastState = LOW; +bool firstrun = true; + +static int32_t gpsSwitch() +{ + if (gps) { + int currentState = digitalRead(PIN_GPS_SWITCH); + + // if the switch is set to zero, disable the GPS Thread + if (firstrun) + if (currentState == LOW) + lastState = HIGH; + + if (currentState != lastState) { + if (currentState == LOW) { + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED; + if (!firstrun) + playGPSDisableBeep(); + gps->disable(); + } else { + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; + if (!firstrun) + playGPSEnableBeep(); + gps->enable(); + } + lastState = currentState; + } + firstrun = false; + } + return 1000; +} + +static concurrency::Periodic *gpsPeriodic; +#endif + static void UBXChecksum(uint8_t *message, size_t length) { uint8_t CK_A = 0, CK_B = 0; @@ -1390,6 +1430,12 @@ GPS *GPS::createGps() pinMode(PIN_GPS_PPS, INPUT); #endif +#ifdef PIN_GPS_SWITCH + // toggle GPS via external GPIO switch + pinMode(PIN_GPS_SWITCH, INPUT); + gpsPeriodic = new concurrency::Periodic("GPSSwitch", gpsSwitch); +#endif + // Currently disabled per issue #525 (TinyGPS++ crash bug) // when fixed upstream, can be un-disabled to enable 3D FixType and PDOP #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index e27495f54..8075dd468 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -30,6 +30,7 @@ along with this program. If not, see . #if !MESHTASTIC_EXCLUDE_GPS #include "GPS.h" #endif +#include "ButtonThread.h" #include "MeshService.h" #include "NodeDB.h" #include "error.h" @@ -1606,6 +1607,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) if (on != screenOn) { if (on) { LOG_INFO("Turn on screen"); + buttonThread->setScreenFlag(true); powerMon->setState(meshtastic_PowerMon_State_Screen_On); #ifdef T_WATCH_S3 PMU->enablePowerOutput(XPOWERS_ALDO2); @@ -1641,6 +1643,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) setScreensaverFrames(einkScreensaver); #endif LOG_INFO("Turn off screen"); + buttonThread->setScreenFlag(false); #ifdef ELECROW_ThinkNode_M1 if (digitalRead(PIN_EINK_EN) == HIGH) { digitalWrite(PIN_EINK_EN, LOW); diff --git a/src/main.cpp b/src/main.cpp index fd65830ef..a528da8af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -212,6 +212,60 @@ const char *getDeviceName() return name; } +#if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2) +static int32_t ledBlinkCount = 0; + +static int32_t elecrowLedBlinker() +{ + // are we in alert buzzer mode? + if (buttonThread->isBuzzing()) { + + // blink LED three times for 3 seconds, then 3 times for a second, with one second pause + if (ledBlinkCount % 2) { // odd means LED OFF + ledBlink.set(false); + ledBlinkCount++; + if (ledBlinkCount >= 12) + ledBlinkCount = 0; + noTone(PIN_BUZZER); + return 1000; + } else { + if (ledBlinkCount < 6) { + ledBlink.set(true); + tone(PIN_BUZZER, 4000, 3000); + ledBlinkCount++; + return 3000; + } else { + ledBlink.set(true); + tone(PIN_BUZZER, 4000, 1000); + ledBlinkCount++; + return 1000; + } + } + } else { + ledBlinkCount = 0; + if (config.device.led_heartbeat_disabled) + return 1000; + + static bool ledOn; + // when fully charged, remain on! + if (powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() >= 100) { + ledOn = true; + } else { + ledOn ^= 1; + } + ledBlink.set(ledOn); + // when charging, blink 0.5Hz square wave rate to indicate that + if (powerStatus->getIsCharging()) { + return 500; + } + // When almost empty, blink rapidly + if (!powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() < 10) { + return 250; + } + } + return 1000; +} +#else static int32_t ledBlinker() { // Still set up the blinking (heartbeat) interval but skip code path below, so LED will blink if @@ -227,6 +281,7 @@ static int32_t ledBlinker() // have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000); } +#endif uint32_t timeLastPowered = 0; @@ -263,11 +318,6 @@ void printInfo() void setup() { -#ifdef POWER_CHRG - pinMode(POWER_CHRG, OUTPUT); - digitalWrite(POWER_CHRG, HIGH); -#endif - #if defined(PIN_POWER_EN) pinMode(PIN_POWER_EN, OUTPUT); digitalWrite(PIN_POWER_EN, HIGH); @@ -278,11 +328,6 @@ void setup() digitalWrite(LED_POWER, HIGH); #endif -#ifdef POWER_LED - pinMode(POWER_LED, OUTPUT); - digitalWrite(POWER_LED, HIGH); -#endif - #ifdef USER_LED pinMode(USER_LED, OUTPUT); digitalWrite(USER_LED, LOW); @@ -414,7 +459,12 @@ void setup() OSThread::setup(); +#if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2) + // The ThinkNodes have their own blink logic + ledPeriodic = new Periodic("Blink", elecrowLedBlinker); +#else ledPeriodic = new Periodic("Blink", ledBlinker); +#endif fsInit(); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9bb63652a..c89abbe74 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -743,6 +743,15 @@ void NodeDB::installDefaultModuleConfig() moduleConfig.external_notification.output_ms = 100; moduleConfig.external_notification.active = true; #endif +#ifdef ELECROW_ThinkNode_M1 + // Default to Elecrow USER_LED (blue) + moduleConfig.external_notification.enabled = true; + moduleConfig.external_notification.output = USER_LED; + moduleConfig.external_notification.active = true; + moduleConfig.external_notification.alert_message = true; + moduleConfig.external_notification.output_ms = 1000; + moduleConfig.external_notification.nag_timeout = 60; +#endif #ifdef BUTTON_SECONDARY_CANNEDMESSAGES // Use a board's second built-in button as input source for canned messages moduleConfig.canned_message.enabled = true; diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp index ab1e5c922..3c4faac3e 100644 --- a/src/platform/esp32/main-esp32.cpp +++ b/src/platform/esp32/main-esp32.cpp @@ -109,9 +109,8 @@ void esp32Setup() randomSeed(seed); */ -#ifdef POWER_FULL - pinMode(POWER_FULL, INPUT); - pinMode(7, INPUT); +#ifdef ADC_V + pinMode(ADC_V, INPUT); #endif LOG_DEBUG("Total heap: %d", ESP.getHeapSize()); diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 53971e95a..9accd2a02 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -235,10 +235,6 @@ void nrf52InitSemiHosting() void nrf52Setup() { -#ifdef USB_CHECK - pinMode(USB_CHECK, INPUT); -#endif - #ifdef ADC_V pinMode(ADC_V, INPUT); #endif @@ -288,7 +284,7 @@ void cpuDeepSleep(uint32_t msecToWake) #endif // This may cause crashes as debug messages continue to flow. Serial.end(); -#ifdef PIN_SERIAL_RX1 +#ifdef PIN_SERIAL1_RX Serial1.end(); #endif setBluetoothEnable(false); diff --git a/src/power.h b/src/power.h index 97944fef7..e9c0deb7c 100644 --- a/src/power.h +++ b/src/power.h @@ -84,11 +84,6 @@ class Power : private concurrency::OSThread void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; } const uint16_t OCV[11] = {OCV_ARRAY}; -#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG) - uint8_t low_voltage_counter_led3; - int power_num = 0; -#endif - protected: meshtastic::PowerStatus *statusHandler; diff --git a/variants/ELECROW-ThinkNode-M1/variant.h b/variants/ELECROW-ThinkNode-M1/variant.h index fc2fddbdf..2e91e378d 100644 --- a/variants/ELECROW-ThinkNode-M1/variant.h +++ b/variants/ELECROW-ThinkNode-M1/variant.h @@ -41,16 +41,15 @@ extern "C" { #define NUM_ANALOG_INPUTS (1) #define NUM_ANALOG_OUTPUTS (0) -#define PIN_LED1 -1 #define PIN_LED2 -1 #define PIN_LED3 -1 // LED -#define POWER_LED (32 + 6) // red +#define PIN_LED1 (32 + 6) // red #define LED_POWER (32 + 4) #define USER_LED (0 + 13) // green // USB_CHECK -#define USB_CHECK (32 + 3) +#define EXT_PWR_DETECT (32 + 3) #define ADC_V (0 + 8) #define LED_RED PIN_LED3 @@ -59,7 +58,7 @@ extern "C" { #define LED_BUILTIN LED_BLUE #define LED_CONN PIN_GREEN #define LED_STATE_ON 0 // State when LED is lit // LED灯亮时的状态 -#define M1_buzzer (0 + 6) +#define PIN_BUZZER (0 + 6) /* * Buttons */ @@ -82,6 +81,7 @@ extern "C" { static const uint8_t A0 = PIN_A0; #define ADC_RESOLUTION 14 +#define BATTERY_SENSE_SAMPLES 30 #define PIN_NFC1 (9) #define PIN_NFC2 (10) @@ -159,7 +159,7 @@ External serial flash WP25R1635FZUIL0 #define GPS_THREAD_INTERVAL 50 -#define PIN_GPS_PPS (32 + 1) // GPS开关判断 +#define PIN_GPS_SWITCH (32 + 1) // GPS开关判断 #define PIN_SERIAL1_RX GPS_TX_PIN #define PIN_SERIAL1_TX GPS_RX_PIN diff --git a/variants/ELECROW-ThinkNode-M2/variant.h b/variants/ELECROW-ThinkNode-M2/variant.h index 801d5606f..55f35e498 100644 --- a/variants/ELECROW-ThinkNode-M2/variant.h +++ b/variants/ELECROW-ThinkNode-M2/variant.h @@ -1,14 +1,13 @@ // Status -#define LED_PIN_POWER 1 -#define BIAS_T_ENABLE LED_PIN_POWER -#define BIAS_T_VALUE HIGH +#define LED_PIN 1 #define PIN_BUTTON1 47 // 功能键 #define PIN_BUTTON2 4 // 电源键 -#define POWER_CFG -#define POWER_CHRG 6 -#define POWER_FULL 42 +#define LED_PIN_POWER 6 +#define ADC_V 42 +// USB_CHECK +#define EXT_PWR_DETECT 7 #define PIN_BUZZER 5 From e2933bcb5b92f92569f9b78e75d5e4a001e33088 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Mon, 7 Apr 2025 14:04:31 +0200 Subject: [PATCH 027/238] Update platformio.ini (#6512) --- variants/crowpanel-esp32s3-5-epaper/platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/variants/crowpanel-esp32s3-5-epaper/platformio.ini b/variants/crowpanel-esp32s3-5-epaper/platformio.ini index f1257a979..ebf013f64 100644 --- a/variants/crowpanel-esp32s3-5-epaper/platformio.ini +++ b/variants/crowpanel-esp32s3-5-epaper/platformio.ini @@ -11,7 +11,7 @@ board = esp32-s3-devkitc-1 board_level = extra upload_protocol = esptool build_flags = - ${esp32_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper + ${esp32s3_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper -D PRIVATE_HW -DBOARD_HAS_PSRAM -DGPS_POWER_TOGGLE @@ -39,7 +39,7 @@ board = esp32-s3-devkitc-1 board_level = extra upload_protocol = esptool build_flags = - ${esp32_base.build_flags} -D CROWPANEL_ESP32S3_4_EPAPER -I variants/crowpanel-esp32s3-5-epaper + ${esp32s3_base.build_flags} -D CROWPANEL_ESP32S3_4_EPAPER -I variants/crowpanel-esp32s3-5-epaper -D PRIVATE_HW -DBOARD_HAS_PSRAM -DGPS_POWER_TOGGLE @@ -67,7 +67,7 @@ board = esp32-s3-devkitc-1 board_level = extra upload_protocol = esptool build_flags = - ${esp32_base.build_flags} -D CROWPANEL_ESP32S3_2_EPAPER -I variants/crowpanel-esp32s3-5-epaper + ${esp32s3_base.build_flags} -D CROWPANEL_ESP32S3_2_EPAPER -I variants/crowpanel-esp32s3-5-epaper -D PRIVATE_HW -DBOARD_HAS_PSRAM -DGPS_POWER_TOGGLE From a084073cc15b4cb0a05c5f9ca52d6fffd94d4530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Mon, 7 Apr 2025 15:35:51 +0200 Subject: [PATCH 028/238] inkhud doesn't have a button thread (#6513) --- src/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index a528da8af..bf4b0c2f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -218,8 +218,8 @@ static int32_t ledBlinkCount = 0; static int32_t elecrowLedBlinker() { // are we in alert buzzer mode? +#if HAS_BUTTON if (buttonThread->isBuzzing()) { - // blink LED three times for 3 seconds, then 3 times for a second, with one second pause if (ledBlinkCount % 2) { // odd means LED OFF ledBlink.set(false); @@ -242,6 +242,7 @@ static int32_t elecrowLedBlinker() } } } else { +#endif ledBlinkCount = 0; if (config.device.led_heartbeat_disabled) return 1000; @@ -262,7 +263,9 @@ static int32_t elecrowLedBlinker() if (!powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() < 10) { return 250; } +#if HAS_BUTTON } +#endif return 1000; } #else From 12d13056188956a1002db2187605c178693c1f03 Mon Sep 17 00:00:00 2001 From: Eric Wolak Date: Mon, 7 Apr 2025 17:34:16 -0700 Subject: [PATCH 029/238] Fix device-specific logic in install script (#6508) * Fix device-specific logic in install script These new for loops to check for variants in a list should be checking for the string to _be empty_, not _non-empty_, if a match is found causing the replacement to fire. * simplify logic per review feedback --------- Co-authored-by: Ben Meadors --- bin/device-install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/device-install.sh b/bin/device-install.sh index bacf48f69..796626a9d 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -138,7 +138,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then # littlefs* offset for BigDB 8mb and OTA OFFSET. for variant in "${BIGDB_8MB[@]}"; do - if [ -n "${FILENAME##*"$variant"*}" ]; then + if [ -z "${FILENAME##*"$variant"*}" ]; then OFFSET=0x670000 OTA_OFFSET=0x340000 fi @@ -146,7 +146,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then # littlefs* offset for BigDB 16mb and OTA OFFSET. for variant in "${BIGDB_16MB[@]}"; do - if [ -n "${FILENAME##*"$variant"*}" ]; then + if [ -z "${FILENAME##*"$variant"*}" ]; then OFFSET=0xc90000 OTA_OFFSET=0x650000 fi @@ -155,7 +155,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then # Account for S3 board's different OTA partition # FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable for variant in "${S3_VARIANTS[@]}"; do - if [ -n "${FILENAME##*"$variant"*}" ]; then + if [ -z "${FILENAME##*"$variant"*}" ]; then MCU="esp32s3" fi done From c0dab4a672c3ea92f3879df2107a4a9f95a34fba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:27:58 -0500 Subject: [PATCH 030/238] Upgrade trunk (#6519) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 608045e45..3aa9628fc 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,14 +9,14 @@ plugins: lint: enabled: - prettier@3.5.3 - - trufflehog@3.88.22 + - trufflehog@3.88.23 - yamllint@1.37.0 - bandit@1.8.3 - - checkov@3.2.396 + - checkov@3.2.398 - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 - - ruff@0.11.3 + - ruff@0.11.4 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.4 From cfc2a96a459318e7fe8a41f9ed9c997ef08b19a7 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 8 Apr 2025 10:09:23 -0400 Subject: [PATCH 031/238] Update web, use centrally defined version (#6500) --- .github/actions/build-variant/action.yml | 9 ++++++++- bin/rpkg.macros | 4 ++++ bin/web.version | 1 + debian/ci_pack_sdeb.sh | 5 +++-- meshtasticd.spec.rpkg | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 bin/web.version diff --git a/.github/actions/build-variant/action.yml b/.github/actions/build-variant/action.yml index 2f0883fad..67d002eea 100644 --- a/.github/actions/build-variant/action.yml +++ b/.github/actions/build-variant/action.yml @@ -43,6 +43,13 @@ runs: id: base uses: ./.github/actions/setup-base + - name: Get web ui version + if: inputs.include-web-ui == 'true' + id: webver + shell: bash + run: | + echo "ver=$(cat bin/web.version)" >> $GITHUB_OUTPUT + - name: Pull web ui if: inputs.include-web-ui == 'true' uses: dsaltares/fetch-gh-release-asset@master @@ -51,7 +58,7 @@ runs: file: build.tar target: build.tar token: ${{ inputs.github_token }} - version: tags/v2.5.3 + version: tags/v${{ steps.webver.outputs.ver }} - name: Unpack web ui if: inputs.include-web-ui == 'true' diff --git a/bin/rpkg.macros b/bin/rpkg.macros index 2bbb203de..aa036fc33 100644 --- a/bin/rpkg.macros +++ b/bin/rpkg.macros @@ -2,6 +2,10 @@ function meshtastic_version { meshtastic_version=$(python3 bin/buildinfo.py short) echo -n "$meshtastic_version" } +function web_version { + web_version=$(cat bin/web.version) + echo -n "$web_version" +} function git_commits_num { total_commits=$(git rev-list --all --count) echo -n "$total_commits" diff --git a/bin/web.version b/bin/web.version new file mode 100644 index 000000000..914ec9671 --- /dev/null +++ b/bin/web.version @@ -0,0 +1 @@ +2.6.0 \ No newline at end of file diff --git a/debian/ci_pack_sdeb.sh b/debian/ci_pack_sdeb.sh index a8b2252ae..c0cea0010 100755 --- a/debian/ci_pack_sdeb.sh +++ b/debian/ci_pack_sdeb.sh @@ -10,8 +10,9 @@ platformio pkg install -e native -t platformio/tool-scons@4.40502.0 # Compress `pio` directory to prevent dh_clean from sanitizing it tar -cf pio.tar pio/ rm -rf pio -# Download the latest meshtastic/web release build.tar to `web.tar` -curl -L https://github.com/meshtastic/web/releases/latest/download/build.tar -o web.tar +# Download the meshtastic/web release build.tar to `web.tar` +web_ver=$(cat bin/web.version) +curl -L "https://github.com/meshtastic/web/releases/download/v$web_ver/build.tar" -o web.tar package=$(dpkg-parsechangelog --show-field Source) diff --git a/meshtasticd.spec.rpkg b/meshtasticd.spec.rpkg index a09261056..4d6c9d6f5 100644 --- a/meshtasticd.spec.rpkg +++ b/meshtasticd.spec.rpkg @@ -21,7 +21,7 @@ Summary: Meshtastic daemon for communicating with Meshtastic devices License: GPL-3.0 URL: https://github.com/meshtastic/firmware Source0: {{{ git_dir_pack }}} -Source1: https://github.com/meshtastic/web/releases/latest/download/build.tar +Source1: https://github.com/meshtastic/web/releases/download/v{{{ web_version }}}/build.tar BuildRequires: systemd-rpm-macros BuildRequires: python3-devel From c94dd1e33110e10c5afbd642212c545664ed5927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 8 Apr 2025 17:46:39 +0200 Subject: [PATCH 032/238] Minor adjustment of blink codes and 'unstick' the M2 button. (#6521) --- src/ButtonThread.cpp | 4 ++++ src/main.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 375029c99..04200a7df 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -349,8 +349,12 @@ void ButtonThread::attachButtonInterrupts() #endif #ifdef BUTTON_PIN_ALT +#ifdef ELECROW_ThinkNode_M2 + wakeOnIrq(BUTTON_PIN_ALT, RISING); +#else wakeOnIrq(BUTTON_PIN_ALT, FALLING); #endif +#endif #ifdef BUTTON_PIN_TOUCH wakeOnIrq(BUTTON_PIN_TOUCH, FALLING); diff --git a/src/main.cpp b/src/main.cpp index bf4b0c2f2..bfbd73a43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -248,8 +248,9 @@ static int32_t elecrowLedBlinker() return 1000; static bool ledOn; - // when fully charged, remain on! - if (powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() >= 100) { + // remain on when fully charged or discharging above 10% + if ((powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() >= 100) || + (!powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() >= 10)) { ledOn = true; } else { ledOn ^= 1; @@ -259,8 +260,8 @@ static int32_t elecrowLedBlinker() if (powerStatus->getIsCharging()) { return 500; } - // When almost empty, blink rapidly - if (!powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() < 10) { + // Blink rapidly when almost empty or if battery is not connected + if ((!powerStatus->getIsCharging() && powerStatus->getBatteryChargePercent() < 10) || !powerStatus->getHasBattery()) { return 250; } #if HAS_BUTTON From fb2010552faea355f8fbf1491d1c1cc9eaa316d2 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Tue, 8 Apr 2025 20:50:58 +0200 Subject: [PATCH 033/238] MUI: update commit reference (#6526) new feature: map locations filtering bugfix: boot logo / bt logo --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 377635873..749aa94c7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -94,7 +94,7 @@ lib_deps = [device-ui_base] lib_deps = - https://github.com/meshtastic/device-ui/archive/99171e87a70452395b56cce713a951c1c2964370.zip + https://github.com/meshtastic/device-ui/archive/56ef8db7eb4dda44dc0c1ec5828044debbbc6d33.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 1b1d4625aa83c8a76855422db1dfc19846fdb125 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Wed, 9 Apr 2025 04:04:33 +0900 Subject: [PATCH 034/238] chore: update ubx.h (#6522) usefull -> useful --- src/gps/ubx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gps/ubx.h b/src/gps/ubx.h index d674bed51..0fe2f01fb 100644 --- a/src/gps/ubx.h +++ b/src/gps/ubx.h @@ -224,7 +224,7 @@ static const uint8_t _message_GSA[] = { 0x00, // Rate for DDC 0x00, // Rate for UART1 0x00, // Rate for UART2 - 0x00, // Rate for USB usefull for native linux + 0x00, // Rate for USB useful for native linux 0x00, // Rate for SPI 0x00 // Reserved }; @@ -258,7 +258,7 @@ static const uint8_t _message_RMC[] = { 0x00, // Rate for DDC 0x01, // Rate for UART1 0x00, // Rate for UART2 - 0x01, // Rate for USB usefull for native linux + 0x01, // Rate for USB useful for native linux 0x00, // Rate for SPI 0x00 // Reserved }; @@ -269,7 +269,7 @@ static const uint8_t _message_GGA[] = { 0x00, // Rate for DDC 0x01, // Rate for UART1 0x00, // Rate for UART2 - 0x01, // Rate for USB, usefull for native linux + 0x01, // Rate for USB, useful for native linux 0x00, // Rate for SPI 0x00 // Reserved }; From 0d800b7a22be675717f3d5cbff29e66234d88ffb Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 8 Apr 2025 17:14:39 -0400 Subject: [PATCH 035/238] meshtasticd docker: Support webui (#6482) --- Dockerfile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 733a46325..55580c579 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ ENV TZ=Etc/UTC # Install Dependencies ENV PIP_ROOT_USER_ACTION=ignore RUN apt-get update && apt-get install --no-install-recommends -y \ - wget g++ zip git ca-certificates \ + curl wget g++ zip git ca-certificates \ libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \ libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ @@ -27,6 +27,12 @@ COPY . /tmp/firmware RUN bash ./bin/build-native.sh && \ cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" +# Fetch web assets +RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/firmware/bin/web.version)/build.tar" -o /tmp/web.tar \ + && mkdir -p /tmp/web \ + && tar -xf /tmp/web.tar -C /tmp/web/ \ + && gzip -dr /tmp/web \ + && rm /tmp/web.tar ##### PRODUCTION BUILD ############# @@ -46,6 +52,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/sbin/ +COPY --from=builder /tmp/web /usr/share/meshtasticd/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d @@ -54,7 +61,9 @@ VOLUME /var/lib/meshtasticd # Expose Meshtastic TCP API port from the host EXPOSE 4403 +# Expose Meshtastic Web UI port from the host +EXPOSE 443 CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ] -HEALTHCHECK NONE \ No newline at end of file +HEALTHCHECK NONE From ec298199ee1cdceaad25b743dcbf31e3ddb021ff Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Wed, 9 Apr 2025 18:40:12 +0800 Subject: [PATCH 036/238] remove checkov from trunk config (#6532) We don't have terraform, cloudformation, helm templates ... and this check pushes out new versions very frequently which is annoying with out automation :) --- .trunk/trunk.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 3aa9628fc..903b4c298 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -12,7 +12,6 @@ lint: - trufflehog@3.88.23 - yamllint@1.37.0 - bandit@1.8.3 - - checkov@3.2.398 - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 From 69f938ea98dca5c103f0898489877afd2c7b2e25 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:13:49 +0200 Subject: [PATCH 037/238] Send UDP packet even if it's encrypted (#6524) Co-authored-by: Ben Meadors --- src/mesh/Router.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index b8b7ee610..2cc3007a2 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -283,11 +283,6 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) abortSendAndNak(encodeResult, p); return encodeResult; // FIXME - this isn't a valid ErrorCode } -#if HAS_UDP_MULTICAST - if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { - udpThread->onSend(const_cast(p)); - } -#endif #if !MESHTASTIC_EXCLUDE_MQTT // Only publish to MQTT if we're the original transmitter of the packet if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) { @@ -297,6 +292,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) packetPool.release(p_decoded); } +#if HAS_UDP_MULTICAST + if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { + udpThread->onSend(const_cast(p)); + } +#endif + assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside) return iface->send(p); } From fc3d9f2a15e201bbedc3a98049abdc8b3bd648da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Wed, 9 Apr 2025 14:55:23 +0200 Subject: [PATCH 038/238] fix power pin definition --- variants/ELECROW-ThinkNode-M2/variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/ELECROW-ThinkNode-M2/variant.h b/variants/ELECROW-ThinkNode-M2/variant.h index 55f35e498..a6bb40f1a 100644 --- a/variants/ELECROW-ThinkNode-M2/variant.h +++ b/variants/ELECROW-ThinkNode-M2/variant.h @@ -4,7 +4,7 @@ #define PIN_BUTTON1 47 // 功能键 #define PIN_BUTTON2 4 // 电源键 -#define LED_PIN_POWER 6 +#define LED_POWER 6 #define ADC_V 42 // USB_CHECK #define EXT_PWR_DETECT 7 From 5256ae90dc4e96a4978cd3fde4a89c56699fb351 Mon Sep 17 00:00:00 2001 From: Andrik45719 Date: Wed, 9 Apr 2025 18:40:38 +0300 Subject: [PATCH 039/238] DIY v1/v1_1 add TCXO_OPTIONAL make it so that the firmware can try both TCXO and XTAL (#6534) * EBYTE_E22 TCXO_OPTIONAL * EBYTE_E22 --------- Co-authored-by: Ben Meadors --- variants/diy/v1/variant.h | 1 + variants/diy/v1_1/variant.h | 1 + 2 files changed, 2 insertions(+) diff --git a/variants/diy/v1/variant.h b/variants/diy/v1/variant.h index 4802dbe89..8a2df3f2b 100644 --- a/variants/diy/v1/variant.h +++ b/variants/diy/v1/variant.h @@ -53,4 +53,5 @@ // Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch // (which is the default for the sx1262interface code) #define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL #endif diff --git a/variants/diy/v1_1/variant.h b/variants/diy/v1_1/variant.h index 8a006d0d2..1c8110301 100644 --- a/variants/diy/v1_1/variant.h +++ b/variants/diy/v1_1/variant.h @@ -54,4 +54,5 @@ // Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch // (which is the default for the sx1262interface code) #define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL #endif From 536b6d87c63888e8ee480a3f06d004e4360b4459 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Thu, 10 Apr 2025 03:41:51 +1200 Subject: [PATCH 040/238] InkHUD support for LilyGo T3S3 E-Paper (#6503) * Purge an incomplete E-Ink driver * Use the deep-sleep mode of SSD16XX E-Ink displays * TwoButton doesn't need to store pin mode * Fix false positive button presses after light sleep * E-Ink driver for DEPG0213BNS800 * InkHUD support for LilyGo T3S3 E-paper --------- Co-authored-by: Ben Meadors --- .../niche/Drivers/EInk/DEPG0154BNS800.cpp | 1 - .../niche/Drivers/EInk/DEPG0154BNS800.h | 34 ----- .../niche/Drivers/EInk/DEPG0213BNS800.cpp | 132 ++++++++++++++++++ .../niche/Drivers/EInk/DEPG0213BNS800.h | 44 ++++++ .../niche/Drivers/EInk/DEPG0290BNS800.cpp | 5 + src/graphics/niche/Drivers/EInk/SSD16XX.cpp | 13 ++ src/graphics/niche/Drivers/EInk/SSD16XX.h | 1 + src/graphics/niche/Inputs/TwoButton.cpp | 7 +- src/graphics/niche/Inputs/TwoButton.h | 3 +- variants/t-echo/nicheGraphics.h | 2 +- variants/tlora_t3s3_epaper/nicheGraphics.h | 102 ++++++++++++++ variants/tlora_t3s3_epaper/platformio.ini | 19 +++ variants/tlora_t3s3_epaper/variant.h | 1 - 13 files changed, 322 insertions(+), 42 deletions(-) delete mode 100644 src/graphics/niche/Drivers/EInk/DEPG0154BNS800.cpp delete mode 100644 src/graphics/niche/Drivers/EInk/DEPG0154BNS800.h create mode 100644 src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp create mode 100644 src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h create mode 100644 variants/tlora_t3s3_epaper/nicheGraphics.h diff --git a/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.cpp b/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.cpp deleted file mode 100644 index b8715ed1d..000000000 --- a/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "./DEPG0154BNS800.h" \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.h b/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.h deleted file mode 100644 index 62d42ef57..000000000 --- a/src/graphics/niche/Drivers/EInk/DEPG0154BNS800.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - -E-Ink display driver - - DEPG0154BNS800 - - Manufacturer: DKE - - Size: 1.54 inch - - Resolution: 152px x 152px - - Flex connector marking: FPC7525 - -*/ - -#pragma once - -#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS -#include "configuration.h" - -#include "./SSD16XX.h" - -namespace NicheGraphics::Drivers -{ -class DEPG0154BNS800 : public SSD16XX -{ - // Display properties - private: - static constexpr uint32_t width = 152; - static constexpr uint32_t height = 152; - static constexpr UpdateTypes supported = (UpdateTypes)(FULL); - - public: - DEPG0154BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte -}; - -} // namespace NicheGraphics::Drivers -#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp b/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp new file mode 100644 index 000000000..2c8df96ed --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp @@ -0,0 +1,132 @@ +#include "./DEPG0213BNS800.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +using namespace NicheGraphics::Drivers; + +// Describes the operation performed when a "fast refresh" is performed +// Source: Modified from GxEPD2 (GxEPD2_213_BN) +static const uint8_t LUT_FAST[] = { + // 1 2 3 + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2B (Existing black pixels) + 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2W (New white pixels) + 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2B (New black pixels) + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2W (Existing white pixels) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VCOM + + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 1. Any pixels changing W2B or B2W. Two medium taps. + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2. All pixels. One short tap. + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3. Cooldown + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, // +}; + +// How strongly the pixels are pulled and pushed +void DEPG0213BNS800::configVoltages() +{ + switch (updateType) { + case FAST: + // Reference: display datasheet, GxEPD1 + sendCommand(0x03); // Gate voltage + sendData(0x17); // VGH: 20V + + // Reference: display datasheet, GxEPD1 + sendCommand(0x04); // Source voltage + sendData(0x41); // VSH1: 15V + sendData(0x00); // VSH2: NA + sendData(0x32); // VSL: -15V + + // GxEPD1 sets this at -1.2V, but that seems to be drive the pixels very hard + sendCommand(0x2C); // VCOM voltage + sendData(0x08); // VCOM: -0.2V + break; + + case FULL: + default: + // From OTP memory + break; + } +} + +// Load settings about how the pixels are moved from old state to new state during a refresh +// - manually specified, +// - or with stored values from displays OTP memory +void DEPG0213BNS800::configWaveform() +{ + switch (updateType) { + case FAST: + sendCommand(0x3C); // Border waveform: + sendData(0x80); // VSS + + sendCommand(0x32); // Write LUT register from MCU: + sendData(LUT_FAST, sizeof(LUT_FAST)); // (describes operation for a FAST refresh) + break; + + case FULL: + default: + // From OTP memory + break; + } +} + +// Describes the sequence of events performed by the displays controller IC during a refresh +// Includes "power up", "load settings from memory", "update the pixels", etc +void DEPG0213BNS800::configUpdateSequence() +{ + switch (updateType) { + case FAST: + sendCommand(0x22); // Set "update sequence" + sendData(0xCF); // Differential, use manually loaded waveform + break; + + case FULL: + default: + sendCommand(0x22); // Set "update sequence" + sendData(0xF7); // Non-differential, load waveform from OTP + break; + } +} + +// Once the refresh operation has been started, +// begin periodically polling the display to check for completion, using the normal Meshtastic threading code +// Only used when refresh is "async" +void DEPG0213BNS800::detachFromUpdate() +{ + switch (updateType) { + case FAST: + return beginPolling(50, 500); // At least 500ms, then poll every 50ms + case FULL: + default: + return beginPolling(100, 3500); // At least 3500ms, then poll every 100ms + } +} + +// For this display, we do not need to re-write the new image. +// We're overriding SSD16XX::finalizeUpdate to make this small optimization. +// The display does also work just fine with the generic SSD16XX method, though. +void DEPG0213BNS800::finalizeUpdate() +{ + // Put a copy of the image into the "old memory". + // Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place + // We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc. + if (updateType != FULL) { + // writeNewImage(); // Not required for this display + writeOldImage(); + sendCommand(0x7F); // Terminate image write without update + wait(); + } + + // Enter deep-sleep to save a few µA + // Waking from this requires that display's reset pin is broken out + if (pin_rst != 0xFF) + deepSleep(); +} +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h b/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h new file mode 100644 index 000000000..e1bb96450 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h @@ -0,0 +1,44 @@ +/* + +E-Ink display driver + - DEPG0213BNS800 + - Manufacturer: DKE + - Size: 2.13 inch + - Resolution: 122px x 250px + - Flex connector marking: FPC-7528B + + Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs. + DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead. +*/ + +#pragma once + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +#include "configuration.h" + +#include "./SSD16XX.h" + +namespace NicheGraphics::Drivers +{ +class DEPG0213BNS800 : public SSD16XX +{ + // Display properties + private: + static constexpr uint32_t width = 122; + static constexpr uint32_t height = 250; + static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); + + public: + DEPG0213BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte + + protected: + void configVoltages() override; + void configWaveform() override; + void configUpdateSequence() override; + void detachFromUpdate() override; + void finalizeUpdate() override; // Only overriden for a slight optimization +}; + +} // namespace NicheGraphics::Drivers +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/DEPG0290BNS800.cpp b/src/graphics/niche/Drivers/EInk/DEPG0290BNS800.cpp index 5f3a05670..15134d5ad 100644 --- a/src/graphics/niche/Drivers/EInk/DEPG0290BNS800.cpp +++ b/src/graphics/niche/Drivers/EInk/DEPG0290BNS800.cpp @@ -116,5 +116,10 @@ void DEPG0290BNS800::finalizeUpdate() sendCommand(0x7F); // Terminate image write without update wait(); } + + // Enter deep-sleep to save a few µA + // Waking from this requires that display's reset pin is broken out + if (pin_rst != 0xFF) + deepSleep(); } #endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/SSD16XX.cpp b/src/graphics/niche/Drivers/EInk/SSD16XX.cpp index 5a5397dbd..a2357a80b 100644 --- a/src/graphics/niche/Drivers/EInk/SSD16XX.cpp +++ b/src/graphics/niche/Drivers/EInk/SSD16XX.cpp @@ -242,5 +242,18 @@ void SSD16XX::finalizeUpdate() sendCommand(0x7F); // Terminate image write without update wait(); } + + // Enter deep-sleep to save a few µA + // Waking from this requires that display's reset pin is broken out + if (pin_rst != 0xFF) + deepSleep(); +} + +// Enter a lower-power state +// May only save a few µA.. +void SSD16XX::deepSleep() +{ + sendCommand(0x10); // Enter deep sleep + sendData(0x01); // Mode 1: preserve image RAM } #endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/SSD16XX.h b/src/graphics/niche/Drivers/EInk/SSD16XX.h index 799a378c0..3f92818ce 100644 --- a/src/graphics/niche/Drivers/EInk/SSD16XX.h +++ b/src/graphics/niche/Drivers/EInk/SSD16XX.h @@ -44,6 +44,7 @@ class SSD16XX : public EInk virtual void detachFromUpdate(); virtual bool isUpdateDone() override; virtual void finalizeUpdate() override; + virtual void deepSleep(); protected: uint8_t bufferOffsetX = 0; // In bytes. Panel x=0 does not always align with controller x=0. Quirky internal wiring? diff --git a/src/graphics/niche/Inputs/TwoButton.cpp b/src/graphics/niche/Inputs/TwoButton.cpp index b270d56cf..1e91d9080 100644 --- a/src/graphics/niche/Inputs/TwoButton.cpp +++ b/src/graphics/niche/Inputs/TwoButton.cpp @@ -98,9 +98,8 @@ void TwoButton::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup) assert(whichButton < 2); buttons[whichButton].pin = pin; buttons[whichButton].activeLogic = LOW; // Unimplemented - buttons[whichButton].mode = internalPullup ? INPUT_PULLUP : INPUT; - pinMode(buttons[whichButton].pin, buttons[whichButton].mode); + pinMode(buttons[whichButton].pin, internalPullup ? INPUT_PULLUP : INPUT); } void TwoButton::setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs) @@ -299,7 +298,9 @@ int TwoButton::afterLightSleep(esp_sleep_wakeup_cause_t cause) // Manually trigger the button-down ISR // - during light sleep, our ISR is disabled // - if light sleep ends by button press, pretend our own ISR caught it - if (cause == ESP_SLEEP_WAKEUP_GPIO) + // - need to manually confirm by reading pin ourselves, to avoid occasional false positives + // (false positive only when using internal pullup resistors?) + if (cause == ESP_SLEEP_WAKEUP_GPIO && digitalRead(buttons[0].pin) == buttons[0].activeLogic) isrPrimary(); return 0; // Indicates success diff --git a/src/graphics/niche/Inputs/TwoButton.h b/src/graphics/niche/Inputs/TwoButton.h index f1e18dd89..ae66adf96 100644 --- a/src/graphics/niche/Inputs/TwoButton.h +++ b/src/graphics/niche/Inputs/TwoButton.h @@ -35,7 +35,7 @@ class TwoButton : protected concurrency::OSThread static TwoButton *getInstance(); // Create or get the singleton instance void start(); // Start handling button input void stop(); // Stop handling button input (disconnect ISRs for sleep) - void setWiring(uint8_t whichButton, uint8_t pin, bool internalPulldown = false); + void setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup = false); void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs); void setHandlerDown(uint8_t whichButton, Callback onDown); void setHandlerUp(uint8_t whichButton, Callback onUp); @@ -65,7 +65,6 @@ class TwoButton : protected concurrency::OSThread // Per-button config uint8_t pin = 0xFF; // 0xFF: unset bool activeLogic = LOW; // Active LOW by default. Currently unimplemented. - uint8_t mode = INPUT; // Whether to use internal pull up / pull down resistors uint32_t debounceLength = 50; // Minimum length for shortpress, in ms uint32_t longpressLength = 500; // How long after button down to fire longpress, in ms volatile State state = State::REST; // Internal state diff --git a/variants/t-echo/nicheGraphics.h b/variants/t-echo/nicheGraphics.h index f5dde6b19..5862dcdfb 100644 --- a/variants/t-echo/nicheGraphics.h +++ b/variants/t-echo/nicheGraphics.h @@ -112,7 +112,7 @@ void setupNicheGraphics() // Setup the capacitive touch button // - short: momentary backlight // - long: latch backlight on - buttons->setWiring(TOUCH_BUTTON, PIN_BUTTON_TOUCH, LOW); + buttons->setWiring(TOUCH_BUTTON, PIN_BUTTON_TOUCH); buttons->setTiming(TOUCH_BUTTON, 50, 5000); // 5 seconds before latch - limited by T-Echo's capacitive touch IC buttons->setHandlerDown(TOUCH_BUTTON, [backlight]() { backlight->peek(); diff --git a/variants/tlora_t3s3_epaper/nicheGraphics.h b/variants/tlora_t3s3_epaper/nicheGraphics.h new file mode 100644 index 000000000..55bb9a203 --- /dev/null +++ b/variants/tlora_t3s3_epaper/nicheGraphics.h @@ -0,0 +1,102 @@ +#pragma once + +#include "configuration.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +// InkHUD-specific components +// --------------------------- +#include "graphics/niche/InkHUD/InkHUD.h" + +// Applets +#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h" +#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h" +#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" +#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" + +// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" +// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" + +// Shared NicheGraphics components +// -------------------------------- +#include "graphics/niche/Drivers/EInk/DEPG0213BNS800.h" +#include "graphics/niche/Inputs/TwoButton.h" + +#include "graphics/niche/Fonts/FreeSans6pt7b.h" +#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" +#include + +void setupNicheGraphics() +{ + using namespace NicheGraphics; + + // SPI + // ----------------------------- + + // Display is connected to HSPI + SPIClass *hspi = new SPIClass(HSPI); + hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); + + // E-Ink Driver + // ----------------------------- + + // Use E-Ink driver + Drivers::EInk *driver = new Drivers::DEPG0213BNS800; + driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); + + // InkHUD + // ---------------------------- + + InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); + + // Set the driver + inkhud->setDriver(driver); + + // Set how many FAST updates per FULL update + // Set how unhealthy additional FAST updates beyond this number are + inkhud->setDisplayResilience(15, 1.5); + + // Prepare fonts + InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); + /* + // Font localization demo: Cyrillic + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); + InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); + */ + + // Customize default settings + inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? + inkhud->persistence->settings.rotation = 3; // 270 degrees clockwise + inkhud->persistence->settings.userTiles.count = 1; // One tile only by default, keep things simple for new users + + // Pick applets + inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown + inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 + // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); + // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); + + // Start running InkHUD + inkhud->begin(); + + // Buttons + // -------------------------- + + Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component + + // Setup the main user button + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin(), true); + buttons->setHandlerShortPress(0, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); + buttons->setHandlerLongPress(0, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + + buttons->start(); +} + +#endif \ No newline at end of file diff --git a/variants/tlora_t3s3_epaper/platformio.ini b/variants/tlora_t3s3_epaper/platformio.ini index 87351e586..957c37b95 100644 --- a/variants/tlora_t3s3_epaper/platformio.ini +++ b/variants/tlora_t3s3_epaper/platformio.ini @@ -7,6 +7,7 @@ upload_protocol = esptool build_flags = ${esp32_base.build_flags} -D TLORA_T3S3_EPAPER -I variants/tlora_t3s3_epaper -DGPS_POWER_TOGGLE + -DUSE_EINK -DEINK_DISPLAY_MODEL=GxEPD2_213_BN -DEINK_WIDTH=250 -DEINK_HEIGHT=122 @@ -16,3 +17,21 @@ build_flags = lib_deps = ${esp32s3_base.lib_deps} https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip + +[env:tlora-t3s3-epaper-inkhud] +extends = esp32s3_base, inkhud +board = tlora-t3s3-v1 +board_check = true +upload_protocol = esptool +build_src_filter = + ${esp32_base.build_src_filter} + ${inkhud.build_src_filter} +build_flags = + ${esp32s3_base.build_flags} + ${inkhud.build_flags} + -I variants/tlora_t3s3_epaper + -D TLORA_T3S3_EPAPER + -D MAX_THREADS=40 ; Required if used with WiFi +lib_deps = + ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX + ${esp32s3_base.lib_deps} \ No newline at end of file diff --git a/variants/tlora_t3s3_epaper/variant.h b/variants/tlora_t3s3_epaper/variant.h index 732869b20..1ed505420 100644 --- a/variants/tlora_t3s3_epaper/variant.h +++ b/variants/tlora_t3s3_epaper/variant.h @@ -2,7 +2,6 @@ #define SDCARD_USE_SPI1 // Display (E-Ink) -#define USE_EINK #define PIN_EINK_CS 15 #define PIN_EINK_BUSY 48 #define PIN_EINK_DC 16 From 78fa4c5c7057232b9b1f70e4e072310b76cb1ff8 Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 9 Apr 2025 13:31:40 -0400 Subject: [PATCH 041/238] Setup RenovateBot (#6535) --- .github/dependabot.yml | 29 --------------- .trunk/trunk.yaml | 1 + arch/esp32/esp32.ini | 10 +++++- arch/esp32/esp32c6.ini | 7 +++- arch/esp32/esp32s2.ini | 2 +- arch/esp32/esp32s3.ini | 1 - arch/nrf52/nrf52.ini | 8 +++-- arch/nrf52/nrf52840.ini | 1 + arch/portduino/portduino.ini | 7 +++- arch/rp2xx0/rp2040.ini | 12 +++++-- arch/rp2xx0/rp2350.ini | 14 +++++--- arch/stm32/stm32.ini | 9 +++-- platformio.ini | 49 +++++++++++++++++++++++++ renovate.json | 70 ++++++++++++++++++++++++++++++++++++ 14 files changed, 175 insertions(+), 45 deletions(-) delete mode 100644 .github/dependabot.yml create mode 100644 renovate.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index b14290be2..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,29 +0,0 @@ -#trunk-ignore-all(yamllint/quoted-strings): required by dependabot syntax check -version: 2 -updates: - - package-ecosystem: docker - directory: /.devcontainer - schedule: - interval: daily - time: "05:00" - timezone: US/Pacific - - package-ecosystem: docker - directory: / - schedule: - interval: daily - time: "05:00" - timezone: US/Pacific - - package-ecosystem: gitsubmodule - directory: / - schedule: - interval: daily - time: "05:00" - timezone: US/Pacific - ignore: - - dependency-name: protobufs - - package-ecosystem: github-actions - directory: /.github/workflows - schedule: - interval: daily - time: "05:00" - timezone: US/Pacific diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 903b4c298..e74c1a362 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,6 +8,7 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: + - renovate@39.235.2 - prettier@3.5.3 - trufflehog@3.88.23 - yamllint@1.37.0 diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index df3778002..3dfefbdb6 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -2,7 +2,9 @@ [esp32_base] extends = arduino_base custom_esp32_kind = esp32 -platform = platformio/espressif32@6.10.0 +platform = + # renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32 + platformio/espressif32@6.10.0 build_src_filter = ${arduino_base.build_src_filter} - - - - - @@ -45,11 +47,17 @@ lib_deps = ${networking_base.lib_deps} ${environmental_base.lib_deps} ${radiolib_base.lib_deps} + # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.zip + # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino h2zero/NimBLE-Arduino@^1.4.3 + # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip + # renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib lewisxhe/XPowersLib@^0.2.7 + # renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@^0.4.0 lib_ignore = diff --git a/arch/esp32/esp32c6.ini b/arch/esp32/esp32c6.ini index dba3bac08..e1cf955e8 100644 --- a/arch/esp32/esp32c6.ini +++ b/arch/esp32/esp32c6.ini @@ -1,6 +1,8 @@ [esp32c6_base] extends = esp32_base -platform = https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip +platform = + # renovate: datasource=git-refs depName=ESP32c6 platform-espressif32 packageName=https://github.com/Jason2866/platform-espressif32 gitBranch=Arduino/IDF5 + https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip build_flags = ${arduino_base.build_flags} -Wall @@ -24,8 +26,11 @@ lib_deps = ${networking_base.lib_deps} ${environmental_base.lib_deps} ${radiolib_base.lib_deps} + # renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib lewisxhe/XPowersLib@^0.2.7 + # renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@^0.4.0 build_src_filter = diff --git a/arch/esp32/esp32s2.ini b/arch/esp32/esp32s2.ini index 40fdc461a..0f97408b8 100644 --- a/arch/esp32/esp32s2.ini +++ b/arch/esp32/esp32s2.ini @@ -16,4 +16,4 @@ build_flags = lib_ignore = ${esp32_base.lib_ignore} NimBLE-Arduino - libpax \ No newline at end of file + libpax diff --git a/arch/esp32/esp32s3.ini b/arch/esp32/esp32s3.ini index 1cd0e2033..8d8b6899e 100644 --- a/arch/esp32/esp32s3.ini +++ b/arch/esp32/esp32s3.ini @@ -3,4 +3,3 @@ extends = esp32_base custom_esp32_kind = esp32s3 monitor_speed = 115200 - diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index ca12be6b1..127f46183 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -1,10 +1,14 @@ [nrf52_base] ; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files -platform = platformio/nordicnrf52@^10.8.0 +platform = + # renovate: datasource=custom.pio depName=platformio/nordicnrf52 packageName=platformio/platform/nordicnrf52 + platformio/nordicnrf52@^10.8.0 extends = arduino_base platform_packages = ; our custom Git version until they merge our PR + # TODO renovate platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf + # renovate: datasource=custom.pio depName=platformio/toolchain-gccarmnoneeabi packageName=platformio/tool/toolchain-gccarmnoneeabi platformio/toolchain-gccarmnoneeabi@~1.90301.0 build_type = debug @@ -28,4 +32,4 @@ lib_deps= lib_ignore = BluetoothOTA - lvgl \ No newline at end of file + lvgl diff --git a/arch/nrf52/nrf52840.ini b/arch/nrf52/nrf52840.ini index 0dab5d9ba..fb5ba9960 100644 --- a/arch/nrf52/nrf52840.ini +++ b/arch/nrf52/nrf52840.ini @@ -6,6 +6,7 @@ build_flags = ${nrf52_base.build_flags} lib_deps = ${nrf52_base.lib_deps} ${environmental_base.lib_deps} + # renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip ; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board. diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index e0488aeff..07e7db95c 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,8 @@ ; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated). [portduino_base] -platform = https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip +platform = + # renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop + https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip framework = arduino build_src_filter = @@ -24,8 +26,11 @@ lib_deps = ${env.lib_deps} ${networking_base.lib_deps} ${radiolib_base.lib_deps} + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@^0.4.0 + # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0 + # renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip build_flags = diff --git a/arch/rp2xx0/rp2040.ini b/arch/rp2xx0/rp2040.ini index 33fcfb211..cd7e684b4 100644 --- a/arch/rp2xx0/rp2040.ini +++ b/arch/rp2xx0/rp2040.ini @@ -1,8 +1,13 @@ ; Common settings for rp2040 Processor based targets [rp2040_base] -platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3 +platform = + # TODO renovate + https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 + ; For arduino-pico >= 4.4.3 extends = arduino_base -platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3 +platform_packages = + # TODO renovate + framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3 board_build.core = earlephilhower board_build.filesystem_size = 0.5m @@ -24,4 +29,5 @@ lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} ${radiolib_base.lib_deps} - rweather/Crypto \ No newline at end of file + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto + rweather/Crypto@0.4.0 diff --git a/arch/rp2xx0/rp2350.ini b/arch/rp2xx0/rp2350.ini index 841035c80..1c7af8be4 100644 --- a/arch/rp2xx0/rp2350.ini +++ b/arch/rp2xx0/rp2350.ini @@ -1,8 +1,13 @@ -; Common settings for rp2040 Processor based targets +; Common settings for rp2350 Processor based targets [rp2350_base] -platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3 +platform = + # TODO renovate + https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 + ; For arduino-pico >= 4.4.3 extends = arduino_base -platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3 +platform_packages = + # TODO renovate + framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3 board_build.core = earlephilhower board_build.filesystem_size = 0.5m @@ -21,4 +26,5 @@ lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} ${radiolib_base.lib_deps} - rweather/Crypto \ No newline at end of file + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto + rweather/Crypto@0.4.0 diff --git a/arch/stm32/stm32.ini b/arch/stm32/stm32.ini index c1b58bb82..dd190c9d4 100644 --- a/arch/stm32/stm32.ini +++ b/arch/stm32/stm32.ini @@ -1,7 +1,11 @@ [stm32_base] extends = arduino_base -platform = ststm32 -platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip +platform = + # renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32 + platformio/ststm32@19.1.0 +platform_packages = + # TODO renovate + platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip extra_scripts = ${env.extra_scripts} post:extra_scripts/extra_stm32.py @@ -35,6 +39,7 @@ debug_tool = stlink lib_deps = ${env.lib_deps} ${radiolib_base.lib_deps} + # renovate: datasource=git-refs depName=caveman99-stm32-Crypto packageName=https://github.com/caveman99/Crypto gitBranch=main https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip lib_ignore = diff --git a/platformio.ini b/platformio.ini index 749aa94c7..844ba261d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,12 +56,19 @@ build_flags = -Wno-missing-field-initializers 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 + # renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton mathertel/OneButton@2.6.1 + # 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 https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip + # renovate: datasource=git-refs depName=meshtastic-ArduinoThread packageName=https://github.com/meshtastic/ArduinoThread gitBranch=master https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip + # renovate: datasource=custom.pio depName=Nanopb packageName=nanopb/library/Nanopb nanopb/Nanopb@0.4.91 + # renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32 erriez/ErriezCRC32@1.0.1 ; Used for the code analysis in PIO Home / Inspect @@ -77,6 +84,7 @@ check_flags = framework = arduino lib_deps = ${env.lib_deps} + # renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL end2endzone/NonBlockingRTTTL@1.3.0 build_flags = ${env.build_flags} -Os build_src_filter = ${env.build_src_filter} - - @@ -84,57 +92,98 @@ build_src_filter = ${env.build_src_filter} - -.+)$"], + "datasourceTemplate": "github-releases", + "depNameTemplate": "meshtastic/web", + "versioningTemplate": "semver-coerced" + }, + { + "customType": "regex", + "description": "Match normal PIO dependencies", + "fileMatch": [".*\\.ini$"], + "matchStrings": [ + "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s+?.+?@(?.+?)\\s" + ], + "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}" + }, + { + "customType": "regex", + "description": "Match PIO zipped dependencies with github tag ref", + "fileMatch": [".*\\.ini$"], + "matchStrings": [ + "# renovate: datasource=github-tags(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s+?https:\/\/.+?archive\/(?.+?).zip\\s" + ], + "datasourceTemplate": "github-tags", + "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}" + }, + { + "customType": "regex", + "description": "Match PIO zipped dependencies with git commit ref", + "fileMatch": [".*\\.ini$"], + "matchStrings": [ + "# renovate: datasource=git-refs(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\sgitBranch=(?.+?)\\s+?https:\/\/.+?archive\/(?.+?).zip\\s" + ], + "datasourceTemplate": "git-refs", + "currentValueTemplate": "{{{gitBranch}}}", + "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}" + } + ], + "packageRules": [] +} From 0d8e39cc2ad748b5a45407c8c309d1913034989a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:46:58 -0500 Subject: [PATCH 042/238] chore(deps): update ntpclient to v3.2.1 (#6545) 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 844ba261d..5f3cbe7cd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -95,7 +95,7 @@ lib_deps = # renovate: datasource=custom.pio depName=PubSubClient packageName=knolleary/library/PubSubClient knolleary/PubSubClient@2.8 # renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient - arduino-libraries/NTPClient@3.1.0 + arduino-libraries/NTPClient@3.2.1 # renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog arcao/Syslog@2.0.0 From 8e40d88e2436e00a7a5f7f23312f90a07cff1430 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:56:36 -0500 Subject: [PATCH 043/238] chore(deps): update platform-native digest to 46f509b (#6540) 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 07e7db95c..7d2569c32 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/c5bd469ab9b5a6966321e09557b27d906961da63.zip + https://github.com/meshtastic/platform-native/archive/46f509b96ddce22d1bf38efc93319dfb3e4f5acf.zip framework = arduino build_src_filter = From 1888342a5701cfbab620d889f1893fbc93181930 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:57:21 -0500 Subject: [PATCH 044/238] chore(deps): update platformio/toolchain-gccarmnoneeabi to v1.140201.0 (#6546) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- arch/nrf52/nrf52.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index 127f46183..e311089ae 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -9,7 +9,7 @@ platform_packages = # TODO renovate platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf # renovate: datasource=custom.pio depName=platformio/toolchain-gccarmnoneeabi packageName=platformio/tool/toolchain-gccarmnoneeabi - platformio/toolchain-gccarmnoneeabi@~1.90301.0 + platformio/toolchain-gccarmnoneeabi@1.140201.0 build_type = debug build_flags = From 456f94511f45844dae9db709ec79486046c755d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:57:43 -0500 Subject: [PATCH 045/238] chore(deps): update libch341-spi-userspace digest to af9bc27 (#6539) 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 7d2569c32..6df3854f4 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -31,7 +31,7 @@ lib_deps = # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0 # renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main - https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip + https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip build_flags = ${arduino_base.build_flags} From daa03aba306375324c8a59d4464149bb9697633a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:02:42 -0500 Subject: [PATCH 046/238] chore(deps): update meshtastic-esp32_https_server digest to 896f177 (#6542) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- arch/esp32/esp32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 3dfefbdb6..5e15cb451 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -48,7 +48,7 @@ lib_deps = ${environmental_base.lib_deps} ${radiolib_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master - https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.zip + https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino h2zero/NimBLE-Arduino@^1.4.3 # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master From e98da27446a9878984f7197d06a3191c67e72a5c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:38:21 -0500 Subject: [PATCH 047/238] chore(deps): update ubuntu to v24 (#6541) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/sec_sast_semgrep_cron.yml | 2 +- .github/workflows/sec_sast_semgrep_pull.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sec_sast_semgrep_cron.yml b/.github/workflows/sec_sast_semgrep_cron.yml index db308c9f5..d7eef29b4 100644 --- a/.github/workflows/sec_sast_semgrep_cron.yml +++ b/.github/workflows/sec_sast_semgrep_cron.yml @@ -13,7 +13,7 @@ permissions: jobs: semgrep-full: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: image: semgrep/semgrep diff --git a/.github/workflows/sec_sast_semgrep_pull.yml b/.github/workflows/sec_sast_semgrep_pull.yml index 527a5c076..3707c91b8 100644 --- a/.github/workflows/sec_sast_semgrep_pull.yml +++ b/.github/workflows/sec_sast_semgrep_pull.yml @@ -6,7 +6,7 @@ permissions: read-all jobs: semgrep-diff: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: image: semgrep/semgrep From 1008a08c9911a849952158c9276ada5275de4dfa Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 9 Apr 2025 16:36:53 -0400 Subject: [PATCH 048/238] =?UTF-8?q?Revert=20"chore(deps):=20update=20platf?= =?UTF-8?q?ormio/toolchain-gccarmnoneeabi=20to=20v1.140201.=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1888342a5701cfbab620d889f1893fbc93181930. --- arch/nrf52/nrf52.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index e311089ae..127f46183 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -9,7 +9,7 @@ platform_packages = # TODO renovate platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf # renovate: datasource=custom.pio depName=platformio/toolchain-gccarmnoneeabi packageName=platformio/tool/toolchain-gccarmnoneeabi - platformio/toolchain-gccarmnoneeabi@1.140201.0 + platformio/toolchain-gccarmnoneeabi@~1.90301.0 build_type = debug build_flags = From 5c13f3451cf710a2f0e65b4f7872532c13520f71 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:10:01 -0500 Subject: [PATCH 049/238] chore(deps): update meshtastic-device-ui digest to 9345b03 (#6552) 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 5f3cbe7cd..3c052e6ad 100644 --- a/platformio.ini +++ b/platformio.ini @@ -107,7 +107,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/56ef8db7eb4dda44dc0c1ec5828044debbbc6d33.zip + https://github.com/meshtastic/device-ui/archive/9345b03d47d3e2be91125325842b8bced0daaf86.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 3694805938777e2be05385cf33f8b901fb840724 Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 9 Apr 2025 18:40:14 -0400 Subject: [PATCH 050/238] renovate: Link PIO deps to PlatformIO page (#6548) --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 417e17d9b..bf6ffdd4b 100644 --- a/renovate.json +++ b/renovate.json @@ -21,7 +21,7 @@ "defaultRegistryUrlTemplate": "https://api.registry.platformio.org/v3/packages/{{packageName}}", "format": "json", "transformTemplates": [ - "{\"releases\": [$map($.versions, function($v) { { \"version\": $v.name, \"releaseTimestamp\": $v.released_at } })] }" + "{\"releases\": [$map($.versions, function($v) { { \"version\": $v.name, \"releaseTimestamp\": $v.released_at } })], \"homepage\": $encodeUrl($join([\"https://registry.platformio.org/\",$.type,\"/\",$.owner.username,\"/\",$.name])) }" ] } }, From 06ce6f3e8a31e062f6ad5af8d1de165a62128cd4 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Thu, 10 Apr 2025 11:48:40 +1200 Subject: [PATCH 051/238] fix: remove redundant GPS code targeting Heltec T114 (#6497) --- src/gps/GPS.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 689f5e204..55f62d8ad 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -810,13 +810,6 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime) powerState = newState; LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState)); -#ifdef HELTEC_MESH_NODE_T114 - if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) { - _serial_gps->begin(serialSpeeds[speedSelect]); - } else if ((newState == GPS_OFF || newState == GPS_HARDSLEEP) && (oldState != GPS_OFF && oldState != GPS_HARDSLEEP)) { - _serial_gps->end(); - } -#endif switch (newState) { case GPS_ACTIVE: case GPS_IDLE: From 91f38797a8c770b693a30ee52f5be6d81bcf14c9 Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 9 Apr 2025 20:23:15 -0400 Subject: [PATCH 052/238] Don't renovate toolchain-gccarmnoneeabi (#6554) --- arch/nrf52/nrf52.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index 127f46183..d49d8920c 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -8,7 +8,7 @@ platform_packages = ; our custom Git version until they merge our PR # TODO renovate platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf - # renovate: datasource=custom.pio depName=platformio/toolchain-gccarmnoneeabi packageName=platformio/tool/toolchain-gccarmnoneeabi + ; Don't renovate toolchain-gccarmnoneeabi platformio/toolchain-gccarmnoneeabi@~1.90301.0 build_type = debug From 854d74f8db468e0be0db9e8c60bdbf43e22a4a5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 22:18:42 +0200 Subject: [PATCH 053/238] chore(deps): update meshtastic-device-ui digest to acf343b (#6559) 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 3c052e6ad..647114537 100644 --- a/platformio.ini +++ b/platformio.ini @@ -107,7 +107,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/9345b03d47d3e2be91125325842b8bced0daaf86.zip + https://github.com/meshtastic/device-ui/archive/acf343b73cedbdcd5838ba1407c054974a0b6914.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 4ef9eae69571517b6954d4292691603682c5938c Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 11 Apr 2025 07:02:55 -0400 Subject: [PATCH 054/238] Portduino: Set C standard to 17 (#6561) --- arch/portduino/portduino.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 6df3854f4..1d731f6b7 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -47,4 +47,5 @@ build_flags = -lyaml-cpp -li2c -luv + -std=gnu17 -std=c++17 From baa05aacf53b910b206b39fb4b55395d2103ab69 Mon Sep 17 00:00:00 2001 From: Ken Piper Date: Fri, 11 Apr 2025 06:04:37 -0500 Subject: [PATCH 055/238] fix: Correct underlying cause of T-Watch not functioning when set to a 16MB filesystem (#6563) * Fix maximum flash size in T-Watch S3 board definition * Revert "Fix: T-Watch-S3 has 8MB Flash (#6407)" This reverts commit 769f0623be6a7d7503c56bc1b6e468114dacdff0. --- bin/device-install.bat | 4 ++-- bin/device-install.sh | 2 +- boards/t-watch-s3.json | 6 +++--- variants/t-watch-s3/platformio.ini | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/device-install.bat b/bin/device-install.bat index 594d973f5..3ffca0b63 100755 --- a/bin/device-install.bat +++ b/bin/device-install.bat @@ -17,8 +17,8 @@ SET "LOGCOUNTER=0" SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone" SET "C3=esp32c3" @REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable. -SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core t-watch-s3 tracksenger" -SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite" +SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger" +SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3" GOTO getopts :help diff --git a/bin/device-install.sh b/bin/device-install.sh index 796626a9d..a43ccbdb4 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -22,7 +22,6 @@ BIGDB_8MB=( "icarus" "seeed-xiao-s3" "tbeam-s3-core" - "t-watch-s3" "tracksenger" ) BIGDB_16MB=( @@ -34,6 +33,7 @@ BIGDB_16MB=( "m5stack-cores3" "station-g2" "t-eth-elite" + "t-watch-s3" ) S3_VARIANTS=( "s3" diff --git a/boards/t-watch-s3.json b/boards/t-watch-s3.json index 51bb7cf4b..bae4f47b0 100644 --- a/boards/t-watch-s3.json +++ b/boards/t-watch-s3.json @@ -24,16 +24,16 @@ "mcu": "esp32s3", "variant": "t-watch-s3" }, - "connectivity": ["wifi", "bluetooth"], + "connectivity": ["wifi", "bluetooth", "lora"], "debug": { "openocd_target": "esp32s3.cfg" }, "frameworks": ["arduino"], "name": "LilyGo T-Watch 2020 V3", "upload": { - "flash_size": "8MB", + "flash_size": "16MB", "maximum_ram_size": 327680, - "maximum_size": 8388608, + "maximum_size": 16777216, "require_upload_port": true, "use_1200bps_touch": true, "wait_for_upload_port": true, diff --git a/variants/t-watch-s3/platformio.ini b/variants/t-watch-s3/platformio.ini index d650b1f11..f98237943 100644 --- a/variants/t-watch-s3/platformio.ini +++ b/variants/t-watch-s3/platformio.ini @@ -3,7 +3,7 @@ extends = esp32s3_base board = t-watch-s3 board_check = true -board_build.partitions = default_8MB.csv +board_build.partitions = default_16MB.csv upload_protocol = esptool build_flags = ${esp32_base.build_flags} From 7079f538edc1d90560453e5246218a95db5eba25 Mon Sep 17 00:00:00 2001 From: Kevin Jahaziel Leon Morales Date: Fri, 11 Apr 2025 04:26:30 -0700 Subject: [PATCH 056/238] feat: Add Electronic Cats variant for Catsniffer (#6483) * feat: Add Electronic Cats variant for catsniffer * fix: Trunk fmt * fix: Variant error --- variants/ec_catsniffer/platformio.ini | 15 ++++++++++ variants/ec_catsniffer/variant.cpp | 39 +++++++++++++++++++++++++ variants/ec_catsniffer/variant.h | 41 +++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 variants/ec_catsniffer/platformio.ini create mode 100644 variants/ec_catsniffer/variant.cpp create mode 100644 variants/ec_catsniffer/variant.h diff --git a/variants/ec_catsniffer/platformio.ini b/variants/ec_catsniffer/platformio.ini new file mode 100644 index 000000000..9afb44236 --- /dev/null +++ b/variants/ec_catsniffer/platformio.ini @@ -0,0 +1,15 @@ +[env:catsniffer] +extends = rp2040_base +board = rpipico +upload_protocol = picotool + +build_flags = ${rp2040_base.build_flags} + -DRPI_PICO + -Ivariants/ec_catsniffer + -DDEBUG_RP2040_PORT=Serial + # -DHW_SPI1_DEVICE + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" +lib_deps = + ${rp2040_base.lib_deps} +debug_build_flags = ${rp2040_base.build_flags}, -g +debug_tool = cmsis-dap \ No newline at end of file diff --git a/variants/ec_catsniffer/variant.cpp b/variants/ec_catsniffer/variant.cpp new file mode 100644 index 000000000..db5226541 --- /dev/null +++ b/variants/ec_catsniffer/variant.cpp @@ -0,0 +1,39 @@ +/* + 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 "wiring_constants.h" +#include "wiring_digital.h" + +#define CTF1 8 +#define CTF2 9 +#define CTF3 10 + +void initVariant() +{ + // Config the LoRa Switch + pinMode(CTF1, OUTPUT); + pinMode(CTF2, OUTPUT); + pinMode(CTF3, OUTPUT); + + digitalWrite(CTF1, HIGH); + digitalWrite(CTF2, LOW); + digitalWrite(CTF3, LOW); +} \ No newline at end of file diff --git a/variants/ec_catsniffer/variant.h b/variants/ec_catsniffer/variant.h new file mode 100644 index 000000000..400074e59 --- /dev/null +++ b/variants/ec_catsniffer/variant.h @@ -0,0 +1,41 @@ +// #define RADIOLIB_CUSTOM_ARDUINO 1 +// #define RADIOLIB_TONE_UNSUPPORTED 1 +// #define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED 1 + +#define ARDUINO_ARCH_AVR + +#define HAS_SCREEN 0 +#define HAS_GPS 0 +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +#define LED_PIN 27 + +#define USE_SX1262 + +#undef LORA_SCK +#undef LORA_MISO +#undef LORA_MOSI +#undef LORA_CS + +#define LORA_SCK 18 +#define LORA_MISO 16 +#define LORA_MOSI 19 +#define LORA_CS 17 // NSS + +#define LORA_DIO0 5 +#define LORA_RESET 24 +#define LORA_DIO1 4 +#define LORA_DIO2 23 +#define LORA_DIO3 25 +#define SX126X_RXEN 21 +#define SX126X_TXEN 20 + +#ifdef USE_SX1262 +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO0 +#define SX126X_BUSY LORA_DIO1 +#define SX126X_RESET LORA_RESET +// #define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 0 +#endif From e9570090193cca7d428dcd951220a280116b54e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Apr 2025 07:48:13 -0500 Subject: [PATCH 057/238] Upgrade trunk (#6564) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index e74c1a362..ba0dd97cc 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,7 +8,7 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - renovate@39.235.2 + - renovate@39.238.1 - prettier@3.5.3 - trufflehog@3.88.23 - yamllint@1.37.0 From e7ce910c3b6613ca50ce8133e3998758c3f07eaa Mon Sep 17 00:00:00 2001 From: Tavis Date: Fri, 11 Apr 2025 07:38:44 -1000 Subject: [PATCH 058/238] Add generic thread module (#5484) * compiling, untested * use INCLUDE not EXLUDE for option to include module * protobuf update * working genericthread module Update protobufs * use EXCLUDE style instead of INCLUDE * Update Modules.cpp --------- Co-authored-by: Ben Meadors --- platformio.ini | 1 + src/modules/GenericThreadModule.cpp | 28 ++++++++++++++++++++++++++++ src/modules/GenericThreadModule.h | 21 +++++++++++++++++++++ src/modules/Modules.cpp | 9 ++++++++- 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/modules/GenericThreadModule.cpp create mode 100644 src/modules/GenericThreadModule.h diff --git a/platformio.ini b/platformio.ini index 647114537..e1eabf952 100644 --- a/platformio.ini +++ b/platformio.ini @@ -50,6 +50,7 @@ build_flags = -Wno-missing-field-initializers -DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1 -DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1 -DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware + -DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1 #-DBUILD_EPOCH=$UNIX_TIME #-D OLED_PL=1 diff --git a/src/modules/GenericThreadModule.cpp b/src/modules/GenericThreadModule.cpp new file mode 100644 index 000000000..eb92566bd --- /dev/null +++ b/src/modules/GenericThreadModule.cpp @@ -0,0 +1,28 @@ +#include "GenericThreadModule.h" +#include "MeshService.h" +#include "configuration.h" +#include + +/* +Generic Thread Module allows for the execution of custom code at a set interval. +*/ +GenericThreadModule *genericThreadModule; + +GenericThreadModule::GenericThreadModule() : concurrency::OSThread("GenericThreadModule") {} + +int32_t GenericThreadModule::runOnce() +{ + + bool enabled = true; + if (!enabled) + return disable(); + + if (firstTime) { + // do something the first time we run + firstTime = 0; + LOG_INFO("first time GenericThread running"); + } + + LOG_INFO("GenericThread executing"); + return (my_interval); +} diff --git a/src/modules/GenericThreadModule.h b/src/modules/GenericThreadModule.h new file mode 100644 index 000000000..05f7946bb --- /dev/null +++ b/src/modules/GenericThreadModule.h @@ -0,0 +1,21 @@ +#pragma once + +#include "MeshModule.h" +#include "concurrency/OSThread.h" +#include "configuration.h" +#include +#include + +class GenericThreadModule : private concurrency::OSThread +{ + bool firstTime = 1; + + public: + GenericThreadModule(); + + protected: + unsigned int my_interval = 10000; // interval in millisconds + virtual int32_t runOnce() override; +}; + +extern GenericThreadModule *genericThreadModule; diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index e2a4a970c..1f2b50057 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -65,6 +65,10 @@ #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY #include "modules/Telemetry/PowerTelemetry.h" #endif +#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE +#include "modules/GenericThreadModule.h" +#endif + #ifdef ARCH_ESP32 #if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO #include "modules/esp32/AudioModule.h" @@ -131,6 +135,9 @@ void setupModules() #if !MESHTASTIC_EXCLUDE_DROPZONE dropzoneModule = new DropzoneModule(); +#endif +#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE + new GenericThreadModule(); #endif // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance // to a global variable. @@ -249,4 +256,4 @@ void setupModules() // NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra // acks routingModule = new RoutingModule(); -} \ No newline at end of file +} From e7d0837d014271c9d3e8a2b1d61b75102cf4184c Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 11 Apr 2025 16:54:53 -0400 Subject: [PATCH 059/238] Add Meshtastic Linux desktop metadata (#6568) --- bin/org.meshtastic.meshtasticd.desktop | 8 ++ bin/org.meshtastic.meshtasticd.metainfo.xml | 94 +++++++++++++++++++++ bin/org.meshtastic.meshtasticd.svg | 16 ++++ 3 files changed, 118 insertions(+) create mode 100644 bin/org.meshtastic.meshtasticd.desktop create mode 100644 bin/org.meshtastic.meshtasticd.metainfo.xml create mode 100644 bin/org.meshtastic.meshtasticd.svg diff --git a/bin/org.meshtastic.meshtasticd.desktop b/bin/org.meshtastic.meshtasticd.desktop new file mode 100644 index 000000000..215c7ee05 --- /dev/null +++ b/bin/org.meshtastic.meshtasticd.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Meshtastic +Comment=Meshtastic App +Exec=meshtasticd +Icon=org.meshtastic.meshtasticd +Terminal=true +Type=Application +Categories=Network;Chat;HamRadio; \ No newline at end of file diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml new file mode 100644 index 000000000..a9e6cbdf5 --- /dev/null +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -0,0 +1,94 @@ + + + org.meshtastic.meshtasticd + + Meshtastic + Decentralized mesh communication + + CC-BY-4.0 + GPL-3.0-or-later + + + Meshtastic + + + +

+ Meshtastic is an open source project for creating off-grid, affordable, and resilient communication with LoRa mesh networks. +

+
+ + org.meshtastic.meshtasticd.desktop + + + Network + Chat + HamRadio + + + mesh + LoRa + + + + keyboard + pointing + touch + + + 360 + + + + #97be89 + #206538 + + + + intense + intense + + + https://github.com/meshtastic/firmware/issues + https://meshtastic.org/ + https://opencollective.com/meshtastic + https://meshtastic.org/docs/software/linux/usage/ + https://github.com/meshtastic/firmware/ + + + + https://meshtastic.org/img/software/meshtastic-ui/mui_home_dashboard_dark.webp + Home Dashboard + + + https://meshtastic.org/img/software/meshtastic-ui/mui_initial_boot.webp + Setup + + + https://meshtastic.org/img/software/meshtastic-ui/mui_node_list_dark.webp + Nodes List + + + https://meshtastic.org/img/software/meshtastic-ui/mui_chat_list_dark.webp + Chats List + + + https://meshtastic.org/img/software/meshtastic-ui/mui_chat_message_dark.webp + Messages + + + https://meshtastic.org/img/software/meshtastic-ui/mui_map_dark.webp + Map + + + https://meshtastic.org/img/software/meshtastic-ui/mui_settings_dark.webp + Settings + + + + + + https://github.com/meshtastic/firmware/releases/tag/v2.6.4.b89355f + + +
\ No newline at end of file diff --git a/bin/org.meshtastic.meshtasticd.svg b/bin/org.meshtastic.meshtasticd.svg new file mode 100644 index 000000000..e6863f6a6 --- /dev/null +++ b/bin/org.meshtastic.meshtasticd.svg @@ -0,0 +1,16 @@ + + + +Created with Fabric.js 4.6.0 + + + + + + + + + + + + \ No newline at end of file From e4c2730f71f7002a374bcf17cd30f3dbc47b8036 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:47:36 +0200 Subject: [PATCH 060/238] chore(deps): update meshtastic-device-ui digest to 13f69c5 (#6567) 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 e1eabf952..b0d9d6237 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/acf343b73cedbdcd5838ba1407c054974a0b6914.zip + https://github.com/meshtastic/device-ui/archive/13f69c5f8d992b9e028d036bfc9b6485183e742f.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 3eb845eaae6421de8a642a7d7c85cef6ec7657e4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:28:37 -0500 Subject: [PATCH 061/238] chore(deps): update meshtastic-device-ui digest to 3cdb8a6 (#6572) 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 b0d9d6237..bba4dfe18 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/13f69c5f8d992b9e028d036bfc9b6485183e742f.zip + https://github.com/meshtastic/device-ui/archive/3cdb8a63039aa2cf426104ab02656996730f79fa.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 28e62e53e5dd83888ecf1bf5bd288c3684fcde62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 07:50:09 -0500 Subject: [PATCH 062/238] Upgrade trunk (#6581) Co-authored-by: sachaw <11172820+sachaw@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 ba0dd97cc..01e8f8d1b 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -4,7 +4,7 @@ cli: plugins: sources: - id: trunk - ref: v1.6.7 + ref: v1.6.8 uri: https://github.com/trunk-io/plugins lint: enabled: @@ -16,7 +16,7 @@ lint: - terrascan@1.19.9 - trivy@0.61.0 - taplo@0.9.3 - - ruff@0.11.4 + - ruff@0.11.5 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.4 From c4dc3472ac3d8f987bb905a570b2c2a5dbd785c2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 01:09:32 +0200 Subject: [PATCH 063/238] chore(deps): update meshtastic-device-ui digest to 3fde170 (#6586) 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 bba4dfe18..f22d92b2e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/3cdb8a63039aa2cf426104ab02656996730f79fa.zip + https://github.com/meshtastic/device-ui/archive/3fde170dca16863218cec133e05c5f2fc8d6e59a.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From b46aad85ccd765edf75a45b8434833a85d2910d2 Mon Sep 17 00:00:00 2001 From: "Aaron.Lee" <32860565+Heltec-Aaron-Lee@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:34:30 +0800 Subject: [PATCH 064/238] Add new hardware: Heltec MeshPocket (#6533) * Add Heltec MeshPocket. * MeshPocket source code update * Optimiz code for refresh border during full update. * Update Heltec MeshPocket json file info. --- boards/heltec_mesh_pocket.json | 54 +++++++ src/graphics/EInkDisplay2.cpp | 16 ++- src/graphics/EInkDisplay2.h | 4 + .../niche/Drivers/EInk/LCMEN2R13ECC1.cpp | 68 +++++++++ .../niche/Drivers/EInk/LCMEN2R13ECC1.h | 41 ++++++ src/platform/nrf52/architecture.h | 2 + src/power.h | 4 + variants/heltec_mesh_pocket/nicheGraphics.h | 107 ++++++++++++++ variants/heltec_mesh_pocket/platformio.ini | 92 ++++++++++++ variants/heltec_mesh_pocket/variant.cpp | 13 ++ variants/heltec_mesh_pocket/variant.h | 135 ++++++++++++++++++ 11 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 boards/heltec_mesh_pocket.json create mode 100644 src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp create mode 100644 src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h create mode 100644 variants/heltec_mesh_pocket/nicheGraphics.h create mode 100644 variants/heltec_mesh_pocket/platformio.ini create mode 100644 variants/heltec_mesh_pocket/variant.cpp create mode 100644 variants/heltec_mesh_pocket/variant.h diff --git a/boards/heltec_mesh_pocket.json b/boards/heltec_mesh_pocket.json new file mode 100644 index 000000000..a35387857 --- /dev/null +++ b/boards/heltec_mesh_pocket.json @@ -0,0 +1,54 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x4405"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"] + ], + "usb_product": "HT-n5262", + "mcu": "nrf52840", + "variant": "heltec_mesh_pocket", + "variants_dir": "variants", + "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", + "onboard_tools": ["jlink"], + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Heltec nrf (Adafruit BSP)", + "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://heltec.org/project/meshpocket/", + "vendor": "Heltec" + } + \ No newline at end of file diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index d2d373d24..737fcc3f0 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -181,7 +181,6 @@ bool EInkDisplay::connect() // Start HSPI hspi = new SPIClass(HSPI); hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS - // VExt already enabled in setup() // RTC GPIO hold disabled in setup() @@ -218,6 +217,21 @@ bool EInkDisplay::connect() adafruitDisplay->setRotation(1); adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT); } +#elif defined(HELTEC_MESH_POCKET) + { + spi1=&SPI1; + spi1->begin(); + // 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, *spi1); + adafruitDisplay = new GxEPD2_BW(*lowLevel); + + // Init GxEPD2 + adafruitDisplay->init(); + adafruitDisplay->setRotation(3); + } #endif return true; diff --git a/src/graphics/EInkDisplay2.h b/src/graphics/EInkDisplay2.h index 9c1c8d18e..93be197b0 100644 --- a/src/graphics/EInkDisplay2.h +++ b/src/graphics/EInkDisplay2.h @@ -73,6 +73,10 @@ class EInkDisplay : public OLEDDisplay SPIClass *hspi = NULL; #endif +#if defined(HELTEC_MESH_POCKET) + SPIClass *spi1 = NULL; +#endif + private: // FIXME quick hack to limit drawing to a very slow rate uint32_t lastDrawMsec = 0; diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp new file mode 100644 index 000000000..5e21c00f6 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp @@ -0,0 +1,68 @@ +#include "./LCMEN2R13ECC1.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +using namespace NicheGraphics::Drivers; + +// Map the display controller IC's output to the connected panel +void LCMEN2R13ECC1::configScanning() +{ + // "Driver output control" + sendCommand(0x01); + sendData(0xF9); + sendData(0x00); + sendData(0x00); + + // To-do: delete this method? + // Values set here might be redundant: F9, 00, 00 seems to be default +} + +// Specify which information is used to control the sequence of voltages applied to move the pixels +// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from +// the controller IC's OTP memory, when the update procedure begins. +void LCMEN2R13ECC1::configWaveform() +{ + switch (updateType) { + case FAST: + sendCommand(0x3C); // Border waveform: + sendData(0x85); + break; + + case FULL: + default: + // From OTP memory + break; + } +} + +void LCMEN2R13ECC1::configUpdateSequence() +{ + switch (updateType) { + case FAST: + sendCommand(0x22); // Set "update sequence" + sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh" + break; + + case FULL: + default: + sendCommand(0x22); // Set "update sequence" + sendData(0xF7); // Will load LUT from OTP memory + break; + } +} + +// Once the refresh operation has been started, +// begin periodically polling the display to check for completion, using the normal Meshtastic threading code +// Only used when refresh is "async" +void LCMEN2R13ECC1::detachFromUpdate() +{ + switch (updateType) { + case FAST: + return beginPolling(50, 800); // At least 500ms for fast refresh + case FULL: + default: + return beginPolling(100, 2500); // At least 2 seconds for full refresh + } +} + +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h new file mode 100644 index 000000000..7b0aed282 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h @@ -0,0 +1,41 @@ +/* + +E-Ink display driver + - SSD1680 + - Manufacturer: WISEVAST + - Size: 2.13 inch + - Resolution: 122px x 255px + - Flex connector marking: Soldering connector, no connector is needed + +*/ + +#pragma once + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +#include "configuration.h" + +#include "./SSD16XX.h" + +namespace NicheGraphics::Drivers +{ +class LCMEN2R13ECC1 : public SSD16XX +{ + // Display properties + private: + static constexpr uint32_t width = 122; + static constexpr uint32_t height = 250; + static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); + + public: + LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte + + protected: + virtual void configScanning() override; + virtual void configWaveform() override; + virtual void configUpdateSequence() override; + void detachFromUpdate() override; +}; + +} // namespace NicheGraphics::Drivers +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 4e8823063..21296c3fc 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -81,6 +81,8 @@ #define HW_VENDOR meshtastic_HardwareModel_MESHLINK #elif defined(SEEED_XIAO_NRF52840_KIT) #define HW_VENDOR meshtastic_HardwareModel_XIAO_NRF52_KIT +#elif defined(HELTEC_MESH_POCKET) +#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET #else #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN #endif diff --git a/src/power.h b/src/power.h index e9c0deb7c..a21f7d164 100644 --- a/src/power.h +++ b/src/power.h @@ -26,6 +26,10 @@ #define OCV_ARRAY 2700, 2560, 2540, 2520, 2500, 2460, 2420, 2400, 2380, 2320, 1500 #elif defined(TRACKER_T1000_E) #define OCV_ARRAY 4190, 4078, 4017, 3969, 3887, 3818, 3798, 3791, 3766, 3712, 3100 +#elif defined(HELTEC_MESH_POCKET_BATTERY_5000) +#define OCV_ARRAY 4300, 4240, 4120, 4000, 3888, 3800, 3740, 3698, 3655, 3580, 3400 +#elif defined(HELTEC_MESH_POCKET_BATTERY_10000) +#define OCV_ARRAY 4100, 4060, 3960, 3840, 3729, 3625, 3550, 3500, 3420, 3345, 3100 #else // LiIon #define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100 #endif diff --git a/variants/heltec_mesh_pocket/nicheGraphics.h b/variants/heltec_mesh_pocket/nicheGraphics.h new file mode 100644 index 000000000..352a9bc47 --- /dev/null +++ b/variants/heltec_mesh_pocket/nicheGraphics.h @@ -0,0 +1,107 @@ +#pragma once + +#include "configuration.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +// InkHUD-specific components +// --------------------------- +#include "graphics/niche/InkHUD/InkHUD.h" + +// Applets +#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h" +#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h" +#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" +#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" + +// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" +// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" + +// Shared NicheGraphics components +// -------------------------------- +#include "graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h" +#include "graphics/niche/Inputs/TwoButton.h" + +#include "graphics/niche/Fonts/FreeSans6pt7b.h" +#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" +#include + +void setupNicheGraphics() +{ + using namespace NicheGraphics; + + // SPI + // ----------------------------- + SPIClass *spi1=&SPI1; + spi1->begin(); + // Display is connected to SPI1 + + // E-Ink Driver + // ----------------------------- + // Use E-Ink driver + Drivers::EInk *driver = new Drivers::LCMEN2R13ECC1; + driver->begin(spi1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); + + // InkHUD + // ---------------------------- + + InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); + + // Set the driver + inkhud->setDriver(driver); + + // Set how many FAST updates per FULL update + // Set how unhealthy additional FAST updates beyond this number are + inkhud->setDisplayResilience(10, 1.5); + + // Prepare fonts + InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); + /* + // Font localization demo: Cyrillic + InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); + InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); + */ + + // Customize default settings + inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? + inkhud->persistence->settings.rotation = 3; // 270 degrees clockwise + inkhud->persistence->settings.userTiles.count = 1; // One tile only by default, keep things simple for new users + inkhud->persistence->settings.optionalMenuItems.nextTile = true; + + // Pick applets + inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown + inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 + // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); + // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); + + // Start running InkHUD + inkhud->begin(); + + // Buttons + // -------------------------- + + Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component + constexpr uint8_t MAIN_BUTTON = 0; + // constexpr uint8_t AUX_BUTTON = 1; + + // Setup the main user button + buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); + buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); + buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + + // Setup the aux button + // Bonus feature of VME213 + // buttons->setWiring(AUX_BUTTON, BUTTON_PIN_SECONDARY); + // buttons->setHandlerShortPress(AUX_BUTTON, []() { InkHUD::InkHUD::getInstance()->nextTile(); }); + buttons->start(); +} + +#endif \ No newline at end of file diff --git a/variants/heltec_mesh_pocket/platformio.ini b/variants/heltec_mesh_pocket/platformio.ini new file mode 100644 index 000000000..53f56e973 --- /dev/null +++ b/variants/heltec_mesh_pocket/platformio.ini @@ -0,0 +1,92 @@ +; First prototype nrf52840/sx1262 device +[env:heltec-mesh-pocket-5000] +extends = nrf52840_base +board = heltec_mesh_pocket +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/heltec_mesh_pocket + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -DHELTEC_MESH_POCKET + -DHELTEC_MESH_POCKET_BATTERY_5000 + -DUSE_EINK + -DEINK_DISPLAY_MODEL=GxEPD2_213_B74 + -DEINK_WIDTH=250 + -DEINK_HEIGHT=122 + -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted + -DEINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + -DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates +; -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated + -DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -DEINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" + -DEINK_HASQUIRK_WEAKFASTREFRESH ; Pixels set with fast-refresh are easy to clear, disrupted by sunlight + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pocket> +lib_deps = + ${nrf52840_base.lib_deps} + lewisxhe/PCF8563_Library@^1.0.1 + https://github.com/meshtastic/GxEPD2#b202ebfec6a4821e098cf7a625ba0f6f2400292d + + +[env:heltec-mesh-pocket-inkhud-5000] +extends = nrf52840_base, inkhud +board = heltec_mesh_pocket +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pocket> ${inkhud.build_src_filter} +build_flags = + ${inkhud.build_flags} + ${nrf52840_base.build_flags} + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -I variants/heltec_mesh_pocket + -D HELTEC_MESH_POCKET + -D HELTEC_MESH_POCKET_BATTERY_5000 +lib_deps = + ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX + ${nrf52840_base.lib_deps} + + +; First prototype nrf52840/sx1262 device +[env:heltec-mesh-pocket-10000] +extends = nrf52840_base +board = heltec_mesh_pocket +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/heltec_mesh_pocket + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -DHELTEC_MESH_POCKET + -DHELTEC_MESH_POCKET_BATTERY_10000 + -DUSE_EINK + -DEINK_DISPLAY_MODEL=GxEPD2_213_B74 + -DEINK_WIDTH=250 + -DEINK_HEIGHT=122 + -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted + -DEINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + -DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates +; -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated + -DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -DEINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" + -DEINK_HASQUIRK_WEAKFASTREFRESH ; Pixels set with fast-refresh are easy to clear, disrupted by sunlight + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pocket> +lib_deps = + ${nrf52840_base.lib_deps} + lewisxhe/PCF8563_Library@^1.0.1 + https://github.com/meshtastic/GxEPD2#b202ebfec6a4821e098cf7a625ba0f6f2400292d + + +[env:heltec-mesh-pocket-inkhud-10000] +extends = nrf52840_base, inkhud +board = heltec_mesh_pocket +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pocket> ${inkhud.build_src_filter} +build_flags = + ${inkhud.build_flags} + ${nrf52840_base.build_flags} + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -I variants/heltec_mesh_pocket + -D HELTEC_MESH_POCKET + -D HELTEC_MESH_POCKET_BATTERY_10000 +lib_deps = + ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX + ${nrf52840_base.lib_deps} diff --git a/variants/heltec_mesh_pocket/variant.cpp b/variants/heltec_mesh_pocket/variant.cpp new file mode 100644 index 000000000..20ba5f2ae --- /dev/null +++ b/variants/heltec_mesh_pocket/variant.cpp @@ -0,0 +1,13 @@ +#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}; + + diff --git a/variants/heltec_mesh_pocket/variant.h b/variants/heltec_mesh_pocket/variant.h new file mode 100644 index 000000000..89f06f358 --- /dev/null +++ b/variants/heltec_mesh_pocket/variant.h @@ -0,0 +1,135 @@ +#ifndef _VARIANT_HELTEC_NRF_ +#define _VARIANT_HELTEC_NRF_ +/** 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 (13) // 13 red (confirmed on 1.0 board) +#define LED_RED PIN_LED1 +#define LED_BLUE PIN_LED1 +#define LED_GREEN PIN_LED1 +#define LED_BUILTIN LED_BLUE +#define LED_CONN LED_BLUE +#define LED_STATE_ON 0 // State when LED is lit + +/* + * Buttons + */ +#define PIN_BUTTON1 (32 + 10) +// #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 + +/* +No longer populated on PCB +*/ +#define PIN_SERIAL2_RX (0 + 7) +#define PIN_SERIAL2_TX (0 + 8) +// #define PIN_SERIAL2_EN (0 + 17) + +/** + Wire Interfaces + */ +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (32+15) +#define PIN_WIRE_SCL (32+13) + +/* + * Lora radio + */ + +#define USE_SX1262 +#define SX126X_CS (0 + 26) // FIXME - we really should define LORA_CS instead +#define LORA_CS (0 + 26) +#define SX126X_DIO1 (0 + 16) +// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching +// #define SX1262_DIO3 (0 + 21) +// This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the +// main +// CPU? +#define SX126X_BUSY (0 + 15) +#define SX126X_RESET (0 + 12) +// Not really an E22 but TTGO seems to be trying to clone that +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// Display (E-Ink) +#define PIN_EINK_CS 24 +#define PIN_EINK_BUSY 32+6 +#define PIN_EINK_DC 31 +#define PIN_EINK_RES 32+4 +#define PIN_EINK_SCLK 22 +#define PIN_EINK_MOSI 20 + + +#define PIN_SPI1_MISO -1 +#define PIN_SPI1_MOSI PIN_EINK_MOSI +#define PIN_SPI1_SCK PIN_EINK_SCLK + + +/* + * GPS pins + */ + +#define PIN_SERIAL1_RX 32+5 +#define PIN_SERIAL1_TX 32+7 + +/* + * SPI Interfaces + */ +#define SPI_INTERFACES_COUNT 2 + +// For LORA, spi 0 +#define PIN_SPI_MISO (32 + 9) +#define PIN_SPI_MOSI (0 + 5) +#define PIN_SPI_SCK (0 + 4) + +// #define PIN_PWR_EN (0 + 6) + +// To debug via the segger JLINK console rather than the CDC-ACM serial device +// #define USE_SEGGER + +// Battery +// The battery sense is hooked to pin A0 (4) +// it is defined in the anlaolgue pin section of this file +// and has 12 bit resolution + +#define ADC_CTRL 32+2 +#define ADC_CTRL_ENABLED HIGH +#define BATTERY_PIN 29 +#define ADC_RESOLUTION 14 + +#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 (4.90F) + +#undef HAS_GPS +#define HAS_GPS 0 +#define HAS_RTC 0 +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file From 4e30023a4bd9a010d2f2b34d103897278ff898b4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 06:41:33 -0500 Subject: [PATCH 065/238] [create-pull-request] automated change (#6589) Co-authored-by: fifieldt <1287116+fifieldt@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 5a5ab103d..f9aa5cfd0 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 5a5ab103d2f6aa071fca29417475681a2cec5dcf +Subproject commit f9aa5cfd08cf14917fce54e5ebc0441b35ce32b3 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 191f9e121..46f9d8315 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -239,6 +239,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92, /* Reserved Fried Chicken ID for future use */ meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93, + /* Heltec Magnetic Power Bank with Meshtastic compatible */ + meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 ecd9f015d8f079a0170a06afdc1243655f5867db Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 06:41:52 -0500 Subject: [PATCH 066/238] chore(deps): update meshtastic-device-ui digest to da8fb5e (#6593) 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 f22d92b2e..cb36e412e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/3fde170dca16863218cec133e05c5f2fc8d6e59a.zip + https://github.com/meshtastic/device-ui/archive/da8fb5eaac7874c31508fad5252999ec82c02498.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 040a34fca8cd0a9581d575c3bf344e8fd82ddf84 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 15 Apr 2025 10:50:24 -0500 Subject: [PATCH 067/238] Switch to actually maintained thingsboard pubsubclient (#5204) * Switch to actually maintained thingsboard pubsubclient * .0 * TBPubSubClient * SetBufferSize is split into Send and Receive. * Update TBPubSubClient to 2.11 * Update platformio.ini Co-authored-by: Austin * Re-add setBufferSize fix --------- Co-authored-by: Tom Fifield Co-authored-by: Austin --- platformio.ini | 4 ++-- src/mqtt/MQTT.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index cb36e412e..85505d63a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -93,8 +93,8 @@ build_src_filter = ${env.build_src_filter} - - Date: Wed, 16 Apr 2025 07:37:09 +1000 Subject: [PATCH 068/238] Trunk fixes for heltec mesh pocket. (#6588) https://github.com/meshtastic/firmware/pull/6533 was merged without running trunk. This patch fixes the newly introduced trunk errors. --- boards/heltec_mesh_pocket.json | 99 +++++++++---------- src/graphics/EInkDisplay2.cpp | 2 +- .../niche/Drivers/EInk/LCMEN2R13ECC1.cpp | 22 ++--- .../niche/Drivers/EInk/LCMEN2R13ECC1.h | 10 +- variants/heltec_mesh_pocket/nicheGraphics.h | 2 +- variants/heltec_mesh_pocket/variant.cpp | 2 - variants/heltec_mesh_pocket/variant.h | 27 +++-- 7 files changed, 79 insertions(+), 85 deletions(-) diff --git a/boards/heltec_mesh_pocket.json b/boards/heltec_mesh_pocket.json index a35387857..e078c860c 100644 --- a/boards/heltec_mesh_pocket.json +++ b/boards/heltec_mesh_pocket.json @@ -1,54 +1,53 @@ { - "build": { - "arduino": { - "ldscript": "nrf52840_s140_v6.ld" - }, - "core": "nRF5", - "cpu": "cortex-m4", - "extra_flags": "-DNRF52840_XXAA", - "f_cpu": "64000000L", - "hwids": [ - ["0x239A", "0x4405"], - ["0x239A", "0x0029"], - ["0x239A", "0x002A"] - ], - "usb_product": "HT-n5262", - "mcu": "nrf52840", - "variant": "heltec_mesh_pocket", - "variants_dir": "variants", - "bsp": { - "name": "adafruit" - }, - "softdevice": { - "sd_flags": "-DS140", - "sd_name": "s140", - "sd_version": "6.1.1", - "sd_fwid": "0x00B6" - }, - "bootloader": { - "settings_addr": "0xFF000" - } + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" }, - "connectivity": ["bluetooth"], - "debug": { - "jlink_device": "nRF52840_xxAA", - "onboard_tools": ["jlink"], - "svd_path": "nrf52840.svd", - "openocd_target": "nrf52840-mdk-rs" + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x4405"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"] + ], + "usb_product": "HT-n5262", + "mcu": "nrf52840", + "variant": "heltec_mesh_pocket", + "variants_dir": "variants", + "bsp": { + "name": "adafruit" }, - "frameworks": ["arduino"], - "name": "Heltec nrf (Adafruit BSP)", - "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 + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "6.1.1", + "sd_fwid": "0x00B6" }, - "url": "https://heltec.org/project/meshpocket/", - "vendor": "Heltec" - } - \ No newline at end of file + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "onboard_tools": ["jlink"], + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Heltec nrf (Adafruit BSP)", + "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://heltec.org/project/meshpocket/", + "vendor": "Heltec" +} diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 737fcc3f0..5a2749482 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -219,7 +219,7 @@ bool EInkDisplay::connect() } #elif defined(HELTEC_MESH_POCKET) { - spi1=&SPI1; + spi1 = &SPI1; spi1->begin(); // VExt already enabled in setup() // RTC GPIO hold disabled in setup() diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp index 5e21c00f6..e9a663f80 100644 --- a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp @@ -23,16 +23,16 @@ void LCMEN2R13ECC1::configScanning() void LCMEN2R13ECC1::configWaveform() { switch (updateType) { - case FAST: - sendCommand(0x3C); // Border waveform: - sendData(0x85); - break; - - case FULL: - default: - // From OTP memory - break; - } + case FAST: + sendCommand(0x3C); // Border waveform: + sendData(0x85); + break; + + case FULL: + default: + // From OTP memory + break; + } } void LCMEN2R13ECC1::configUpdateSequence() @@ -65,4 +65,4 @@ void LCMEN2R13ECC1::detachFromUpdate() } } -#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h index 7b0aed282..b78e3bcca 100644 --- a/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h @@ -28,13 +28,13 @@ class LCMEN2R13ECC1 : public SSD16XX static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); public: - LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte + LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte protected: - virtual void configScanning() override; - virtual void configWaveform() override; - virtual void configUpdateSequence() override; - void detachFromUpdate() override; + virtual void configScanning() override; + virtual void configWaveform() override; + virtual void configUpdateSequence() override; + void detachFromUpdate() override; }; } // namespace NicheGraphics::Drivers diff --git a/variants/heltec_mesh_pocket/nicheGraphics.h b/variants/heltec_mesh_pocket/nicheGraphics.h index 352a9bc47..b697faa57 100644 --- a/variants/heltec_mesh_pocket/nicheGraphics.h +++ b/variants/heltec_mesh_pocket/nicheGraphics.h @@ -34,7 +34,7 @@ void setupNicheGraphics() // SPI // ----------------------------- - SPIClass *spi1=&SPI1; + SPIClass *spi1 = &SPI1; spi1->begin(); // Display is connected to SPI1 diff --git a/variants/heltec_mesh_pocket/variant.cpp b/variants/heltec_mesh_pocket/variant.cpp index 20ba5f2ae..bdded700b 100644 --- a/variants/heltec_mesh_pocket/variant.cpp +++ b/variants/heltec_mesh_pocket/variant.cpp @@ -9,5 +9,3 @@ const uint32_t g_ADigitalPinMap[] = { // P1 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; - - diff --git a/variants/heltec_mesh_pocket/variant.h b/variants/heltec_mesh_pocket/variant.h index 89f06f358..79f47bd0e 100644 --- a/variants/heltec_mesh_pocket/variant.h +++ b/variants/heltec_mesh_pocket/variant.h @@ -49,16 +49,16 @@ No longer populated on PCB */ #define WIRE_INTERFACES_COUNT 1 -#define PIN_WIRE_SDA (32+15) -#define PIN_WIRE_SCL (32+13) +#define PIN_WIRE_SDA (32 + 15) +#define PIN_WIRE_SCL (32 + 13) /* * Lora radio */ #define USE_SX1262 -#define SX126X_CS (0 + 26) // FIXME - we really should define LORA_CS instead -#define LORA_CS (0 + 26) +#define SX126X_CS (0 + 26) // FIXME - we really should define LORA_CS instead +#define LORA_CS (0 + 26) #define SX126X_DIO1 (0 + 16) // Note DIO2 is attached internally to the module to an analog switch for TX/RX switching // #define SX1262_DIO3 (0 + 21) @@ -72,25 +72,23 @@ No longer populated on PCB #define SX126X_DIO3_TCXO_VOLTAGE 1.8 // Display (E-Ink) -#define PIN_EINK_CS 24 -#define PIN_EINK_BUSY 32+6 -#define PIN_EINK_DC 31 -#define PIN_EINK_RES 32+4 +#define PIN_EINK_CS 24 +#define PIN_EINK_BUSY 32 + 6 +#define PIN_EINK_DC 31 +#define PIN_EINK_RES 32 + 4 #define PIN_EINK_SCLK 22 #define PIN_EINK_MOSI 20 - #define PIN_SPI1_MISO -1 #define PIN_SPI1_MOSI PIN_EINK_MOSI #define PIN_SPI1_SCK PIN_EINK_SCLK - /* * GPS pins */ -#define PIN_SERIAL1_RX 32+5 -#define PIN_SERIAL1_TX 32+7 +#define PIN_SERIAL1_RX 32 + 5 +#define PIN_SERIAL1_TX 32 + 7 /* * SPI Interfaces @@ -112,7 +110,7 @@ No longer populated on PCB // it is defined in the anlaolgue pin section of this file // and has 12 bit resolution -#define ADC_CTRL 32+2 +#define ADC_CTRL 32 + 2 #define ADC_CTRL_ENABLED HIGH #define BATTERY_PIN 29 #define ADC_RESOLUTION 14 @@ -124,12 +122,11 @@ No longer populated on PCB #define VBAT_AR_INTERNAL AR_INTERNAL_3_0 #define ADC_MULTIPLIER (4.90F) -#undef HAS_GPS +#undef HAS_GPS #define HAS_GPS 0 #define HAS_RTC 0 #ifdef __cplusplus } #endif - #endif \ No newline at end of file From 7e8294dfad233e883c58005cff549812587145ff Mon Sep 17 00:00:00 2001 From: Kalle Lilja <15094562+ThatKalle@users.noreply.github.com> Date: Wed, 16 Apr 2025 00:57:21 +0200 Subject: [PATCH 069/238] FlatHub: bump metainfo.xml on release (#6578) * add bump_metainfo.py * bump org.meshtastic.meshtasticd.metainfo.xml on release * update bump-version job to trigger on published * use defusedxml.ElementTree parse * move bump_metainfo, use requirements.txt * add bin/bump_metainfo/requirements.txt to renovate * Switch to short version string * Bump version.properties to 2.6.6 * change version format * remove url * Add url back in * Update url format * manual add 2.6.6 * consolidate into one PR * update run steps * add ability to add date if missing * update pull request title * add comments * remove quote changes --------- Co-authored-by: Austin --- .github/workflows/release_channels.yml | 32 ++++++--- bin/bump_metainfo/bump_metainfo.py | 72 +++++++++++++++++++++ bin/bump_metainfo/requirements.txt | 1 + bin/org.meshtastic.meshtasticd.metainfo.xml | 10 ++- renovate.json | 3 + version.properties | 2 +- 6 files changed, 109 insertions(+), 11 deletions(-) create mode 100755 bin/bump_metainfo/bump_metainfo.py create mode 100644 bin/bump_metainfo/requirements.txt diff --git a/.github/workflows/release_channels.yml b/.github/workflows/release_channels.yml index 710e8e51d..eece12346 100644 --- a/.github/workflows/release_channels.yml +++ b/.github/workflows/release_channels.yml @@ -46,11 +46,14 @@ jobs: # Create a PR to bump version when a release is Published bump-version: - if: ${{ github.event.release.published }} + if: github.event.action == 'published' runs-on: ubuntu-latest permissions: pull-requests: write contents: write + defaults: + run: + shell: bash steps: - name: Checkout uses: actions/checkout@v4 @@ -63,29 +66,42 @@ jobs: - name: Get release version string run: | echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT id: version env: BUILD_LOCATION: local - name: Bump version.properties - run: >- - bin/bump_version.py + run: | + # Bump version.properties + chmod +x ./bin/bump_version.py + ./bin/bump_version.py - name: Ensure debian deps are installed - shell: bash run: | sudo apt-get update -y --fix-missing sudo apt-get install -y devscripts - name: Update debian changelog - run: >- - debian/ci_changelog.sh + run: | + # Update debian changelog + chmod +x ./debian/ci_changelog.sh + ./debian/ci_changelog.sh - - name: Create version.properties pull request + - name: Bump org.meshtastic.meshtasticd.metainfo.xml + run: | + # Bump org.meshtastic.meshtasticd.metainfo.xml + pip install -r bin/bump_metainfo/requirements.txt -q + chmod +x ./bin/bump_metainfo/bump_metainfo.py + ./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.version.outputs.short }}" + + - name: Create Bumps pull request uses: peter-evans/create-pull-request@v7 with: - title: Bump version.properties + title: Bump release version + commit-message: automated bumps add-paths: | version.properties debian/changelog + bin/org.meshtastic.meshtasticd.metainfo.xml diff --git a/bin/bump_metainfo/bump_metainfo.py b/bin/bump_metainfo/bump_metainfo.py new file mode 100755 index 000000000..290cbae79 --- /dev/null +++ b/bin/bump_metainfo/bump_metainfo.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +import argparse +import xml.etree.ElementTree as ET +from defusedxml.ElementTree import parse +from datetime import datetime, timezone + + +# Indent by 2 spaces to align with xml formatting. +def indent(elem, level=0): + i = "\n" + level * " " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + for child in elem: + indent(child, level + 1) + if not child.tail or not child.tail.strip(): + child.tail = i + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + + +def main(): + parser = argparse.ArgumentParser( + description="Prepend new release entry to metainfo.xml file.") + parser.add_argument("--file", help="Path to the metainfo.xml file", + default="org.meshtastic.meshtasticd.metainfo.xml") + parser.add_argument("version", help="Version string (e.g. 2.6.4)") + parser.add_argument("--date", help="Release date (YYYY-MM-DD), defaults to today", + default=datetime.now(timezone.utc).date().isoformat()) + + args = parser.parse_args() + + tree = parse(args.file) + root = tree.getroot() + + releases = root.find('releases') + if releases is None: + raise RuntimeError(" element not found in XML.") + + existing_versions = { + release.get('version'): release + for release in releases.findall('release') + } + existing_release = existing_versions.get(args.version) + + if existing_release is not None: + if not existing_release.get('date'): + print(f"Version {args.version} found without date. Adding date...") + existing_release.set('date', args.date) + else: + print( + f"Version {args.version} is already present with date, skipping insertion.") + else: + new_release = ET.Element('release', { + 'version': args.version, + 'date': args.date + }) + url = ET.SubElement(new_release, 'url', {'type': 'details'}) + url.text = f"https://github.com/meshtastic/firmware/releases?q=tag%3Av{args.version}" + + releases.insert(0, new_release) + + indent(releases, level=1) + releases.tail = "\n" + + print(f"Inserted new release: {args.version}") + + tree.write(args.file, encoding='UTF-8', xml_declaration=True) + + +if __name__ == "__main__": + main() diff --git a/bin/bump_metainfo/requirements.txt b/bin/bump_metainfo/requirements.txt new file mode 100644 index 000000000..09dd20d24 --- /dev/null +++ b/bin/bump_metainfo/requirements.txt @@ -0,0 +1 @@ +defusedxml==0.7.1 diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index a9e6cbdf5..cb921fcb3 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,8 +87,14 @@ - - https://github.com/meshtastic/firmware/releases/tag/v2.6.4.b89355f + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6 + + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5 + + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4 \ No newline at end of file diff --git a/renovate.json b/renovate.json index bf6ffdd4b..11d35aff8 100644 --- a/renovate.json +++ b/renovate.json @@ -13,6 +13,9 @@ "git-submodules": { "enabled": true }, + "pip_requirements": { + "fileMatch": ["bin/bump_metainfo/requirements.txt"] + }, "commitMessageTopic": "{{depName}}", "labels": ["dependencies"], "customDatasources": { diff --git a/version.properties b/version.properties index 0b46aeec6..8f5953fdc 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 5 +build = 6 From cf5c8de92e21acf7b5814225b225ceac7d87553b Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Wed, 16 Apr 2025 13:33:44 +1200 Subject: [PATCH 070/238] Fix spurious button presses on some T-Echos (#6590) Co-authored-by: Ben Meadors --- src/graphics/niche/Inputs/TwoButton.cpp | 2 +- src/mesh/RadioLibInterface.cpp | 8 ++++++++ src/mesh/RadioLibInterface.h | 5 +++++ variants/t-echo/nicheGraphics.h | 19 +++++++++++++++++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/graphics/niche/Inputs/TwoButton.cpp b/src/graphics/niche/Inputs/TwoButton.cpp index 1e91d9080..bd29f981d 100644 --- a/src/graphics/niche/Inputs/TwoButton.cpp +++ b/src/graphics/niche/Inputs/TwoButton.cpp @@ -181,7 +181,7 @@ void TwoButton::isrSecondary() void TwoButton::startThread() { if (!OSThread::enabled) { - OSThread::setInterval(50); + OSThread::setInterval(10); OSThread::enabled = true; } } diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index a6faebff4..e3ef58f14 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -210,6 +210,14 @@ bool RadioLibInterface::canSleep() return res; } +/** Allow other firmware components to ask whether we are currently sending a packet +Initially implemented to protect T-Echo's capacitive touch button from spurious presses during tx +*/ +bool RadioLibInterface::isSending() +{ + return sendingPacket != NULL; +} + /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ bool RadioLibInterface::cancelSending(NodeNum from, PacketId id) { diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index b24879eaf..9622bd625 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -132,6 +132,11 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified */ virtual bool isActivelyReceiving() = 0; + /** Are we are currently sending a packet? + * This method is public, intending to expose this information to other firmware components + */ + virtual bool isSending(); + /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ virtual bool cancelSending(NodeNum from, PacketId id) override; diff --git a/variants/t-echo/nicheGraphics.h b/variants/t-echo/nicheGraphics.h index 5862dcdfb..af310db25 100644 --- a/variants/t-echo/nicheGraphics.h +++ b/variants/t-echo/nicheGraphics.h @@ -29,6 +29,12 @@ #include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" #include +// Special case - fix T-Echo's touch button +// ---------------------------------------- +// On a handful of T-Echos, LoRa TX triggers the capacitive touch +// To avoid this, we lockout the button during TX +#include "mesh/RadioLibInterface.h" + void setupNicheGraphics() { using namespace NicheGraphics; @@ -115,13 +121,22 @@ void setupNicheGraphics() buttons->setWiring(TOUCH_BUTTON, PIN_BUTTON_TOUCH); buttons->setTiming(TOUCH_BUTTON, 50, 5000); // 5 seconds before latch - limited by T-Echo's capacitive touch IC buttons->setHandlerDown(TOUCH_BUTTON, [backlight]() { + // Discard the button press if radio is active + // Rare hardware fault: LoRa activity triggers touch button + if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending()) + return; + + // Backlight on (while held) backlight->peek(); - InkHUD::InkHUD::getInstance()->persistence->settings.optionalMenuItems.backlight = - false; // We've proved user still has the button. No need to make backlight togglable via the menu. + + // Handler has run, which confirms touch button wasn't removed as part of DIY build. + // No longer need the fallback backlight toggle in menu. + InkHUD::InkHUD::getInstance()->persistence->settings.optionalMenuItems.backlight = false; }); buttons->setHandlerLongPress(TOUCH_BUTTON, [backlight]() { backlight->latch(); }); buttons->setHandlerShortPress(TOUCH_BUTTON, [backlight]() { backlight->off(); }); + // Begin handling button events buttons->start(); } From 1138f74e2c025852534cd529248de45e6a6347ac Mon Sep 17 00:00:00 2001 From: Niklas <44636701+MayNiklas@users.noreply.github.com> Date: Wed, 16 Apr 2025 03:39:13 +0200 Subject: [PATCH 071/238] fix: set upload_speed for tlora_v1_3 & tlora_v2_1_16 (#6595) --- variants/tlora_v1_3/platformio.ini | 3 ++- variants/tlora_v2_1_16/platformio.ini | 3 ++- variants/tlora_v2_1_16_tcxo/platformio.ini | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/variants/tlora_v1_3/platformio.ini b/variants/tlora_v1_3/platformio.ini index 99df28e56..c5eca589f 100644 --- a/variants/tlora_v1_3/platformio.ini +++ b/variants/tlora_v1_3/platformio.ini @@ -3,4 +3,5 @@ board_level = extra extends = esp32_base board = ttgo-lora32-v1 build_flags = - ${esp32_base.build_flags} -D TLORA_V1_3 -I variants/tlora_v1_3 \ No newline at end of file + ${esp32_base.build_flags} -D TLORA_V1_3 -I variants/tlora_v1_3 +upload_speed = 115200 \ No newline at end of file diff --git a/variants/tlora_v2_1_16/platformio.ini b/variants/tlora_v2_1_16/platformio.ini index 351f71676..4253cc6af 100644 --- a/variants/tlora_v2_1_16/platformio.ini +++ b/variants/tlora_v2_1_16/platformio.ini @@ -4,4 +4,5 @@ board = ttgo-lora32-v21 board_check = true build_flags = ${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/tlora_v2_1_16 - -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. \ No newline at end of file + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. +upload_speed = 115200 \ No newline at end of file diff --git a/variants/tlora_v2_1_16_tcxo/platformio.ini b/variants/tlora_v2_1_16_tcxo/platformio.ini index 538fd81b0..5c7cb7eb3 100644 --- a/variants/tlora_v2_1_16_tcxo/platformio.ini +++ b/variants/tlora_v2_1_16_tcxo/platformio.ini @@ -7,4 +7,5 @@ build_flags = -D TLORA_V2_1_16 -I variants/tlora_v2_1_16 -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. - -D LORA_TCXO_GPIO=33 \ No newline at end of file + -D LORA_TCXO_GPIO=33 +upload_speed = 115200 \ No newline at end of file From 447703197174d38e5326cdd70e3edaa0276bb82a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:46:06 +0200 Subject: [PATCH 072/238] [create-pull-request] automated change (#6599) --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/protobufs b/protobufs index f9aa5cfd0..b982b36df 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit f9aa5cfd08cf14917fce54e5ebc0441b35ce32b3 +Subproject commit b982b36dfab2e96b8f8be90af891c68ebf8790c2 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 46f9d8315..36bded9b2 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -241,6 +241,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93, /* Heltec Magnetic Power Bank with Meshtastic compatible */ meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94, + /* Seeed Solar Node */ + meshtastic_HardwareModel_SEEED_SOLAR_NODE = 95, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 64c8bde04a222aea6694d40897b3f5db996ce4bf Mon Sep 17 00:00:00 2001 From: Benjamin Kyd Date: Wed, 16 Apr 2025 09:12:23 +0100 Subject: [PATCH 073/238] Update platformio.ini to exclude unused modules from t1000-e (#6584) * Update platformio.ini to exclude unused modules * Add No EXT GPIO flag and also correct some exclusions in main * CANNEDMSG != CANNEDMESSAGES * Remove NO_EXT_GPIO --- src/main.cpp | 8 ++++---- variants/tracker-t1000-e/platformio.ini | 6 +++++- variants/tracker-t1000-e/variant.h | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bfbd73a43..535a7afa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1310,7 +1310,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AUDIO_CONFIG; #endif // Option to explicitly include canned messages for edge cases, e.g. niche graphics -#if (!HAS_SCREEN && NO_EXT_GPIO) && !MESHTASTIC_INCLUDE_CANNEDMSG +#if (!HAS_SCREEN || NO_EXT_GPIO) || MESHTASTIC_EXCLUDE_CANNEDMESSAGES deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG; #endif #if NO_EXT_GPIO @@ -1318,11 +1318,11 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() #endif // Only edge case here is if we apply this a device with built in Accelerometer and want to detect interrupts // We'll have to macro guard against those targets potentially -#if NO_EXT_GPIO +#if NO_EXT_GPIO || MESHTASTIC_EXCLUDE_DETECTIONSENSOR deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_DETECTIONSENSOR_CONFIG; #endif -// If we don't have any GPIO and we don't have GPS, no purpose in having serial config -#if NO_EXT_GPIO && NO_GPS +// If we don't have any GPIO and we don't have GPS OR we don't want too - no purpose in having serial config +#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG; #endif #ifndef ARCH_ESP32 diff --git a/variants/tracker-t1000-e/platformio.ini b/variants/tracker-t1000-e/platformio.ini index 8c3c97e6c..64da61434 100644 --- a/variants/tracker-t1000-e/platformio.ini +++ b/variants/tracker-t1000-e/platformio.ini @@ -5,6 +5,10 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/tracker-t1000-e -Isrc/plat -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL=1 + -DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -DMESHTASTIC_EXCLUDE_SCREEN=1 + -DMESHTASTIC_EXCLUDE_DETECTIONSENSOR=1 + -DMESHTASTIC_EXCLUDE_WIFI=1 board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/tracker-t1000-e> lib_deps = @@ -12,4 +16,4 @@ lib_deps = https://github.com/meshtastic/QMA6100P_Arduino_Library/archive/14c900b8b2e4feaac5007a7e41e0c1b7f0841136.zip debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) -upload_protocol = nrfutil \ No newline at end of file +upload_protocol = nrfutil diff --git a/variants/tracker-t1000-e/variant.h b/variants/tracker-t1000-e/variant.h index 0d98a3033..81b4ef3fb 100644 --- a/variants/tracker-t1000-e/variant.h +++ b/variants/tracker-t1000-e/variant.h @@ -152,6 +152,8 @@ extern "C" { #define T1000X_NTC_PIN (0 + 31) // P0.31/AIN7 #define T1000X_LUX_PIN (0 + 29) // P0.29/AIN5 +#define HAS_SCREEN 0 + #ifdef __cplusplus } #endif @@ -160,4 +162,4 @@ extern "C" { * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif // _VARIANT_TRACKER_T1000_E_ \ No newline at end of file +#endif // _VARIANT_TRACKER_T1000_E_ From e5cd0d613cc2cdf643e162cda80aa9d24af3b4f8 Mon Sep 17 00:00:00 2001 From: "Aaron.Lee" <32860565+Heltec-Aaron-Lee@users.noreply.github.com> Date: Wed, 16 Apr 2025 17:20:12 +0800 Subject: [PATCH 074/238] Make startup screen show the short ID (#6591) * Update the short ID show on the boot up screen function --- .../InkHUD/Applets/System/Logo/LogoApplet.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp index 520b3ef65..89bdb0bc7 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp @@ -11,10 +11,19 @@ InkHUD::LogoApplet::LogoApplet() : concurrency::OSThread("LogoApplet") OSThread::setIntervalFromNow(8 * 1000UL); OSThread::enabled = true; - textLeft = ""; - textRight = ""; - textTitle = xstr(APP_VERSION_SHORT); - fontTitle = fontSmall; + // During onboarding, show the default short name as well as the version string + // This behavior assists manufacturers during mass production, and should not be modified without good reason + if (!settings->tips.safeShutdownSeen) { + fontTitle = fontLarge; + textLeft = xstr(APP_VERSION_SHORT); + textRight = owner.short_name; + textTitle = "Meshtastic"; + } else { + fontTitle = fontSmall; + textLeft = ""; + textRight = ""; + textTitle = xstr(APP_VERSION_SHORT); + } bringToForeground(); // This is then drawn with a FULL refresh by Renderer::begin From 5699d8632ef27d527e6907735208cbdec51d1de2 Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 16 Apr 2025 05:21:31 -0400 Subject: [PATCH 075/238] Debian: use native-tft compile target (#6580) --- debian/ci_pack_sdeb.sh | 4 ++-- debian/control | 5 ++++- debian/meshtasticd.install | 10 +++++----- debian/rules | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/debian/ci_pack_sdeb.sh b/debian/ci_pack_sdeb.sh index c0cea0010..81e681e0c 100755 --- a/debian/ci_pack_sdeb.sh +++ b/debian/ci_pack_sdeb.sh @@ -5,8 +5,8 @@ export PLATFORMIO_PACKAGES_DIR=pio/packages export PLATFORMIO_CORE_DIR=pio/core # Download libraries to `pio` -platformio pkg install -e native -platformio pkg install -e native -t platformio/tool-scons@4.40502.0 +platformio pkg install -e native-tft +platformio pkg install -e native-tft -t platformio/tool-scons@4.40502.0 # Compress `pio` directory to prevent dh_clean from sanitizing it tar -cf pio.tar pio/ rm -rf pio diff --git a/debian/control b/debian/control index 693cd6aa5..9277f6f54 100644 --- a/debian/control +++ b/debian/control @@ -21,7 +21,10 @@ Build-Depends: debhelper-compat (= 13), openssl, libssl-dev, libulfius-dev, - liborcania-dev + liborcania-dev, + libx11-dev, + libinput-dev, + libxkbcommon-x11-dev Standards-Version: 4.6.2 Homepage: https://github.com/meshtastic/firmware Rules-Requires-Root: no diff --git a/debian/meshtasticd.install b/debian/meshtasticd.install index da1b0685d..6b6b5a361 100644 --- a/debian/meshtasticd.install +++ b/debian/meshtasticd.install @@ -1,8 +1,8 @@ -.pio/build/native/meshtasticd usr/sbin +.pio/build/native-tft/meshtasticd usr/sbin -bin/config.yaml etc/meshtasticd -bin/config.d/* etc/meshtasticd/available.d +bin/config.yaml etc/meshtasticd +bin/config.d/* etc/meshtasticd/available.d -bin/meshtasticd.service lib/systemd/system +bin/meshtasticd.service lib/systemd/system -web/* usr/share/meshtasticd/web \ No newline at end of file +web/* usr/share/meshtasticd/web \ No newline at end of file diff --git a/debian/rules b/debian/rules index 0612ba352..0b5d1ac57 100755 --- a/debian/rules +++ b/debian/rules @@ -26,7 +26,7 @@ override_dh_auto_build: mkdir -p web && tar -xf web.tar -C web gunzip web/ -r # Build with platformio - $(PIO_ENV) platformio run -e native + $(PIO_ENV) platformio run -e native-tft # Move the binary and default config to the correct name - mv .pio/build/native/program .pio/build/native/meshtasticd + mv .pio/build/native-tft/program .pio/build/native-tft/meshtasticd cp bin/config-dist.yaml bin/config.yaml From 4a9a59342a3f6227fb8f48807314e1bbb2b6f650 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Wed, 16 Apr 2025 11:23:52 +0200 Subject: [PATCH 076/238] Create lora-piggystick-lr1121.yaml (#6600) --- bin/config.d/lora-piggystick-lr1121.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 bin/config.d/lora-piggystick-lr1121.yaml diff --git a/bin/config.d/lora-piggystick-lr1121.yaml b/bin/config.d/lora-piggystick-lr1121.yaml new file mode 100644 index 000000000..348db61b1 --- /dev/null +++ b/bin/config.d/lora-piggystick-lr1121.yaml @@ -0,0 +1,11 @@ +Lora: + Module: lr1121 + CS: 0 + IRQ: 6 + Reset: 2 + Busy: 4 + spidev: ch341 + DIO3_TCXO_VOLTAGE: 1.8 +# USB_Serialnum: 12345678 + USB_PID: 0x5512 + USB_VID: 0x1A86 From e0dafc3618ae8ce6c115caafdd7a1f68fdb94df6 Mon Sep 17 00:00:00 2001 From: Niklas <44636701+MayNiklas@users.noreply.github.com> Date: Wed, 16 Apr 2025 13:15:16 +0200 Subject: [PATCH 077/238] fix: set upload_speed for tlora_v1 (#6601) --- variants/tlora_v1/platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/variants/tlora_v1/platformio.ini b/variants/tlora_v1/platformio.ini index 65ec4bcdc..17fc71d72 100644 --- a/variants/tlora_v1/platformio.ini +++ b/variants/tlora_v1/platformio.ini @@ -3,4 +3,5 @@ board_level = extra extends = esp32_base board = ttgo-lora32-v1 build_flags = - ${esp32_base.build_flags} -D TLORA_V1 -I variants/tlora_v1 \ No newline at end of file + ${esp32_base.build_flags} -D TLORA_V1 -I variants/tlora_v1 +upload_speed = 115200 \ No newline at end of file From 816d948ee53d9125001945963a5cd9fe800ae980 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 06:15:33 -0500 Subject: [PATCH 078/238] Upgrade trunk (#6592) Co-authored-by: sachaw <11172820+sachaw@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 01e8f8d1b..60e422312 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,7 +8,7 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - renovate@39.238.1 + - renovate@39.243.0 - prettier@3.5.3 - trufflehog@3.88.23 - yamllint@1.37.0 @@ -28,7 +28,7 @@ lint: - shellcheck@0.10.0 - black@25.1.0 - git-diff-check - - gitleaks@8.24.2 + - gitleaks@8.24.3 - clang-format@16.0.3 ignore: - linters: [ALL] From 5fd64d41143c3ef33d1f5e584f6964e39b806ac4 Mon Sep 17 00:00:00 2001 From: Benjamin Kyd Date: Wed, 16 Apr 2025 20:42:08 +0100 Subject: [PATCH 079/238] Fix uninitialised memory read (adminModule) (#6605) --- src/graphics/Screen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 8075dd468..9afd88c76 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1796,7 +1796,9 @@ void Screen::setup() powerStatusObserver.observe(&powerStatus->onNewStatus); gpsStatusObserver.observe(&gpsStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus); +#if !MESHTASTIC_EXCLUDE_ADMIN adminMessageObserver.observe(adminModule); +#endif if (textMessageModule) textMessageObserver.observe(textMessageModule); if (inputBroker) @@ -2857,4 +2859,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg) } // 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 From d74359abf0d07d66b893f1e1366f7d5dd21364ee Mon Sep 17 00:00:00 2001 From: dylanli Date: Thu, 17 Apr 2025 14:11:17 +0800 Subject: [PATCH 080/238] add support for Seeed solar panel (#6597) * add seeed_solar_node * fix RF_SW problem * fix IIC problem * Update Button redefination * Add on-board flash pin defination * fix missing a ',' * update seeed sorlar panel defination * fix word spell * fix upstream change * fix upstream change * fix upstream change * fix formate * Restore the FLASH definition that was deleted by mistake and pull down the CS pin to ensure low power consumption * fix led defination conflict * Delete lib/device-ui directory * Restore protobufs submodule --------- Co-authored-by: WayenWeng --- boards/Seeed_Solar_Node.json | 54 ++++++++ src/platform/nrf52/architecture.h | 4 +- variants/Seeed_Solar_Node/platformio.ini | 14 ++ variants/Seeed_Solar_Node/variant.cpp | 108 ++++++++++++++++ variants/Seeed_Solar_Node/variant.h | 157 +++++++++++++++++++++++ 5 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 boards/Seeed_Solar_Node.json create mode 100644 variants/Seeed_Solar_Node/platformio.ini create mode 100644 variants/Seeed_Solar_Node/variant.cpp create mode 100644 variants/Seeed_Solar_Node/variant.h diff --git a/boards/Seeed_Solar_Node.json b/boards/Seeed_Solar_Node.json new file mode 100644 index 000000000..e1b502cfa --- /dev/null +++ b/boards/Seeed_Solar_Node.json @@ -0,0 +1,54 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v7.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [["0x2886", "0x0059"]], + "usb_product": "XIAO-BOOT", + "mcu": "nrf52840", + "variant": "Seeed_Solar_Node", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "7.3.0", + "sd_fwid": "0x0123" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Seeed_Solar_Node", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html", + "vendor": "Seeed Studio" +} diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 21296c3fc..9d1d48f1c 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -81,6 +81,8 @@ #define HW_VENDOR meshtastic_HardwareModel_MESHLINK #elif defined(SEEED_XIAO_NRF52840_KIT) #define HW_VENDOR meshtastic_HardwareModel_XIAO_NRF52_KIT +#elif defined(SEEED_SOLAR_NODE) +#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE #elif defined(HELTEC_MESH_POCKET) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET #else @@ -135,4 +137,4 @@ #if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA) // No serial ports on this board - ONLY use segger in memory console #define USE_SEGGER -#endif +#endif \ No newline at end of file diff --git a/variants/Seeed_Solar_Node/platformio.ini b/variants/Seeed_Solar_Node/platformio.ini new file mode 100644 index 000000000..9651d3a77 --- /dev/null +++ b/variants/Seeed_Solar_Node/platformio.ini @@ -0,0 +1,14 @@ +[env:Seeed_Solar_Node] +board = Seeed_Solar_Node +extends = nrf52840_base +;board_level = extra +build_flags = ${nrf52840_base.build_flags} + -I $PROJECT_DIR/variants/Seeed_Solar_Node + -D SEEED_SOLAR_NODE + -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" +board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/Seeed_Solar_Node> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink diff --git a/variants/Seeed_Solar_Node/variant.cpp b/variants/Seeed_Solar_Node/variant.cpp new file mode 100644 index 000000000..994e97ff9 --- /dev/null +++ b/variants/Seeed_Solar_Node/variant.cpp @@ -0,0 +1,108 @@ +/* + * variant.cpp - Digital pin mapping for nRF52-based development board + * + * This file defines the pin mapping array that maps logical digital pins (D0-D17) + * to physical GPIO ports/pins on the Nordic nRF52 series microcontroller. + * + * Board: [Seeed Studio XIAO nRF52840 Sense (Seeed Solar Node)] + * Hardware Features: + * - LoRa module (CS/SCK/MISO/MOSI control pins) + * - GNSS module (TX/RX/Reset/Wakeup) + * - User LEDs (D11-D12) + * - User button (D13) + * - Grove/NFC interface (D14-D15) + * - Battery voltage monitoring (D16) + * + * Created [20250225] + * By [Dylan] + * Version 1.0 + * License: [MIT] + */ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +/** + * @brief Digital pin to GPIO port/pin mapping table + * + * Format: Logical Pin (Dx) -> nRF Port.Pin (Px.xx) + * + * Pin Groupings: + * [D0-D10] - Peripheral control (LoRa, GNSS) + * [D11-D12] - LED outputs + * [D13] - User button + * [D14-D15] - Grove/NFC interface + * [D16] - Battery voltage ADC input + * [D17] - GNSS module reset + */ + +extern "C" { +const uint32_t g_ADigitalPinMap[] = { + // D0 .. D10 - Peripheral control pins + 2, // D0 P0.02 (A0) GNSS_WAKEUP + 3, // D1 P0.03 (A1) LORA_DIO1 + 28, // D2 P0.28 (A2) LORA_RESET + 29, // D3 P0.29 (A3) LORA_BUSY + 4, // D4 P0.04 (A4/SDA) LORA_CS + 5, // D5 P0.05 (A5/SCL) LORA_SW + 43, // D6 P1.11 (UART_TX) GNSS_TX + 44, // D7 P1.12 (UART_RX) GNSS_RX + 45, // D8 P1.13 (SPI_SCK) LORA_SCK + 46, // D9 P1.14 (SPI_MISO) LORA_MISO + 47, // D10 P1.15 (SPI_MOSI) LORA_MOSI + + // D11-D12 - LED outputs + 15, // D11 P0.15 User LED + 19, // D12 P0.19 Breathing LED + + // D13 - User input + 33, // D13 P1.01 User Button + + // D14-D15 - Grove/NFC interface + 9, // D14 P0.09 NFC1/GROVE_D1 + 10, // D15 P0.10 NFC2/GROVE_D0 + + // D16 - Power management + // 31, // D16 P0.31 VBAT_ADC (Battery voltage) + 31, // D16 P0.31 VBAT_ADC (Battery voltage) + // D17 - GNSS control + 35, // D17 P1.03 GNSS_RESET + + 37, // D18 P1.05 GNSS_ENABLE + 14, // D19 P0.14 BAT_READ + 39, // D20 P1.07 USER_BUTTON + + // + 21, // D21 P0.21 (QSPI_SCK) + 25, // D22 P0.25 (QSPI_CSN) + 20, // D23 P0.20 (QSPI_SIO_0 DI) + 24, // D24 P0.24 (QSPI_SIO_1 DO) + 22, // D25 P0.22 (QSPI_SIO_2 WP) + 23, // D26 P0.23 (QSPI_SIO_3 HOLD) +}; +} + +void initVariant() +{ + pinMode(PIN_QSPI_CS, OUTPUT); + digitalWrite(PIN_QSPI_CS, HIGH); + // This setup is crucial for ensuring low power consumption and proper initialization of the hardware components. + pinMode(GPS_EN, OUTPUT); + digitalWrite(GPS_EN, LOW); + + // VBAT_ENABLE + pinMode(BAT_READ, OUTPUT); + digitalWrite(BAT_READ, LOW); + + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, LOW); + pinMode(PIN_LED2, OUTPUT); + digitalWrite(PIN_LED2, LOW); + pinMode(PIN_LED2, OUTPUT); + // digitalWrite(LED_PIN, LOW); + + pinMode(GPS_EN, OUTPUT); + digitalWrite(GPS_EN, HIGH); +} \ No newline at end of file diff --git a/variants/Seeed_Solar_Node/variant.h b/variants/Seeed_Solar_Node/variant.h new file mode 100644 index 000000000..86682302b --- /dev/null +++ b/variants/Seeed_Solar_Node/variant.h @@ -0,0 +1,157 @@ +#ifndef _SEEED_SOLAR_NODE_H_ +#define _SEEED_SOLAR_NODE_H_ +#include "WVariant.h" +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Clock Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define VARIANT_MCK (64000000ul) // Master clock frequency +#define USE_LFXO // 32.768kHz crystal for LFCLK + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Pin Capacity Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PINS_COUNT (33u) // Total GPIO pins +#define NUM_DIGITAL_PINS (33u) // Digital I/O pins +#define NUM_ANALOG_INPUTS (8u) // Analog inputs (A0-A5 + VBAT + AREF) +#define NUM_ANALOG_OUTPUTS (0u) + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LED Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LEDs +// LEDs +#define PIN_LED1 (11) // LED P1.15 +#define PIN_LED2 (12) // + +#define LED_BUILTIN PIN_LED1 +#define LED_CONN PIN_LED2 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 +// #define LED_PIN PIN_LED2 +#define LED_STATE_ON 1 // State when LED is litted +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Button Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define BUTTON_PIN D13 // This is the Program Button +// #define BUTTON_NEED_PULLUP 1 +#define BUTTON_ACTIVE_LOW true +#define BUTTON_ACTIVE_PULLUP false + +#define BUTTON_PIN_TOUCH 20 // Touch button +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Digital Pin Mapping (D0-D10) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define D0 0 // P0.02 GNSS_WAKEUP/IO0 +#define D1 1 // P0.03 LORA_DIO1 +#define D2 2 // P0.28 LORA_RESET +#define D3 3 // P0.29 LORA_BUSY +#define D4 4 // P0.04 LORA_CS/I2C_SDA +#define D5 5 // P0.05 LORA_SW/I2C_SCL +#define D6 6 // P1.11 GNSS_TX +#define D7 7 // P1.12 GNSS_RX +#define D8 8 // P1.13 SPI_SCK +#define D9 9 // P1.14 SPI_MISO +#define D10 10 // P1.15 SPI_MOSI +#define D13 13 // P1.01 User Button +#define D14 14 // P0.09 NFC1/GROVE_D1 +#define D15 15 // P0.10 NFC2/GROVE_D0 +#define D16 16 // P0.31 VBAT_ADC (Battery voltage) +#define D17 17 // P1.03 GNSS_RESET +#define D18 18 // P1.05 GNSS_ENABLE +#define D19 19 // P0.14 BAT_READ +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Analog Pin Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PIN_A0 0 // P0.02 Analog Input 0 +#define PIN_A1 1 // P0.03 Analog Input 1 +#define PIN_A2 2 // P0.28 Analog Input 2 +#define PIN_A3 3 // P0.29 Analog Input 3 +#define PIN_A4 4 // P0.04 Analog Input 4 +#define PIN_A5 5 // P0.05 Analog Input 5 +#define PIN_VBAT D16 // P0.31 Battery voltage sense +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Communication Interfaces +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// I2C Configuration +#define HAS_WIRE 1 +#define PIN_WIRE_SDA D14 // P0.09 +#define PIN_WIRE_SCL D15 // P0.10 +#define WIRE_INTERFACES_COUNT 1 +#define I2C_NO_RESCAN + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; +// SPI Configuration (SX1262) + +#define SPI_INTERFACES_COUNT 1 +#define PIN_SPI_MISO 9 // P1.14 (D9) +#define PIN_SPI_MOSI 10 // P1.15 (D10) +#define PIN_SPI_SCK 8 // P1.13 (D8) + +// SX1262 LoRa Module Pins +#define USE_SX1262 +#define SX126X_CS D4 // Chip select +#define SX126X_DIO1 D1 // Digital IO 1 (Interrupt) +#define SX126X_BUSY D3 // Busy status +#define SX126X_RESET D2 // Reset control +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // TCXO supply voltage +#define SX126X_RXEN D5 // RX enable control +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_DIO2_AS_RF_SWITCH // This Line is really necessary for SX1262 to work with RF switch or will loss TX power +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Power Management +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +#define BAT_READ \ + D19 // P0_14 = 14 Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is + // program pin 32 / or P0.31) +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define ADC_MULTIPLIER 3.3 +#define BATTERY_PIN PIN_VBAT // PIN_A7 +#define AREF_VOLTAGE 3.3 +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// GPS L76KB +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define GPS_L76K +#ifdef GPS_L76K +#define PIN_GPS_RX D6 // 44 +#define PIN_GPS_TX D7 // 43 +#define HAS_GPS 1 +#define GPS_BAUDRATE 9600 +#define GPS_THREAD_INTERVAL 50 +#define PIN_SERIAL1_RX PIN_GPS_TX +#define PIN_SERIAL1_TX PIN_GPS_RX +#define PIN_GPS_STANDBY D0 +#define GPS_EN D18 // P1.05 +#endif + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +#define PIN_QSPI_SCK (21) +#define PIN_QSPI_CS (22) +#define PIN_QSPI_IO0 (23) +#define PIN_QSPI_IO1 (24) +#define PIN_QSPI_IO2 (25) +#define PIN_QSPI_IO3 (26) + +#define EXTERNAL_FLASH_DEVICES P25Q16H +#define EXTERNAL_FLASH_USE_QSPI + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Compatibility Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#ifdef __cplusplus +extern "C" { +#endif +// Serial port placeholders + +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) +#ifdef __cplusplus +} +#endif + +#endif // _SEEED_SOLAR_NODE_H_ \ No newline at end of file From a36f21b29ae22b5c1476277aa3b9768460cd7642 Mon Sep 17 00:00:00 2001 From: Benjamin Kyd Date: Thu, 17 Apr 2025 10:36:19 +0100 Subject: [PATCH 081/238] Fix compiler error in PowerFSM when WiFi is excluded (#6603) --- src/PowerFSM.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 4c4d203c2..dbe4796cf 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -19,7 +19,7 @@ #include "sleep.h" #include "target_specific.h" -#if HAS_WIFI && !defined(ARCH_PORTDUINO) +#if HAS_WIFI && !defined(ARCH_PORTDUINO) || defined(MESHTASTIC_EXCLUDE_WIFI) #include "mesh/wifi/WiFiAPClient.h" #endif @@ -269,9 +269,6 @@ Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0); - 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; bool hasPower = isPowered(); LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0); @@ -383,6 +380,12 @@ void PowerFSM_setup() // See: https://github.com/meshtastic/firmware/issues/1071 // Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated // through the modules + +#if HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI) + 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; + if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) { powerFSM.add_timed_transition(&stateNB, &stateLS, Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, @@ -400,7 +403,9 @@ void PowerFSM_setup() Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout"); } -#else +#endif // HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI) + +#else // (not) ARCH_ESP32 // 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, @@ -409,4 +414,4 @@ void PowerFSM_setup() powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state } -#endif \ No newline at end of file +#endif From c177c6d655b2bbb05d4d8711fd67756de9fc6412 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 05:33:42 -0500 Subject: [PATCH 082/238] [create-pull-request] automated change (#6610) Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/protobufs b/protobufs index b982b36df..27fac3914 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit b982b36dfab2e96b8f8be90af891c68ebf8790c2 +Subproject commit 27fac39141d99fe727a0a1824c5397409b1aea75 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 36bded9b2..6fa0b60b0 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -243,6 +243,10 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94, /* Seeed Solar Node */ meshtastic_HardwareModel_SEEED_SOLAR_NODE = 95, + /* NomadStar Meteor Pro https://nomadstar.ch/ */ + meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO = 96, + /* Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin */ + meshtastic_HardwareModel_CROWPANEL = 97, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 ef14967fbf29f0aa2dc38f5dcc9c8289b7461ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 17 Apr 2025 16:03:37 +0200 Subject: [PATCH 083/238] Crowpanel 2.4,2.8 and 3.5 support (#6355) Co-authored-by: mverch67 --- boards/crowpanel.json | 43 ++++ src/FSCommon.cpp | 9 +- src/Power.cpp | 2 + src/graphics/Screen.cpp | 12 +- src/graphics/ScreenFonts.h | 4 +- src/graphics/TFTDisplay.cpp | 330 +++++++++++++++++++++++++- src/graphics/images.h | 2 +- src/main.cpp | 24 +- src/mesh/NodeDB.cpp | 7 +- src/platform/esp32/architecture.h | 2 + src/sleep.cpp | 4 +- variants/elecrow_panel/pins_arduino.h | 64 +++++ variants/elecrow_panel/platformio.ini | 123 ++++++++++ variants/elecrow_panel/variant.h | 195 +++++++++++++++ 14 files changed, 789 insertions(+), 32 deletions(-) create mode 100644 boards/crowpanel.json create mode 100644 variants/elecrow_panel/pins_arduino.h create mode 100644 variants/elecrow_panel/platformio.ini create mode 100644 variants/elecrow_panel/variant.h diff --git a/boards/crowpanel.json b/boards/crowpanel.json new file mode 100644 index 000000000..570961ed7 --- /dev/null +++ b/boards/crowpanel.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "ESP32-S3-WROOM-1-N16R8" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "ESP32-S3-WROOM-1-N16R8 (16 MB Flash, 8 MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 524288, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "monitor": { + "speed": 115200 + }, + "url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf", + "vendor": "Espressif" +} diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index 88f0764b5..f215be80f 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -12,13 +12,14 @@ #include "SPILock.h" #include "configuration.h" -#ifdef HAS_SDCARD +// Software SPI is used by MUI so disable SD card here until it's also implemented +#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) #include #include #ifdef SDCARD_USE_SPI1 -SPIClass SPI1(HSPI); -#define SDHandler SPI1 +SPIClass SPI_HSPI(HSPI); +#define SDHandler SPI_HSPI #else #define SDHandler SPI #endif @@ -306,7 +307,7 @@ void fsInit() */ void setupSDCard() { -#ifdef HAS_SDCARD +#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) concurrency::LockGuard g(spiLock); SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI); if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) { diff --git a/src/Power.cpp b/src/Power.cpp index f11f8eac3..ed1bd20ef 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -450,6 +450,8 @@ class AnalogBatteryLevel : public HasBatteryLevel return isBatteryConnect() && isVbusIn(); #endif #endif + // by default, we check the battery voltage only + return isVbusIn(); } private: diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 9afd88c76..ad0b94efe 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1104,7 +1104,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(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x, y + 3, 8, 8, imgUser); #else @@ -1545,7 +1545,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O 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(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_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) @@ -1751,7 +1751,7 @@ void Screen::setup() // flip it. If you have a headache now, you're welcome. if (!config.display.flip_screen) { #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \ - defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) + defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) static_cast(dispdev)->flipScreenVertically(); #elif defined(USE_ST7789) static_cast(dispdev)->flipScreenVertically(); @@ -2492,7 +2492,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat, (storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1); @@ -2504,7 +2504,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 #endif } else { #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_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); @@ -2519,7 +2519,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 } else { // TODO: Raspberry Pi supports more than just the one screen size #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_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); diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index 079a3e282..0be0dc814 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -65,8 +65,8 @@ #endif #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) || \ + defined(ILI9488_CS) && !defined(DISPLAY_FORCE_SMALL_FONTS) // The screen is bigger so use bigger fonts #define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19 #define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index c5187cffc..14787baff 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -120,6 +120,303 @@ static void rak14014_tpIntHandle(void) _rak14014_touch_int = true; } +#elif defined(ST72xx_DE) +#include +#include +#include +#include +TCA9534 ioex; + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Bus_RGB _bus_instance; + lgfx::Panel_RGB _panel_instance; + lgfx::Touch_GT911 _touch_instance; + + public: + const uint16_t screenWidth = TFT_WIDTH; + const uint16_t screenHeight = TFT_HEIGHT; + + bool init_impl(bool use_reset, bool use_clear) override + { + ioex.attach(Wire); + ioex.setDeviceAddress(0x18); + ioex.config(1, TCA9534::Config::OUT); + ioex.config(2, TCA9534::Config::OUT); + ioex.config(3, TCA9534::Config::OUT); + ioex.config(4, TCA9534::Config::OUT); + + ioex.output(1, TCA9534::Level::H); + ioex.output(3, TCA9534::Level::L); + ioex.output(4, TCA9534::Level::H); + + pinMode(1, OUTPUT); + digitalWrite(1, LOW); + ioex.output(2, TCA9534::Level::L); + delay(20); + ioex.output(2, TCA9534::Level::H); + delay(100); + pinMode(1, INPUT); + + return LGFX_Device::init_impl(use_reset, use_clear); + } + + LGFX(void) + { + { + auto cfg = _panel_instance.config(); + + cfg.memory_width = screenWidth; + cfg.memory_height = screenHeight; + cfg.panel_width = screenWidth; + cfg.panel_height = screenHeight; + cfg.offset_x = 0; + cfg.offset_y = 0; + cfg.offset_rotation = 0; + _panel_instance.config(cfg); + } + + { + auto cfg = _panel_instance.config_detail(); + cfg.use_psram = 0; + _panel_instance.config_detail(cfg); + } + + { + auto cfg = _bus_instance.config(); + cfg.panel = &_panel_instance; + cfg.pin_d0 = ST72xx_B0; // B0 + cfg.pin_d1 = ST72xx_B1; // B1 + cfg.pin_d2 = ST72xx_B2; // B2 + cfg.pin_d3 = ST72xx_B3; // B3 + cfg.pin_d4 = ST72xx_B4; // B4 + cfg.pin_d5 = ST72xx_G0; // G0 + cfg.pin_d6 = ST72xx_G1; // G1 + cfg.pin_d7 = ST72xx_G2; // G2 + cfg.pin_d8 = ST72xx_G3; // G3 + cfg.pin_d9 = ST72xx_G4; // G4 + cfg.pin_d10 = ST72xx_G5; // G5 + cfg.pin_d11 = ST72xx_R0; // R0 + cfg.pin_d12 = ST72xx_R1; // R1 + cfg.pin_d13 = ST72xx_R2; // R2 + cfg.pin_d14 = ST72xx_R3; // R3 + cfg.pin_d15 = ST72xx_R4; // R4 + + cfg.pin_henable = ST72xx_DE; + cfg.pin_vsync = ST72xx_VSYNC; + cfg.pin_hsync = ST72xx_HSYNC; + cfg.pin_pclk = ST72xx_PCLK; + cfg.freq_write = 13000000; + +#ifdef ST7265_HSYNC_POLARITY + cfg.hsync_polarity = ST7265_HSYNC_POLARITY; + cfg.hsync_front_porch = ST7265_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = ST7265_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = ST7265_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = ST7265_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = ST7265_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = ST7265_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = ST7265_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = ST7265_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + +#ifdef ST7262_HSYNC_POLARITY + cfg.hsync_polarity = ST7262_HSYNC_POLARITY; + cfg.hsync_front_porch = ST7262_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = ST7262_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = ST7262_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = ST7262_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = ST7262_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = ST7262_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = ST7262_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = ST7262_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + +#ifdef SC7277_HSYNC_POLARITY + cfg.hsync_polarity = SC7277_HSYNC_POLARITY; + cfg.hsync_front_porch = SC7277_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = SC7277_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = SC7277_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = SC7277_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = SC7277_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = SC7277_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = SC7277_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = SC7277_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + + _bus_instance.config(cfg); + } + _panel_instance.setBus(&_bus_instance); + + { + auto cfg = _touch_instance.config(); + cfg.x_min = 0; + cfg.x_max = TFT_WIDTH; + cfg.y_min = 0; + cfg.y_max = TFT_HEIGHT; + cfg.pin_int = -1; + cfg.pin_rst = -1; + cfg.bus_shared = true; + cfg.offset_rotation = 0; + + cfg.i2c_port = 0; + cfg.i2c_addr = 0x5D; + cfg.pin_sda = I2C_SDA; + cfg.pin_scl = I2C_SCL; + cfg.freq = 400000; + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } + + setPanel(&_panel_instance); + } +}; + +static LGFX *tft = nullptr; + +#elif defined(ILI9488_CS) +#include // Graphics and font library for ILI9488 driver chip + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_ILI9488 _panel_instance; + lgfx::Bus_SPI _bus_instance; + lgfx::Light_PWM _light_instance; + lgfx::Touch_GT911 _touch_instance; + + public: + LGFX(void) + { + { + auto cfg = _bus_instance.config(); + + // configure SPI + cfg.spi_host = ILI9488_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_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 = ILI9488_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = ILI9488_SDA; // Set SPI MOSI pin number + cfg.pin_miso = ILI9488_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = ILI9488_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 = ILI9488_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable) + cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable) + + // The following setting values ​​are general initial values ​​for each panel, so please comment out any + // unknown items and try them. + + cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + 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 mirrored) +#ifdef TFT_DUMMY_READ_PIXELS + cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout +#else + cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout +#endif + 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 = true; // 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; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI + cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) + + // Set the following only when the display is shifted with a driver with a variable number of pixels, such as the + // ST7735 or ILI9163. + // cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + // cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + _panel_instance.config(cfg); + } + +#ifdef ILI9488_BL + // Set the backlight control + { + auto cfg = _light_instance.config(); // Gets a structure for backlight settings. + + cfg.pin_bl = ILI9488_BL; // Pin number to which the backlight is connected + cfg.invert = false; // true to invert the brightness of the backlight + // cfg.freq = 44100; // PWM frequency of backlight + // cfg.pwm_channel = 1; // PWM channel number to use + + _light_instance.config(cfg); + _panel_instance.setLight(&_light_instance); // Set the backlight on the panel. + } +#endif + +#if HAS_TOUCHSCREEN + // Configure settings for touch screen control. + { + auto cfg = _touch_instance.config(); + + cfg.pin_cs = -1; + cfg.x_min = 0; + cfg.x_max = TFT_HEIGHT - 1; + cfg.y_min = 0; + cfg.y_max = TFT_WIDTH - 1; + cfg.pin_int = SCREEN_TOUCH_INT; +#ifdef SCREEN_TOUCH_RST + cfg.pin_rst = SCREEN_TOUCH_RST; +#endif + cfg.bus_shared = true; + cfg.offset_rotation = TFT_OFFSET_ROTATION; + // cfg.freq = 2500000; + + // I2C + cfg.i2c_port = TOUCH_I2C_PORT; + cfg.i2c_addr = TOUCH_SLAVE_ADDRESS; +#ifdef SCREEN_TOUCH_USE_I2C1 + cfg.pin_sda = I2C_SDA1; + cfg.pin_scl = I2C_SCL1; +#else + cfg.pin_sda = I2C_SDA; + cfg.pin_scl = I2C_SCL; +#endif + // cfg.freq = 400000; + + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } +#endif + + setPanel(&_panel_instance); + } +}; + +static LGFX *tft = nullptr; + #elif defined(ST7789_CS) #include // Graphics and font library for ST7735 driver chip @@ -129,7 +426,7 @@ class LGFX : public lgfx::LGFX_Device lgfx::Bus_SPI _bus_instance; lgfx::Light_PWM _light_instance; #if HAS_TOUCHSCREEN -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) lgfx::Touch_FT5x06 _touch_instance; #else lgfx::Touch_GT911 _touch_instance; @@ -171,16 +468,22 @@ class LGFX : public lgfx::LGFX_Device // The following setting values ​​are general initial values ​​for each panel, so please comment out any // unknown items and try them. - 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 mirrored) - cfg.dummy_read_pixel = 9; // 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 = true; // 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.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + 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 mirrored) +#ifdef TFT_DUMMY_READ_PIXELS + cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout +#else + cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout +#endif + 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 = true; // 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; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) @@ -217,6 +520,9 @@ class LGFX : public lgfx::LGFX_Device cfg.y_min = 0; cfg.y_max = TFT_WIDTH - 1; cfg.pin_int = SCREEN_TOUCH_INT; +#ifdef SCREEN_TOUCH_RST + cfg.pin_rst = SCREEN_TOUCH_RST; +#endif cfg.bus_shared = true; cfg.offset_rotation = TFT_OFFSET_ROTATION; // cfg.freq = 2500000; @@ -640,7 +946,7 @@ static LGFX *tft = nullptr; #endif #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ - defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || (ARCH_PORTDUINO && HAS_SCREEN != 0) #include "SPILock.h" #include "TFTDisplay.h" #include diff --git a/src/graphics/images.h b/src/graphics/images.h index b757dcf30..069839a16 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -21,7 +21,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03 #endif #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_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}; diff --git a/src/main.cpp b/src/main.cpp index 535a7afa1..eb93a70d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,6 +115,10 @@ AccelerometerThread *accelerometerThread = nullptr; AudioThread *audioThread = nullptr; #endif +#ifdef USE_PCA9557 +PCA9557 IOEXP; +#endif + #if HAS_TFT extern void tftSetup(void); #endif @@ -133,6 +137,10 @@ void setupNicheGraphics(); #include "nicheGraphics.h" #endif +#if defined(HW_SPI1_DEVICE) && defined(ARCH_ESP32) +SPIClass SPI1(HSPI); +#endif + using namespace concurrency; volatile static const char slipstreamTZString[] = {USERPREFS_TZ_STRING}; @@ -364,9 +372,11 @@ void setup() SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); #endif +#if !HAS_TFT meshtastic_Config_DisplayConfig_OledType screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO; OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64; +#endif #ifdef USE_SEGGER auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM; @@ -595,6 +605,7 @@ void setup() } #endif +#if !HAS_TFT auto screenInfo = i2cScanner->firstScreen(); screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE; @@ -612,6 +623,7 @@ void setup() screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO; } } +#endif #define UPDATE_FROM_SCANNER(FIND_FN) @@ -779,9 +791,11 @@ void setup() else playStartMelody(); +#if !HAS_TFT // fixed screen override? if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO) screen_model = config.display.oled; +#endif #if defined(USE_SH1107) screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128 @@ -837,10 +851,16 @@ void setup() #elif !defined(ARCH_ESP32) // ARCH_RP2040 SPI.begin(); #else - // ESP32 + // ESP32 +#if defined(HW_SPI1_DEVICE) + SPI1.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); + LOG_DEBUG("SPI1.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); + SPI1.setFrequency(4000000); +#else SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); SPI.setFrequency(4000000); +#endif #endif // Initialize the screen first so we can show the logo while we start up everything else. @@ -934,7 +954,7 @@ void setup() // Don't call screen setup until after nodedb is setup (because we need // the current region name) #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ - defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) + defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) screen->setup(); #elif defined(ARCH_PORTDUINO) if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) { diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index c89abbe74..90a90e89f 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -584,7 +584,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32); -#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \ +#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \ + defined(ELECROW)) && \ HAS_TFT // switch BT off by default; use TFT programming mode or hotkey to enable config.bluetooth.enabled = false; @@ -595,7 +596,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) config.bluetooth.fixed_pin = defaultBLEPin; #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \ - defined(HX8357_CS) || defined(USE_ST7789) + defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) bool hasScreen = true; #ifdef HELTEC_MESH_NODE_T114 uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET); @@ -689,7 +690,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) +#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) || defined(ELECROW) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 0af6d4d04..68d06c6d7 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -182,6 +182,8 @@ #define HW_VENDOR meshtastic_HardwareModel_T_ETH_ELITE #elif defined(HELTEC_SENSOR_HUB) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_SENSOR_HUB +#elif defined(ELECROW_PANEL) +#define HW_VENDOR meshtastic_HardwareModel_CROWPANEL #endif // ----------------------------------------------------------------------------- diff --git a/src/sleep.cpp b/src/sleep.cpp index 02fa8d871..2985db0c2 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -400,7 +400,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef INPUTDRIVER_ENCODER_BTN gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL); #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif enableLoraInterrupt(); @@ -434,7 +434,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_disable(pin); #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) gpio_wakeup_disable((gpio_num_t)SCREEN_TOUCH_INT); #endif diff --git a/variants/elecrow_panel/pins_arduino.h b/variants/elecrow_panel/pins_arduino.h new file mode 100644 index 000000000..b98530378 --- /dev/null +++ b/variants/elecrow_panel/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// static const uint8_t LED_BUILTIN = -1; + +// static const uint8_t TX = 43; +// static const uint8_t RX = 44; + +static const uint8_t SDA = 39; +static const uint8_t SCL = 40; + +// Default SPI will be mapped to Radio +static const uint8_t SS = -1; +static const uint8_t MOSI = 48; +static const uint8_t MISO = 47; +static const uint8_t SCK = 41; + +#ifndef CROW_SELECT +static const uint8_t SPI_MOSI = 6; +static const uint8_t SPI_SCK = 5; +static const uint8_t SPI_MISO = 4; +static const uint8_t SPI_CS = 7; // SD does not support -1 +static const uint8_t SDCARD_CS = SPI_CS; +#endif + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ \ No newline at end of file diff --git a/variants/elecrow_panel/platformio.ini b/variants/elecrow_panel/platformio.ini new file mode 100644 index 000000000..66dc35c3b --- /dev/null +++ b/variants/elecrow_panel/platformio.ini @@ -0,0 +1,123 @@ +[crowpanel_base] +extends = esp32s3_base +board = crowpanel +board_check = true +upload_protocol = esptool +board_build.partitions = default_16MB.csv ; must be here for some reason, board.json is not enough !? + +build_flags = ${esp32s3_base.build_flags} -Os + -I variants/elecrow_panel + -D ELECROW + -D ELECROW_PANEL + -D CONFIG_ARDUHAL_LOG_COLORS + -D RADIOLIB_DEBUG_SPI=0 + -D RADIOLIB_DEBUG_PROTOCOL=0 + -D RADIOLIB_DEBUG_BASIC=0 + -D RADIOLIB_VERBOSE_ASSERT=0 + -D RADIOLIB_SPI_PARANOID=0 + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 + -D MESHTASTIC_EXCLUDE_SERIAL=1 + -D MESHTASTIC_EXCLUDE_SOCKETAPI=1 + -D MESHTASTIC_EXCLUDE_SCREEN=1 + -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 +; -D INPUTDRIVER_BUTTON_TYPE=0 + -D HAS_TELEMETRY=0 + -D CONFIG_DISABLE_HAL_LOCKS=1 + -D HAS_SCREEN=0 + -D HAS_TFT=1 + -D RAM_SIZE=6144 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D LV_BUILD_TEST=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + +lib_deps = ${esp32s3_base.lib_deps} + ${device-ui_base.lib_deps} + earlephilhower/ESP8266Audio@^1.9.9 + earlephilhower/ESP8266SAM@^1.0.1 + lovyan03/LovyanGFX@^1.2.0 + hideakitai/TCA9534@^0.1.1 + +[env:elecrow-24-28-tft] +extends = crowpanel_base + +build_flags = + ${crowpanel_base.build_flags} + -D TFT_HEIGHT=320 ; needed in variant.h + -D HAS_SDCARD + -D SDCARD_USE_SOFT_SPI + -D SPI_DRIVER_SELECT=2 + -D USE_PIN_BUZZER +; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! + -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch + -D LGFX_DRIVER_TEMPLATE + -D LGFX_DRIVER=LGFX_GENERIC + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" + -D SPI_FREQUENCY=80000000 + -D LGFX_SCREEN_WIDTH=240 + -D LGFX_SCREEN_HEIGHT=320 + -D LGFX_PANEL=ST7789 + -D LGFX_ROTATION=1 + -D LGFX_CFG_HOST=SPI2_HOST + -D LGFX_PIN_SCK=42 + -D LGFX_PIN_MOSI=39 + -D LGFX_PIN_DC=41 + -D LGFX_PIN_CS=40 + -D LGFX_PIN_BL=38 + -D LGFX_TOUCH=FT5x06 + -D LGFX_TOUCH_I2C_ADDR=0x38 + -D LGFX_TOUCH_I2C_SDA=15 + -D LGFX_TOUCH_I2C_SCL=16 + -D LGFX_TOUCH_INT=47 + -D LGFX_TOUCH_RST=48 + -D LGFX_TOUCH_ROTATION=0 + -D VIEW_320x240 + -D MAP_FULL_REDRAW + +[env:elecrow-35-tft] +extends = crowpanel_base + +build_flags = + ${crowpanel_base.build_flags} + -D TFT_HEIGHT=480 ; needed in variant.h + -D HAS_SDCARD + -D SDCARD_USE_SOFT_SPI + -D SPI_DRIVER_SELECT=2 + -D USE_PIN_BUZZER +; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! + -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch + -D LV_CACHE_DEF_SIZE=2097152 + -D LGFX_DRIVER_TEMPLATE + -D LGFX_DRIVER=LGFX_GENERIC + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" + -D SPI_FREQUENCY=60000000 + -D LGFX_SCREEN_WIDTH=320 + -D LGFX_SCREEN_HEIGHT=480 + -D LGFX_PANEL=ILI9488 + -D LGFX_ROTATION=0 + -D LGFX_CFG_HOST=SPI2_HOST + -D LGFX_PIN_SCK=42 + -D LGFX_PIN_MOSI=39 + -D LGFX_PIN_DC=41 + -D LGFX_PIN_CS=40 + -D LGFX_PIN_BL=38 + -D LGFX_TOUCH=GT911 + -D LGFX_TOUCH_I2C_ADDR=0x5D + -D LGFX_TOUCH_I2C_SDA=15 + -D LGFX_TOUCH_I2C_SCL=16 + -D LGFX_TOUCH_INT=47 + -D LGFX_TOUCH_RST=48 + -D LGFX_TOUCH_ROTATION=0 + -D DISPLAY_SET_RESOLUTION + -D VIEW_320x240 + -D MAP_FULL_REDRAW diff --git a/variants/elecrow_panel/variant.h b/variants/elecrow_panel/variant.h new file mode 100644 index 000000000..b1035ed31 --- /dev/null +++ b/variants/elecrow_panel/variant.h @@ -0,0 +1,195 @@ +#define I2C_SDA 15 +#define I2C_SCL 16 + +#if TFT_HEIGHT == 320 && not defined(HAS_TFT) // 2.4 and 2.8 TFT +// ST7789 TFT LCD +#define ST7789_CS 40 +#define ST7789_RS 41 // DC +#define ST7789_SDA 39 // MOSI +#define ST7789_SCK 42 +#define ST7789_RESET -1 +#define ST7789_MISO 38 +#define ST7789_BUSY -1 +#define ST7789_BL 38 +#define ST7789_SPI_HOST SPI2_HOST +#define TFT_BL 38 +#define SPI_FREQUENCY 60000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_ROTATE +#define TFT_DUMMY_READ_PIXELS 8 +#define SCREEN_TRANSITION_FRAMERATE 5 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness + +#define HAS_TOUCHSCREEN 1 +#define SCREEN_TOUCH_INT 47 +#define SCREEN_TOUCH_RST 48 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x38 // FT5x06 +#endif + +#if TFT_HEIGHT == 480 && not defined(HAS_TFT) // 3.5 TFT +// ILI9488 TFT LCD +#define ILI9488_CS 40 +#define ILI9488_RS 41 // DC +#define ILI9488_SDA 39 // MOSI +#define ILI9488_SCK 42 +#define ILI9488_RESET -1 +#define ILI9488_MISO 38 +#define ILI9488_BUSY -1 +#define ILI9488_BL 38 +#define ILI9488_SPI_HOST SPI2_HOST +#define TFT_BL 38 +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_ROTATE +#define TFT_DUMMY_READ_PIXELS 8 +#define SCREEN_TRANSITION_FRAMERATE 5 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness + +#define HAS_TOUCHSCREEN 1 +#define SCREEN_TOUCH_INT 47 +#define SCREEN_TOUCH_RST 48 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#endif + +#ifdef CROW_SELECT +#define ST72xx_DE 42 +#define ST72xx_VSYNC 41 +#define ST72xx_HSYNC 40 +#define ST72xx_PCLK 39 +#define ST72xx_R0 7 +#define ST72xx_R1 17 +#define ST72xx_R2 18 +#define ST72xx_R3 3 +#define ST72xx_R4 46 +#define ST72xx_G0 9 +#define ST72xx_G1 10 +#define ST72xx_G2 11 +#define ST72xx_G3 12 +#define ST72xx_G4 13 +#define ST72xx_G5 14 +#define ST72xx_B0 21 +#define ST72xx_B1 47 +#define ST72xx_B2 48 +#define ST72xx_B3 45 +#define ST72xx_B4 38 + +#define HAS_TOUCHSCREEN 1 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 1 // 4.3 TFT 800x480 +#define ST7265_HSYNC_POLARITY 0 +#define ST7265_HSYNC_FRONT_PORCH 24 +#define ST7265_HSYNC_PULSE_WIDTH 8 +#define ST7265_HSYNC_BACK_PORCH 24 +#define ST7265_VSYNC_POLARITY 1 +#define ST7265_VSYNC_FRONT_PORCH 24 +#define ST7265_VSYNC_PULSE_WIDTH 8 +#define ST7265_VSYNC_BACK_PORCH 24 +#define ST7265_PCLK_ACTIVE_NEG 1 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 2 // 5.0 TFT 800x480 +#define ST7262_HSYNC_POLARITY 0 +#define ST7262_HSYNC_FRONT_PORCH 8 +#define ST7262_HSYNC_PULSE_WIDTH 4 +#define ST7262_HSYNC_BACK_PORCH 8 +#define ST7262_VSYNC_POLARITY 0 +#define ST7262_VSYNC_FRONT_PORCH 8 +#define ST7262_VSYNC_PULSE_WIDTH 4 +#define ST7262_VSYNC_BACK_PORCH 8 +#define ST7262_PCLK_ACTIVE_NEG 0 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 3 // 7.0 TFT 800x480 +#define SC7277_HSYNC_POLARITY 0 +#define SC7277_HSYNC_FRONT_PORCH 8 +#define SC7277_HSYNC_PULSE_WIDTH 4 +#define SC7277_HSYNC_BACK_PORCH 8 +#define SC7277_VSYNC_POLARITY 0 +#define SC7277_VSYNC_FRONT_PORCH 8 +#define SC7277_VSYNC_PULSE_WIDTH 4 +#define SC7277_VSYNC_BACK_PORCH 8 +#define SC7277_PCLK_ACTIVE_NEG 0 +#endif + +#if TFT_HEIGHT == 320 // 2.4-2.8 have I2S audio +// dac / amp +// #define HAS_I2S // didn't get I2S sound working +#define PIN_BUZZER 8 // using pwm buzzer instead (nobody will notice, lol) +#define DAC_I2S_BCK 13 +#define DAC_I2S_WS 11 +#define DAC_I2S_DOUT 12 +#define DAC_I2S_MCLK 8 // don't use GPIO0 because it's assigned to LoRa or button +#else +#define PIN_BUZZER 8 +#endif + +// GPS via UART1 connector +#define HAS_GPS 1 +#define GPS_DEFAULT_NOT_PRESENT 1 +#define GPS_RX_PIN 18 +#define GPS_TX_PIN 17 + +// Extension Slot Layout, viewed from above (2.4-3.5) +// DIO1/IO1 o o IO2/NRESET +// SCK/IO10 o o IO16/NC +// MISO/IO9 o o IO15/NC +// MOSI/IO3 o o NC/DIO2 +// 3V3 o o IO46/BUSY +// GND o o IO0/NSS +// 5V/NC o o NC/DIO3 +// J9 J8 + +// Extension Slot Layout, viewed from above (4.3-7.0) +// !! DIO1/IO20 o o IO19/NRESET !! +// !! SCK/IO5 o o IO16/NC +// !! MISO/IO4 o o IO15/NC +// !! MOSI/IO6 o o NC/DIO2 +// 3V3 o o IO2/BUSY !! +// GND o o IO0/NSS +// 5V/NC o o NC/DIO3 +// J9 J8 + +// LoRa +#define USE_SX1262 +#define LORA_CS 0 // GND + +#if TFT_HEIGHT == 320 || TFT_HEIGHT == 480 // 2.4 - 3.5 TFT +#define LORA_SCK 10 +#define LORA_MISO 9 +#define LORA_MOSI 3 + +#define LORA_RESET 2 +#define LORA_DIO1 1 // SX1262 IRQ +#define LORA_DIO2 46 // SX1262 BUSY + +// need to pull IO45 low to enable LORA and disable Microphone on 24 28 35 +#define SENSOR_POWER_CTRL_PIN 45 +#define SENSOR_POWER_ON LOW +#else +#define LORA_SCK 5 +#define LORA_MISO 4 +#define LORA_MOSI 6 + +#define LORA_RESET 19 +#define LORA_DIO1 20 // SX1262 IRQ +#define LORA_DIO2 2 // SX1262 BUSY +#endif + +#define HW_SPI1_DEVICE +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH + +#define SX126X_DIO3_TCXO_VOLTAGE 3.3 + +#define USE_VIRTUAL_KEYBOARD 1 +#define DISPLAY_CLOCK_FRAME 1 \ No newline at end of file From e2f6600cb955f8de86175a87fae36f49863ba72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 17 Apr 2025 22:58:28 +0200 Subject: [PATCH 084/238] Lib Update (#6510) * Lib Update Draft because PIN display doesn't work yet. * pin entry still no worky * Fix for missing PIN code issue (#6574) --------- Co-authored-by: Ben Meadors Co-authored-by: Alexander Begoon --- arch/esp32/esp32.ini | 2 +- src/nimble/NimbleBluetooth.cpp | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 5e15cb451..35f3a5a1c 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -50,7 +50,7 @@ lib_deps = # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino - h2zero/NimBLE-Arduino@^1.4.3 + h2zero/NimBLE-Arduino@^2.2.3 # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip # renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 009439f25..208d8ae3c 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -49,7 +49,7 @@ static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE]; class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks { - virtual void onWrite(NimBLECharacteristic *pCharacteristic) + virtual void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) { LOG_DEBUG("To Radio onwrite"); auto val = pCharacteristic->getValue(); @@ -66,7 +66,7 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks { - virtual void onRead(NimBLECharacteristic *pCharacteristic) + virtual void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) { uint8_t fromRadioBytes[meshtastic_FromRadio_size]; size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes); @@ -79,7 +79,7 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothServerCallback : public NimBLEServerCallbacks { - virtual uint32_t onPassKeyRequest() + virtual uint32_t onPassKeyDisplay() { uint32_t passkey = config.bluetooth.fixed_pin; @@ -125,7 +125,7 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks return passkey; } - virtual void onAuthenticationComplete(ble_gap_conn_desc *desc) + virtual void onAuthenticationComplete(NimBLEConnInfo &connInfo) { LOG_INFO("BLE authentication complete"); @@ -138,9 +138,9 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks } } - virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc) + virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) { - LOG_INFO("BLE disconnect"); + LOG_INFO("BLE disconnect. Reason %i", reason); bluetoothStatus->updateStatus( new meshtastic::BluetoothStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED)); @@ -191,7 +191,7 @@ int NimbleBluetooth::getRssi() if (bleServer && isConnected()) { auto service = bleServer->getServiceByUUID(MESH_SERVICE_UUID); uint16_t handle = service->getHandle(); - return NimBLEDevice::getClientByID(handle)->getRssi(); + return NimBLEDevice::getClientByHandle(handle)->getRssi(); } return 0; // FIXME figure out where to source this } @@ -216,6 +216,7 @@ void NimbleBluetooth::setup() NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback(); bleServer->setCallbacks(serverCallbacks, true); + bleServer->advertiseOnDisconnect(true); setupService(); startAdvertising(); } @@ -259,7 +260,7 @@ void NimbleBluetooth::setupService() BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic) (uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1); - NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904); + NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->create2904(); batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8); batteryLevelDescriptor->setNamespace(1); batteryLevelDescriptor->setUnit(0x27ad); From 74b3dc34e4e230193fa6e5bab9fd88fbce5d574b Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 18 Apr 2025 10:11:42 +1200 Subject: [PATCH 085/238] Fix crash when clearing NRF52 BLE bonds (#6609) * Fix crash before clearing BLE bonds * Prevent clients re-pairing BLE during factory reset Clients seem able to re-pair BLE after clearing bonds during factory reset, even after advertising disabled. This seems to primarily occur on Android devices, which seem to more actively maintain the BLE connection. As a workaround, `NRF52Bluetooth::shutdown` swaps the BLE pairing callback to one which actively rejects new connections. --------- Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 1 - src/platform/nrf52/NRF52Bluetooth.cpp | 40 +++++++++++++++++++-------- src/platform/nrf52/NRF52Bluetooth.h | 3 ++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 90a90e89f..67f0da600 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -450,7 +450,6 @@ bool NodeDB::factoryReset(bool eraseBleBonds) nvs_flash_erase(); #endif #ifdef ARCH_NRF52 - Bluefruit.begin(); LOG_INFO("Clear bluetooth bonds!"); bond_print_list(BLE_GAP_ROLE_PERIPH); bond_print_list(BLE_GAP_ROLE_CENTRAL); diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp index 87d8adfa9..4f6fe7c6b 100644 --- a/src/platform/nrf52/NRF52Bluetooth.cpp +++ b/src/platform/nrf52/NRF52Bluetooth.cpp @@ -210,17 +210,8 @@ void NRF52Bluetooth::shutdown() { // Shutdown bluetooth for minimum power draw LOG_INFO("Disable NRF52 bluetooth"); - uint8_t connection_num = Bluefruit.connected(); - if (connection_num) { - for (uint8_t i = 0; i < connection_num; i++) { - LOG_INFO("NRF52 bluetooth disconnecting handle %d", i); - Bluefruit.disconnect(i); - } - // Wait for disconnection - while (Bluefruit.connected()) - yield(); - LOG_INFO("All bluetooth connections ended"); - } + Bluefruit.Security.setPairPasskeyCallback(NRF52Bluetooth::onUnwantedPairing); // Actively refuse (during factory reset) + disconnect(); Bluefruit.Advertising.stop(); } void NRF52Bluetooth::startDisabled() @@ -372,6 +363,33 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke LOG_INFO("BLE passkey pair: match_request=%i", match_request); return true; } + +// Actively refuse new BLE pairings +// After clearing bonds (at factory reset), clients seem initially able to attempt to re-pair, even with advertising disabled. +// On NRF52Bluetooth::shutdown, we change the pairing callback to this method, to aggressively refuse any connection attempts. +bool NRF52Bluetooth::onUnwantedPairing(uint16_t conn_handle, uint8_t const passkey[6], bool match_request) +{ + NRF52Bluetooth::disconnect(); + return false; +} + +// Disconnect any BLE connections +void NRF52Bluetooth::disconnect() +{ + uint8_t connection_num = Bluefruit.connected(); + if (connection_num) { + // Close all connections. We're only expecting one. + for (uint8_t i = 0; i < connection_num; i++) + Bluefruit.disconnect(i); + + // Wait for disconnection + while (Bluefruit.connected()) + yield(); + + LOG_INFO("Ended BLE connection"); + } +} + void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_status) { if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS) { diff --git a/src/platform/nrf52/NRF52Bluetooth.h b/src/platform/nrf52/NRF52Bluetooth.h index 2229163f8..630ab05bc 100644 --- a/src/platform/nrf52/NRF52Bluetooth.h +++ b/src/platform/nrf52/NRF52Bluetooth.h @@ -19,4 +19,7 @@ class NRF52Bluetooth : BluetoothApi static void onConnectionSecured(uint16_t conn_handle); static bool onPairingPasskey(uint16_t conn_handle, uint8_t const passkey[6], bool match_request); static void onPairingCompleted(uint16_t conn_handle, uint8_t auth_status); + + static bool onUnwantedPairing(uint16_t conn_handle, uint8_t const passkey[6], bool match_request); + static void disconnect(); }; \ No newline at end of file From 9da141aa8c062bfb3664214d0945fb95b6a44e8a Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 18 Apr 2025 08:27:38 -0400 Subject: [PATCH 086/238] Add TFT docker builds (for CI) (#6614) --- .github/workflows/docker_build.yml | 7 +++++++ .github/workflows/main_matrix.yml | 26 ++++++++++++++++++++++---- Dockerfile | 13 ++++++++----- alpine.Dockerfile | 6 ++++-- bin/build-native.sh | 7 ++++--- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index eec0785c0..cde7fd274 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -26,6 +26,11 @@ on: required: false type: boolean default: false + pio_env: + description: PlatformIO environment to build + required: false + type: string + default: native outputs: digest: description: Digest of built image @@ -90,3 +95,5 @@ jobs: push: ${{ inputs.push }} tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job platforms: ${{ inputs.platform }} + build-args: | + PIO_ENV=${{ inputs.pio_env }} diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 5b11926f2..0889ce22e 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -145,7 +145,7 @@ jobs: test-native: uses: ./.github/workflows/test_native.yml - docker-debian-amd64: + docker-deb-amd64: uses: ./.github/workflows/docker_build.yml with: distro: debian @@ -153,7 +153,16 @@ jobs: runs-on: ubuntu-24.04 push: false - docker-alpine-amd64: + docker-deb-amd64-tft: + uses: ./.github/workflows/docker_build.yml + with: + distro: debian + platform: linux/amd64 + runs-on: ubuntu-24.04 + push: false + pio_env: native-tft + + docker-alp-amd64: uses: ./.github/workflows/docker_build.yml with: distro: alpine @@ -161,7 +170,16 @@ jobs: runs-on: ubuntu-24.04 push: false - docker-debian-arm64: + docker-alp-amd64-tft: + uses: ./.github/workflows/docker_build.yml + with: + distro: alpine + platform: linux/amd64 + runs-on: ubuntu-24.04 + push: false + pio_env: native-tft + + docker-deb-arm64: uses: ./.github/workflows/docker_build.yml with: distro: debian @@ -169,7 +187,7 @@ jobs: runs-on: ubuntu-24.04-arm push: false - docker-debian-armv7: + docker-deb-armv7: uses: ./.github/workflows/docker_build.yml with: distro: debian diff --git a/Dockerfile b/Dockerfile index 55580c579..be192f216 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ # trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue # trunk-ignore-all(trivy/DS002): We must run as root for this container -# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions # trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions +ARG PIO_ENV=native FROM python:3.13-bookworm AS builder ENV DEBIAN_FRONTEND=noninteractive @@ -12,9 +12,10 @@ ENV TZ=Etc/UTC # Install Dependencies ENV PIP_ROOT_USER_ACTION=ignore RUN apt-get update && apt-get install --no-install-recommends -y \ - curl wget g++ zip git ca-certificates \ + curl wget g++ zip git ca-certificates pkg-config \ libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \ - libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \ + libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \ + libx11-dev libinput-dev libxkbcommon-x11-dev \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && pip install --no-cache-dir -U platformio \ && mkdir /tmp/firmware @@ -24,7 +25,7 @@ WORKDIR /tmp/firmware COPY . /tmp/firmware # Build -RUN bash ./bin/build-native.sh && \ +RUN bash ./bin/build-native.sh "$PIO_ENV" && \ cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" # Fetch web assets @@ -44,7 +45,9 @@ ENV TZ=Etc/UTC USER root RUN apt-get update && apt-get --no-install-recommends -y install \ - libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \ + libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev \ + liborcania2.3 libulfius2.7 libssl3 \ + libx11-6 libinput10 libxkbcommon-x11-0 \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/lib/meshtasticd \ && mkdir -p /etc/meshtasticd/config.d \ diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 17afc2964..f85c147da 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -1,8 +1,8 @@ # trunk-ignore-all(trivy/DS002): We must run as root for this container -# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions # trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions +ARG PIO_ENV=native FROM python:3.13-alpine3.21 AS builder @@ -10,6 +10,7 @@ ENV PIP_ROOT_USER_ACTION=ignore RUN apk --no-cache add \ bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \ libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \ + libx11-dev libinput-dev libxkbcommon-dev \ && rm -rf /var/cache/apk/* \ && pip install --no-cache-dir -U platformio \ && mkdir /tmp/firmware @@ -21,7 +22,7 @@ COPY . /tmp/firmware # Add `argp` for musl ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp" -RUN bash ./bin/build-native.sh && \ +RUN bash ./bin/build-native.sh "$PIO_ENV" && \ cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" # ##### PRODUCTION BUILD ############# @@ -33,6 +34,7 @@ USER root RUN apk --no-cache add \ libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \ + libx11 libinput libxkbcommon \ && rm -rf /var/cache/apk/* \ && mkdir -p /var/lib/meshtasticd \ && mkdir -p /etc/meshtasticd/config.d \ diff --git a/bin/build-native.sh b/bin/build-native.sh index c6b1434dd..51379ad76 100755 --- a/bin/build-native.sh +++ b/bin/build-native.sh @@ -15,6 +15,7 @@ platformioFailed() { VERSION=$(bin/buildinfo.py long) SHORT_VERSION=$(bin/buildinfo.py short) +PIO_ENV=${1:-native} OUTDIR=release/ @@ -24,7 +25,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 -pio pkg update --environment native || platformioFailed -pio run --environment native || platformioFailed -cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)" +pio pkg update --environment "$PIO_ENV" || platformioFailed +pio run --environment "$PIO_ENV" || platformioFailed +cp ".pio/build/$PIO_ENV/program" "$OUTDIR/meshtasticd_linux_$(uname -m)" cp bin/native-install.* $OUTDIR From 64a1cd3f99ca39f08f302b0cecd6b6aa0fdf4231 Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 18 Apr 2025 10:29:39 -0400 Subject: [PATCH 087/238] Docker is fun (#6623) --- Dockerfile | 2 +- alpine.Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index be192f216..6c1b83653 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,9 +3,9 @@ # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions # trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions -ARG PIO_ENV=native FROM python:3.13-bookworm AS builder +ARG PIO_ENV=native ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Etc/UTC diff --git a/alpine.Dockerfile b/alpine.Dockerfile index f85c147da..f4a95095d 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -2,11 +2,11 @@ # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions # trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions -ARG PIO_ENV=native FROM python:3.13-alpine3.21 AS builder - +ARG PIO_ENV=native ENV PIP_ROOT_USER_ACTION=ignore + RUN apk --no-cache add \ bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \ libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \ From 5ab1db01420210896082eb4fcc2be741a23b1d70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 18 Apr 2025 09:36:23 -0500 Subject: [PATCH 088/238] chore(deps): update meshtastic-device-ui digest to 65eb74f (#6624) 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 85505d63a..f0756cb89 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/da8fb5eaac7874c31508fad5252999ec82c02498.zip + https://github.com/meshtastic/device-ui/archive/65eb74fadf373e3ceec0bddb95a7cb978e2acd81.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From c6e5ec055f9bb44b823d0895eea053726fe07e3d Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 18 Apr 2025 20:48:32 -0400 Subject: [PATCH 089/238] RPM: Build native-tft target (#6613) --- meshtasticd.spec.rpkg | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/meshtasticd.spec.rpkg b/meshtasticd.spec.rpkg index 4d6c9d6f5..2d777bc76 100644 --- a/meshtasticd.spec.rpkg +++ b/meshtasticd.spec.rpkg @@ -42,6 +42,10 @@ BuildRequires: pkgconfig(openssl) BuildRequires: pkgconfig(liborcania) BuildRequires: pkgconfig(libyder) BuildRequires: pkgconfig(libulfius) +# TFT components: +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(libinput) +BuildRequires: pkgconfig(xkbcommon-x11) %description Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid @@ -55,12 +59,12 @@ tar -xf %{SOURCE1} -C web gzip -dr web %build -# Use the “native” environment from platformio to build a Linux binary -platformio run -e native +# Use the “native-tft” environment from platformio to build a Linux binary +platformio run -e native-tft %install mkdir -p %{buildroot}%{_sbindir} -install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd +install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml From d26b50b78c28cf9cfaf2002fce0946b0fb14d36d Mon Sep 17 00:00:00 2001 From: Austin Date: Sat, 19 Apr 2025 00:29:59 -0400 Subject: [PATCH 090/238] docker alpine: Add available.d config templates (#6631) --- alpine.Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/alpine.Dockerfile b/alpine.Dockerfile index f4a95095d..350129040 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -39,7 +39,11 @@ RUN apk --no-cache add \ && mkdir -p /var/lib/meshtasticd \ && mkdir -p /etc/meshtasticd/config.d \ && mkdir -p /etc/meshtasticd/ssl + +# Fetch compiled binary from the builder COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/ +# Copy config templates +COPY ./bin/config.d /etc/meshtasticd/available.d WORKDIR /var/lib/meshtasticd VOLUME /var/lib/meshtasticd From 916afb5098d320cacb324e81d0f663a57696ba12 Mon Sep 17 00:00:00 2001 From: Austin Date: Sat, 19 Apr 2025 10:56:41 -0400 Subject: [PATCH 091/238] appdata.xml: Add date to all releases (#6632) --- bin/org.meshtastic.meshtasticd.metainfo.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index cb921fcb3..32e6eb077 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -1,4 +1,4 @@ - + org.meshtastic.meshtasticd @@ -87,13 +87,13 @@ - + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6 - + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5 - + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4 From a30f431b6a89261ef02ed115bd78f51cb0294299 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 19 Apr 2025 18:49:05 +0200 Subject: [PATCH 092/238] Update Kongduino-Adafruit_nRFCrypto digest to 5f838d2 (#6634) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- arch/nrf52/nrf52840.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nrf52/nrf52840.ini b/arch/nrf52/nrf52840.ini index fb5ba9960..f0a4ab6c0 100644 --- a/arch/nrf52/nrf52840.ini +++ b/arch/nrf52/nrf52840.ini @@ -7,7 +7,7 @@ lib_deps = ${nrf52_base.lib_deps} ${environmental_base.lib_deps} # renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master - https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip + https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip ; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board. From 2b57ffafd78c15adc024268d6882f6cc1c57cd63 Mon Sep 17 00:00:00 2001 From: Nivek-domo <123359286+Nivek-domo@users.noreply.github.com> Date: Sun, 20 Apr 2025 10:51:01 +0200 Subject: [PATCH 093/238] Rak13800 Ethernet works on rak11310 too we can use rak13800 on rak11310 too --- src/mesh/api/ServerAPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/api/ServerAPI.h b/src/mesh/api/ServerAPI.h index fe6a733a7..111314476 100644 --- a/src/mesh/api/ServerAPI.h +++ b/src/mesh/api/ServerAPI.h @@ -43,7 +43,7 @@ template class APIServerPort : public U, private concurrency: * delegate to the worker. Once coroutines are implemented we can relax this restriction. */ T *openAPI = NULL; -#if RAK_4631 +#if defined(RAK_4631) || defined(RAK11310) // Track wait time for RAK13800 Ethernet requests int32_t waitTime = 100; #endif From 5d48d2c0a74b1a561246899e7786aa1460cf0ef1 Mon Sep 17 00:00:00 2001 From: Nivek-domo <123359286+Nivek-domo@users.noreply.github.com> Date: Sun, 20 Apr 2025 12:06:39 +0200 Subject: [PATCH 094/238] Add IP Address Frame (#6615) * Update Screen.cpp add ip on screen if has ethernet pcb like w5500 spi * Run Trunk Format and Translate Comments FR->EN --------- Co-authored-by: Tom Fifield --- src/graphics/Screen.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index ad0b94efe..45706cf33 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -56,6 +56,10 @@ along with this program. If not, see . #include "mesh/wifi/WiFiAPClient.h" #endif +#if HAS_ETHERNET +#include "mesh/eth/ethClient.h" +#endif + #ifdef ARCH_ESP32 #include "esp_task_wdt.h" #include "modules/StoreForwardModule.h" @@ -232,6 +236,42 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i #endif +#if HAS_ETHERNET +static void drawEthernetFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + display->setFont(FONT_SMALL); + display->setTextAlignment(TEXT_ALIGN_LEFT); + + if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) { + display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL); + display->setColor(BLACK); + } + + display->setColor(WHITE); + + // Adjust vertical position verticale ajustée - starts higher + int16_t y_offset = y + 2; // Reduces space at top + + // Left Alignement (x + small offset) + int16_t x_offset = x + 2; + + // Display is not centered, align left + display->drawString(x_offset, y_offset, "Ethernet Config:"); + y_offset += FONT_HEIGHT_SMALL + 2; // Slightly reduced spacing + + display->drawString(x_offset, y_offset, "IP: " + Ethernet.localIP().toString()); + y_offset += FONT_HEIGHT_SMALL; + + display->drawString(x_offset, y_offset, "Mask: " + Ethernet.subnetMask().toString()); + y_offset += FONT_HEIGHT_SMALL; + + display->drawString(x_offset, y_offset, "GW: " + Ethernet.gatewayIP().toString()); + // y_offset += FONT_HEIGHT_SMALL; + + // display->drawString(x_offset, y_offset, "DNS: " + Ethernet.dnsServerIP().toString()); +} +#endif + void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message) { uint16_t x_offset = display->width() / 2; @@ -2182,6 +2222,12 @@ void Screen::setFrames(FrameFocus focus) } #endif +#if HAS_ETHERNET + if (Ethernet.hardwareStatus() != EthernetNoHardware) { + normalFrames[numframes++] = drawEthernetFrame; + } +#endif + fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE LOG_DEBUG("Finished build frames. numframes: %d", numframes); From e03f3de185e8a67bd08e7af0c3425989e4b6e0ec Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 20 Apr 2025 10:45:58 -0400 Subject: [PATCH 095/238] Build and deploy event firmwares (#6628) --- .github/workflows/main_matrix.yml | 52 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 0889ce22e..b6a0a3445 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -5,14 +5,20 @@ concurrency: on: # # Triggers the workflow on push but only for the master branch push: - branches: [master, develop] + branches: + - master + - develop + - event/* paths-ignore: - "**.md" - version.properties # Note: This is different from "pull_request". Need to specify ref when doing checkouts. pull_request_target: - branches: [master, develop] + branches: + - master + - develop + - event/* paths-ignore: - "**.md" #- "**.yml" @@ -32,12 +38,12 @@ jobs: name: Checkout base - id: jsonStep run: | - if [[ "${{ github.head_ref }}" == "" ]]; then + if [[ "$GITHUB_HEAD_REF" == "" ]]; then TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}}) else TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick) fi - echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS" + echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS" echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT outputs: esp32: ${{ steps.jsonStep.outputs.esp32 }} @@ -195,17 +201,6 @@ jobs: runs-on: ubuntu-24.04-arm push: false - after-checks: - runs-on: ubuntu-latest - if: ${{ github.event_name != 'workflow_dispatch' }} - needs: [check] - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} - gather-artifacts: permissions: contents: write @@ -350,7 +345,7 @@ jobs: merge-multiple: true path: ./output/pio-deps-native-tft - - name: Zip linux sources + - name: Zip Linux sources working-directory: output run: | zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src @@ -360,7 +355,9 @@ jobs: - name: Display structure of downloaded files run: ls -lR - - name: Add linux sources to release + - name: Add Linux sources to GtiHub Release + # Only run when targeting master branch with workflow_dispatch + if: ${{ github.ref_name == 'master' }} run: | gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip @@ -418,9 +415,28 @@ jobs: - name: Display structure of downloaded files run: ls -lR - - name: Add bins and debug elfs to release + - name: Add bins and debug elfs to GitHub Release + # Only run when targeting master branch with workflow_dispatch + if: ${{ github.ref_name == 'master' }} run: | gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish firmware to meshtastic.github.io + uses: peaceiris/actions-gh-pages@v4 + env: + # On event/* branches, use the event name as the destination prefix + DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }} + with: + deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }} + external_repository: meshtastic/meshtastic.github.io + publish_branch: master + publish_dir: ./output + destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }} + keep_files: true + user_name: github-actions[bot] + user_email: github-actions[bot]@users.noreply.github.com + commit_message: ${{ steps.version.outputs.long }} ${{ matrix.arch }} + enable_jekyll: true From 48dc0e014c451fed8b3979d8548a8f328a613301 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 20 Apr 2025 09:48:07 -0500 Subject: [PATCH 096/238] Revert "Lib Update (#6510)" (#6640) This reverts commit e2f6600cb955f8de86175a87fae36f49863ba72f. --- arch/esp32/esp32.ini | 2 +- src/nimble/NimbleBluetooth.cpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 35f3a5a1c..5e15cb451 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -50,7 +50,7 @@ lib_deps = # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino - h2zero/NimBLE-Arduino@^2.2.3 + h2zero/NimBLE-Arduino@^1.4.3 # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip # renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 208d8ae3c..009439f25 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -49,7 +49,7 @@ static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE]; class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks { - virtual void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) + virtual void onWrite(NimBLECharacteristic *pCharacteristic) { LOG_DEBUG("To Radio onwrite"); auto val = pCharacteristic->getValue(); @@ -66,7 +66,7 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks { - virtual void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) + virtual void onRead(NimBLECharacteristic *pCharacteristic) { uint8_t fromRadioBytes[meshtastic_FromRadio_size]; size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes); @@ -79,7 +79,7 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothServerCallback : public NimBLEServerCallbacks { - virtual uint32_t onPassKeyDisplay() + virtual uint32_t onPassKeyRequest() { uint32_t passkey = config.bluetooth.fixed_pin; @@ -125,7 +125,7 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks return passkey; } - virtual void onAuthenticationComplete(NimBLEConnInfo &connInfo) + virtual void onAuthenticationComplete(ble_gap_conn_desc *desc) { LOG_INFO("BLE authentication complete"); @@ -138,9 +138,9 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks } } - virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) + virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc) { - LOG_INFO("BLE disconnect. Reason %i", reason); + LOG_INFO("BLE disconnect"); bluetoothStatus->updateStatus( new meshtastic::BluetoothStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED)); @@ -191,7 +191,7 @@ int NimbleBluetooth::getRssi() if (bleServer && isConnected()) { auto service = bleServer->getServiceByUUID(MESH_SERVICE_UUID); uint16_t handle = service->getHandle(); - return NimBLEDevice::getClientByHandle(handle)->getRssi(); + return NimBLEDevice::getClientByID(handle)->getRssi(); } return 0; // FIXME figure out where to source this } @@ -216,7 +216,6 @@ void NimbleBluetooth::setup() NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback(); bleServer->setCallbacks(serverCallbacks, true); - bleServer->advertiseOnDisconnect(true); setupService(); startAdvertising(); } @@ -260,7 +259,7 @@ void NimbleBluetooth::setupService() BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic) (uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1); - NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->create2904(); + NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904); batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8); batteryLevelDescriptor->setNamespace(1); batteryLevelDescriptor->setUnit(0x27ad); From 8812eadd4444386919d985d4370756cc28aa9093 Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 20 Apr 2025 10:49:21 -0400 Subject: [PATCH 097/238] Revert "Add IP Address Frame (#6615)" (#6639) This reverts commit 5d48d2c0a74b1a561246899e7786aa1460cf0ef1. --- src/graphics/Screen.cpp | 46 ----------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 45706cf33..ad0b94efe 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -56,10 +56,6 @@ along with this program. If not, see . #include "mesh/wifi/WiFiAPClient.h" #endif -#if HAS_ETHERNET -#include "mesh/eth/ethClient.h" -#endif - #ifdef ARCH_ESP32 #include "esp_task_wdt.h" #include "modules/StoreForwardModule.h" @@ -236,42 +232,6 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i #endif -#if HAS_ETHERNET -static void drawEthernetFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ - display->setFont(FONT_SMALL); - display->setTextAlignment(TEXT_ALIGN_LEFT); - - if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) { - display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL); - display->setColor(BLACK); - } - - display->setColor(WHITE); - - // Adjust vertical position verticale ajustée - starts higher - int16_t y_offset = y + 2; // Reduces space at top - - // Left Alignement (x + small offset) - int16_t x_offset = x + 2; - - // Display is not centered, align left - display->drawString(x_offset, y_offset, "Ethernet Config:"); - y_offset += FONT_HEIGHT_SMALL + 2; // Slightly reduced spacing - - display->drawString(x_offset, y_offset, "IP: " + Ethernet.localIP().toString()); - y_offset += FONT_HEIGHT_SMALL; - - display->drawString(x_offset, y_offset, "Mask: " + Ethernet.subnetMask().toString()); - y_offset += FONT_HEIGHT_SMALL; - - display->drawString(x_offset, y_offset, "GW: " + Ethernet.gatewayIP().toString()); - // y_offset += FONT_HEIGHT_SMALL; - - // display->drawString(x_offset, y_offset, "DNS: " + Ethernet.dnsServerIP().toString()); -} -#endif - void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message) { uint16_t x_offset = display->width() / 2; @@ -2222,12 +2182,6 @@ void Screen::setFrames(FrameFocus focus) } #endif -#if HAS_ETHERNET - if (Ethernet.hardwareStatus() != EthernetNoHardware) { - normalFrames[numframes++] = drawEthernetFrame; - } -#endif - fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE LOG_DEBUG("Finished build frames. numframes: %d", numframes); From 72dd5bd88d541eaa8b91dd02ec66a0b8ece41b29 Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 20 Apr 2025 16:31:47 -0400 Subject: [PATCH 098/238] Publish firmware all together (#6642) --- .github/workflows/main_matrix.yml | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index b6a0a3445..a9c4cbb52 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -424,6 +424,31 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish-firmware: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' }} + needs: [release-firmware] + env: + targets: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,stm32 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Get release version string + run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - uses: actions/download-artifact@v4 + with: + pattern: firmware-{${{ env.targets }}}-${{ steps.version.outputs.long }} + merge-multiple: true + path: ./publish + - name: Publish firmware to meshtastic.github.io uses: peaceiris/actions-gh-pages@v4 env: @@ -433,10 +458,10 @@ jobs: deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }} external_repository: meshtastic/meshtastic.github.io publish_branch: master - publish_dir: ./output + publish_dir: ./publish destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }} keep_files: true user_name: github-actions[bot] user_email: github-actions[bot]@users.noreply.github.com - commit_message: ${{ steps.version.outputs.long }} ${{ matrix.arch }} + commit_message: ${{ steps.version.outputs.long }} enable_jekyll: true From 24e9539d40f91b8e6a0ec533fc688cfee3d0da5a Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:25:07 +0200 Subject: [PATCH 099/238] remove buzzer (#6652) --- variants/seeed-sensecap-indicator/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/seeed-sensecap-indicator/platformio.ini b/variants/seeed-sensecap-indicator/platformio.ini index fb51d77c3..b643288a6 100644 --- a/variants/seeed-sensecap-indicator/platformio.ini +++ b/variants/seeed-sensecap-indicator/platformio.ini @@ -49,7 +49,6 @@ build_flags = -D HAS_SCREEN=0 -D HAS_TFT=1 -D DISPLAY_SET_RESOLUTION - -D USE_PIN_BUZZER -D RAM_SIZE=4096 -D LV_LVGL_H_INCLUDE_SIMPLE -D LV_CONF_INCLUDE_SIMPLE From 70ced735d966724f665bf3442e9e261c51b12a2e Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Tue, 22 Apr 2025 23:25:53 +1200 Subject: [PATCH 100/238] Correct a typing error in InkHUD display driver (#6651) * Fix LCMEN2R13EFC1 LUT A typing error when the driver was initially created. * Spelling.. --- src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp b/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp index c843c4694..13a3f452d 100644 --- a/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp @@ -42,11 +42,10 @@ static const uint8_t LUT_FAST_BW[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // }; -// Look up table: fash refresh, pixels which change from white to black +// Look up table: fast refresh, pixels which change from white to black static const uint8_t LUT_FAST_WB[] = { - 0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, // - 0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, // 0x01, 0x46, 0x43, 0x02, 0x01, 0x01, 0x01, // + 0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // @@ -55,7 +54,7 @@ static const uint8_t LUT_FAST_WB[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // }; -// Look up table: fash refresh, pixels which remain black +// Look up table: fast refresh, pixels which remain black static const uint8_t LUT_FAST_BB[] = { 0x01, 0x06, 0x03, 0x42, 0x41, 0x01, 0x01, // 0x01, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, // From b1e35cd8b36a57098184491dc3841d83ff65ec76 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Tue, 22 Apr 2025 21:21:29 +0200 Subject: [PATCH 101/238] Fix preamble detected IRQ flag (#6653) --- src/mesh/LR11x0Interface.cpp | 4 ++-- src/mesh/RadioLibInterface.h | 3 +++ src/mesh/SX126xInterface.cpp | 3 +-- src/mesh/SX128xInterface.cpp | 3 +-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 2b060ad38..aecc8f722 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -247,8 +247,8 @@ template void LR11x0Interface::startReceive() lora.setPreambleLength(preambleLength); // Solve RX ack fail after direct message sent. Not sure why this is needed. // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. - // Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving - int err = lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0); + int err = + lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0); assert(err == RADIOLIB_ERR_NONE); RadioLibInterface::startReceive(); diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 9622bd625..2ab2679c0 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -16,6 +16,9 @@ #define RADIOLIB_PIN_TYPE uint32_t +// In addition to the default Rx flags, we need the PREAMBLE_DETECTED flag to detect whether we are actively receiving +#define MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS (RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1 << RADIOLIB_IRQ_PREAMBLE_DETECTED)) + /** * We need to override the RadioLib ArduinoHal class to add mutex protection for SPI bus access */ diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 6a4be023b..c867466b7 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -277,8 +277,7 @@ template void SX126xInterface::startReceive() setStandby(); // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. - // Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving - int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED); + int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS); if (err != RADIOLIB_ERR_NONE) LOG_ERROR("SX126X startReceiveDutyCycleAuto %s%d", radioLibErr, err); assert(err == RADIOLIB_ERR_NONE); diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index e06f274e7..23a023d3f 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -260,8 +260,7 @@ template void SX128xInterface::startReceive() #endif #endif - // We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving - int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED); + int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS); if (err != RADIOLIB_ERR_NONE) LOG_ERROR("SX128X startReceive %s%d", radioLibErr, err); From 45fcd479f61a5350ead219dcba0e2610aa55da2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:50:35 +0200 Subject: [PATCH 102/238] Update meshtastic-device-ui digest to 189ed6c (#6657) 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 f0756cb89..fe87fb3d8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/65eb74fadf373e3ceec0bddb95a7cb978e2acd81.zip + https://github.com/meshtastic/device-ui/archive/189ed6cba42c218e79142a876987f4516d0c87fd.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 89df9d7686390aebecff349b63b9ffb2b333a69d Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 25 Apr 2025 13:40:48 +1200 Subject: [PATCH 103/238] Fix WiPhone variant.h (#6664) --- variants/wiphone/variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/wiphone/variant.h b/variants/wiphone/variant.h index cfa5667bb..70973db16 100644 --- a/variants/wiphone/variant.h +++ b/variants/wiphone/variant.h @@ -24,7 +24,7 @@ // This board has no GPS or Screen for now #undef GPS_RX_PIN #undef GPS_TX_PIN -#define NO_GPS +#define NO_GPS 1 #define HAS_GPS 0 #define NO_SCREEN #define HAS_SCREEN 0 From 03f19bca0e9e456342dfb0397a805404677e5abc Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 25 Apr 2025 12:30:20 -0400 Subject: [PATCH 104/238] Downgrade web to 2.5.4 (#6669) --- bin/web.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/web.version b/bin/web.version index 914ec9671..d21aa93cc 100644 --- a/bin/web.version +++ b/bin/web.version @@ -1 +1 @@ -2.6.0 \ No newline at end of file +2.5.4 \ No newline at end of file From 54c1423039bbb2b6fdecc807843eef8de47a6b41 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 26 Apr 2025 06:17:08 -0500 Subject: [PATCH 105/238] Use the last GOOD version --- bin/web.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/web.version b/bin/web.version index d21aa93cc..a4db534a2 100644 --- a/bin/web.version +++ b/bin/web.version @@ -1 +1 @@ -2.5.4 \ No newline at end of file +2.5.3 \ No newline at end of file From 77e6868d5dbcf280fa19cfae0d10c7ecc1834411 Mon Sep 17 00:00:00 2001 From: Kalle Lilja <15094562+ThatKalle@users.noreply.github.com> Date: Mon, 28 Apr 2025 22:47:09 +0200 Subject: [PATCH 106/238] Fix create pull request (#6680) * add base property * bump to 2.6.7 - manual * disable pip version check --- .github/workflows/release_channels.yml | 3 +++ bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ version.properties | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release_channels.yml b/.github/workflows/release_channels.yml index eece12346..12d66b9c2 100644 --- a/.github/workflows/release_channels.yml +++ b/.github/workflows/release_channels.yml @@ -95,10 +95,13 @@ jobs: pip install -r bin/bump_metainfo/requirements.txt -q chmod +x ./bin/bump_metainfo/bump_metainfo.py ./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.version.outputs.short }}" + env: + PIP_DISABLE_PIP_VERSION_CHECK: 1 - name: Create Bumps pull request uses: peter-evans/create-pull-request@v7 with: + base: ${{ github.event.repository.default_branch }} title: Bump release version commit-message: automated bumps add-paths: | diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 32e6eb077..2cfba3523 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6 diff --git a/version.properties b/version.properties index 8f5953fdc..5baa63dc2 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 6 +build = 7 From ca8c1773634fd2781b6e2cc2631a134c880a249b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Apr 2025 08:24:00 +1000 Subject: [PATCH 107/238] Update meshtastic-device-ui digest to 8113d4f (#6677) 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 fe87fb3d8..9ed780c87 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/189ed6cba42c218e79142a876987f4516d0c87fd.zip + https://github.com/meshtastic/device-ui/archive/8113d4ff5a63280834acfeb7584f179cdc6376b6.zip ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) From 473ef1bc032c4d898cab090b9e3a3cd632092993 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 28 Apr 2025 18:35:13 -0500 Subject: [PATCH 108/238] Step one of Linux Sensor support (#6673) * First addition of __has_include for sensor support * Add __has_include blocks for sensors * Put BMP and BME back in the right sensors * Make TelemetrySensor::setup() a pure virtual finction * Split environmental_base to environmental_extra, to compile the working sensor libs for Native * Remove hard-coded checks for ARCH_PORTDUINO * Un-clobber bmx160 * Move BusIO to environmental_extra due to Armv7 compile error * Move to forked BusIO for the moment * Enable HAS_SENSOR for Portduino * Move back to Adafruit BusIO after patch --- arch/esp32/esp32.ini | 1 + arch/esp32/esp32c6.ini | 1 + arch/nrf52/nrf52840.ini | 1 + arch/portduino/portduino.ini | 6 +- arch/rp2xx0/rp2040.ini | 1 + arch/rp2xx0/rp2350.ini | 1 + platformio.ini | 59 +++--- src/Power.cpp | 51 ++++-- src/modules/Telemetry/AirQualityTelemetry.cpp | 2 +- src/modules/Telemetry/AirQualityTelemetry.h | 2 +- src/modules/Telemetry/DeviceTelemetry.cpp | 4 - .../Telemetry/EnvironmentTelemetry.cpp | 170 ++++++++++++++---- src/modules/Telemetry/PowerTelemetry.cpp | 4 +- src/modules/Telemetry/Sensor/AHT10.cpp | 2 +- src/modules/Telemetry/Sensor/AHT10.h | 2 +- src/modules/Telemetry/Sensor/BME280Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/BME280Sensor.h | 2 +- src/modules/Telemetry/Sensor/BME680Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/BME680Sensor.h | 2 +- src/modules/Telemetry/Sensor/BMP085Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/BMP085Sensor.h | 2 +- src/modules/Telemetry/Sensor/BMP280Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/BMP280Sensor.h | 2 +- src/modules/Telemetry/Sensor/BMP3XXSensor.cpp | 2 +- src/modules/Telemetry/Sensor/BMP3XXSensor.h | 2 +- .../Telemetry/Sensor/DFRobotGravitySensor.cpp | 2 +- .../Telemetry/Sensor/DFRobotGravitySensor.h | 2 +- .../Telemetry/Sensor/DFRobotLarkSensor.cpp | 2 +- .../Telemetry/Sensor/DFRobotLarkSensor.h | 2 +- src/modules/Telemetry/Sensor/DPS310Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/DPS310Sensor.h | 2 +- src/modules/Telemetry/Sensor/INA219Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/INA219Sensor.h | 2 +- src/modules/Telemetry/Sensor/INA226Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/INA260Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/INA260Sensor.h | 2 +- .../Telemetry/Sensor/INA3221Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/INA3221Sensor.h | 2 +- .../Telemetry/Sensor/LPS22HBSensor.cpp | 2 +- src/modules/Telemetry/Sensor/LPS22HBSensor.h | 2 +- .../Telemetry/Sensor/MAX17048Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/MAX17048Sensor.h | 2 +- .../Telemetry/Sensor/MAX30102Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/MAX30102Sensor.h | 2 +- .../Telemetry/Sensor/MCP9808Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/MCP9808Sensor.h | 2 +- .../Telemetry/Sensor/MLX90614Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/MLX90614Sensor.h | 2 +- .../Telemetry/Sensor/MLX90632Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/MLX90632Sensor.h | 2 +- .../Telemetry/Sensor/NAU7802Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/NAU7802Sensor.h | 2 +- .../Telemetry/Sensor/OPT3001Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/OPT3001Sensor.h | 2 +- src/modules/Telemetry/Sensor/SHT31Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/SHT31Sensor.h | 2 +- src/modules/Telemetry/Sensor/SHT4XSensor.cpp | 2 +- src/modules/Telemetry/Sensor/SHT4XSensor.h | 2 +- src/modules/Telemetry/Sensor/SHTC3Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/SHTC3Sensor.h | 2 +- .../Telemetry/Sensor/TSL2591Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/TSL2591Sensor.h | 2 +- .../Telemetry/Sensor/TelemetrySensor.h | 4 +- .../Telemetry/Sensor/VEML7700Sensor.cpp | 2 +- src/modules/Telemetry/Sensor/VEML7700Sensor.h | 2 +- src/modules/Telemetry/Sensor/nullSensor.cpp | 23 +++ src/modules/Telemetry/Sensor/nullSensor.h | 22 +++ src/motion/BMA423Sensor.cpp | 2 +- src/motion/BMA423Sensor.h | 2 +- src/motion/BMX160Sensor.cpp | 4 +- src/motion/BMX160Sensor.h | 4 +- src/motion/ICM20948Sensor.cpp | 2 +- src/motion/ICM20948Sensor.h | 2 +- src/motion/LIS3DHSensor.cpp | 2 +- src/motion/LIS3DHSensor.h | 2 +- src/motion/LSM6DS3Sensor.cpp | 2 +- src/motion/LSM6DS3Sensor.h | 2 +- src/motion/MPU6050Sensor.cpp | 2 +- src/motion/MPU6050Sensor.h | 2 +- src/motion/MotionSensor.cpp | 2 +- src/motion/MotionSensor.h | 2 +- src/motion/QMA6100PSensor.cpp | 2 +- src/motion/QMA6100PSensor.h | 2 +- src/motion/STK8XXXSensor.cpp | 2 +- src/motion/STK8XXXSensor.h | 2 +- src/platform/portduino/architecture.h | 3 + src/power.h | 37 +++- 87 files changed, 366 insertions(+), 168 deletions(-) create mode 100644 src/modules/Telemetry/Sensor/nullSensor.cpp create mode 100644 src/modules/Telemetry/Sensor/nullSensor.h diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 5e15cb451..3a6dc8323 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -46,6 +46,7 @@ lib_deps = ${arduino_base.lib_deps} ${networking_base.lib_deps} ${environmental_base.lib_deps} + ${environmental_extra.lib_deps} ${radiolib_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip diff --git a/arch/esp32/esp32c6.ini b/arch/esp32/esp32c6.ini index e1cf955e8..7c7e3e923 100644 --- a/arch/esp32/esp32c6.ini +++ b/arch/esp32/esp32c6.ini @@ -25,6 +25,7 @@ lib_deps = ${arduino_base.lib_deps} ${networking_base.lib_deps} ${environmental_base.lib_deps} + ${environmental_extra.lib_deps} ${radiolib_base.lib_deps} # renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib lewisxhe/XPowersLib@^0.2.7 diff --git a/arch/nrf52/nrf52840.ini b/arch/nrf52/nrf52840.ini index f0a4ab6c0..5e846b3b7 100644 --- a/arch/nrf52/nrf52840.ini +++ b/arch/nrf52/nrf52840.ini @@ -6,6 +6,7 @@ build_flags = ${nrf52_base.build_flags} lib_deps = ${nrf52_base.lib_deps} ${environmental_base.lib_deps} + ${environmental_extra.lib_deps} # renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 1d731f6b7..5dc0daf6b 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -17,15 +17,13 @@ build_src_filter = + - - - - - - - - +<../variants/portduino> lib_deps = ${env.lib_deps} ${networking_base.lib_deps} ${radiolib_base.lib_deps} + ${environmental_base.lib_deps} # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@^0.4.0 # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX @@ -49,3 +47,5 @@ build_flags = -luv -std=gnu17 -std=c++17 + +lib_ignore = Adafruit NeoPixel \ No newline at end of file diff --git a/arch/rp2xx0/rp2040.ini b/arch/rp2xx0/rp2040.ini index cd7e684b4..4f9421872 100644 --- a/arch/rp2xx0/rp2040.ini +++ b/arch/rp2xx0/rp2040.ini @@ -28,6 +28,7 @@ lib_ignore = lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} + ${environmental_extra.lib_deps} ${radiolib_base.lib_deps} # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@0.4.0 diff --git a/arch/rp2xx0/rp2350.ini b/arch/rp2xx0/rp2350.ini index 1c7af8be4..e8611a113 100644 --- a/arch/rp2xx0/rp2350.ini +++ b/arch/rp2xx0/rp2350.ini @@ -25,6 +25,7 @@ lib_ignore = lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} + ${environmental_extra.lib_deps} ${radiolib_base.lib_deps} # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto rweather/Crypto@0.4.0 diff --git a/platformio.ini b/platformio.ini index 9ed780c87..fb121aafe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -111,11 +111,10 @@ lib_deps = https://github.com/meshtastic/device-ui/archive/8113d4ff5a63280834acfeb7584f179cdc6376b6.zip ; Common libs for environmental measurements in telemetry module -; (not included in native / portduino) [environmental_base] lib_deps = - # renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO - adafruit/Adafruit BusIO@1.17.0 + # renovate: datasource=git-refs depName=Adafruit BusIO packageName=https://github.com/adafruit/Adafruit_BusIO gitBranch=master + https://github.com/adafruit/Adafruit_BusIO/archive/5e8f137415f473e390c9410421bb54d828898fad.zip # renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor adafruit/Adafruit Unified Sensor@1.1.15 # renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library @@ -124,8 +123,6 @@ lib_deps = adafruit/Adafruit BMP085 Library@1.2.4 # renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library adafruit/Adafruit BME280 Library@2.2.4 - # renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library - adafruit/Adafruit BMP3XX Library@2.1.6 # renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310 adafruit/Adafruit DPS310@1.1.5 # renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library @@ -134,14 +131,6 @@ lib_deps = adafruit/Adafruit INA260 Library@1.5.2 # renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219 adafruit/Adafruit INA219@1.2.3 - # renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X - adafruit/Adafruit MAX1704X@1.0.3 - # renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library - adafruit/Adafruit SHTC3 Library@1.0.1 - # renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X - adafruit/Adafruit LPS2X@2.0.6 - # renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library - adafruit/Adafruit SHT31 Library@2.2.2 # renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor adafruit/Adafruit PM25 AQI Sensor@1.2.0 # renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050 @@ -152,24 +141,12 @@ lib_deps = adafruit/Adafruit AHTX0@2.0.5 # renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS adafruit/Adafruit LSM6DS@4.7.4 - # renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library - adafruit/Adafruit VEML7700 Library@2.1.6 - # renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library - adafruit/Adafruit SHT4x Library@1.0.5 # renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library adafruit/Adafruit TSL2591 Library@1.4.5 - # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library - sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 - # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library - sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0 - # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 - ClosedCube OPT3001@1.1.2 # renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632 emotibit/EmotiBit MLX90632@1.0.8 # renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library adafruit/Adafruit MLX90614 Library@2.1.5 - # renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library - https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library boschsensortec/BME68x Sensor Library@1.1.40407 # renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221 @@ -178,13 +155,37 @@ lib_deps = mprograms/QMC5883LCompass@1.2.3 # renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU dfrobot/DFRobot_RTU@1.0.3 - # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master - https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip # renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip # renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226 robtillaart/INA226@0.6.4 - - ; Health Sensor Libraries # renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 + +; (not included in native / portduino) +[environmental_extra] +lib_deps = + # renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library + adafruit/Adafruit BMP3XX Library@2.1.6 + # renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X + adafruit/Adafruit MAX1704X@1.0.3 + # renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library + adafruit/Adafruit SHTC3 Library@1.0.1 + # renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X + adafruit/Adafruit LPS2X@2.0.6 + # renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library + adafruit/Adafruit SHT31 Library@2.2.2 + # renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library + adafruit/Adafruit VEML7700 Library@2.1.6 + # renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library + adafruit/Adafruit SHT4x Library@1.0.5 + # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library + sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 + # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library + sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0 + # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 + ClosedCube OPT3001@1.1.2 + # renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library + https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip + # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master + https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip \ No newline at end of file diff --git a/src/Power.cpp b/src/Power.cpp index ed1bd20ef..a9ed6360e 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -76,23 +76,47 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE; #endif #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if __has_include() INA219Sensor ina219Sensor; -INA226Sensor ina226Sensor; -INA260Sensor ina260Sensor; -INA3221Sensor ina3221Sensor; +#else +NullSensor ina219Sensor; #endif -#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if __has_include() +INA226Sensor ina226Sensor; +#else +NullSensor ina226Sensor; +#endif + +#if __has_include() +INA260Sensor ina260Sensor; +#else +NullSensor ina260Sensor; +#endif + +#if __has_include() +INA3221Sensor ina3221Sensor; +#else +NullSensor ina3221Sensor; +#endif + +#endif + +#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL) #include "modules/Telemetry/Sensor/MAX17048Sensor.h" #include extern std::pair nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1]; #if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY) +#if __has_include() MAX17048Sensor max17048Sensor; +#else +NullSensor max17048Sensor; +#endif #endif #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT RAK9154Sensor rak9154Sensor; #endif @@ -203,7 +227,7 @@ class AnalogBatteryLevel : public HasBatteryLevel */ virtual int getBatteryPercent() override { -#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) +#if defined(HAS_RAKPROT) && !defined(HAS_PMU) if (hasRAK()) { return rak9154Sensor.getBusBatteryPercent(); } @@ -248,15 +272,13 @@ class AnalogBatteryLevel : public HasBatteryLevel virtual uint16_t getBattVoltage() override { -#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \ - !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR if (hasRAK()) { return getRAKVoltage(); } #endif -#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \ - !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR if (hasINA()) { return getINAVoltage(); } @@ -426,8 +448,7 @@ class AnalogBatteryLevel : public HasBatteryLevel /// we can't be smart enough to say 'full'? virtual bool isCharging() override { -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \ - !defined(HAS_PMU) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU) if (hasRAK()) { return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse; } @@ -435,7 +456,7 @@ class AnalogBatteryLevel : public HasBatteryLevel #ifdef EXT_CHRG_DETECT return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value; #else -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \ +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) && \ !defined(DISABLE_INA_CHARGING_DETECTION) if (hasINA()) { // get current flow from INA sensor - negative value means power flowing into the battery @@ -482,7 +503,7 @@ class AnalogBatteryLevel : public HasBatteryLevel } #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) uint16_t getINAVoltage() { if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) { diff --git a/src/modules/Telemetry/AirQualityTelemetry.cpp b/src/modules/Telemetry/AirQualityTelemetry.cpp index 392bd6148..1ddb9ca9b 100644 --- a/src/modules/Telemetry/AirQualityTelemetry.cpp +++ b/src/modules/Telemetry/AirQualityTelemetry.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h") #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "AirQualityTelemetry.h" diff --git a/src/modules/Telemetry/AirQualityTelemetry.h b/src/modules/Telemetry/AirQualityTelemetry.h index 3b983bd56..4e82efac3 100644 --- a/src/modules/Telemetry/AirQualityTelemetry.h +++ b/src/modules/Telemetry/AirQualityTelemetry.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h") #pragma once #include "../mesh/generated/meshtastic/telemetry.pb.h" diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 192754e09..251608641 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -99,13 +99,9 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry() t.variant.device_metrics.has_uptime_seconds = true; t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent(); -#if ARCH_PORTDUINO - t.variant.device_metrics.battery_level = MAGIC_USB_BATTERY_LEVEL; -#else t.variant.device_metrics.battery_level = (!powerStatus->getHasBattery() || powerStatus->getIsCharging()) ? MAGIC_USB_BATTERY_LEVEL : powerStatus->getBatteryChargePercent(); -#endif t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent(); t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0; t.variant.device_metrics.uptime_seconds = getUptimeSeconds(); diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 8c0507e77..32c660bbf 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -20,48 +20,144 @@ #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL // Sensors -#include "Sensor/AHT10.h" -#include "Sensor/BME280Sensor.h" -#include "Sensor/BME680Sensor.h" -#include "Sensor/BMP085Sensor.h" -#include "Sensor/BMP280Sensor.h" -#include "Sensor/BMP3XXSensor.h" -#include "Sensor/CGRadSensSensor.h" -#include "Sensor/DFRobotGravitySensor.h" -#include "Sensor/DFRobotLarkSensor.h" -#include "Sensor/DPS310Sensor.h" -#include "Sensor/LPS22HBSensor.h" -#include "Sensor/MCP9808Sensor.h" -#include "Sensor/MLX90632Sensor.h" -#include "Sensor/NAU7802Sensor.h" -#include "Sensor/OPT3001Sensor.h" -#include "Sensor/RCWL9620Sensor.h" -#include "Sensor/SHT31Sensor.h" -#include "Sensor/SHT4XSensor.h" -#include "Sensor/SHTC3Sensor.h" -#include "Sensor/TSL2591Sensor.h" -#include "Sensor/VEML7700Sensor.h" -BMP085Sensor bmp085Sensor; -BMP280Sensor bmp280Sensor; -BME280Sensor bme280Sensor; -BME680Sensor bme680Sensor; -DPS310Sensor dps310Sensor; -MCP9808Sensor mcp9808Sensor; -SHTC3Sensor shtc3Sensor; -LPS22HBSensor lps22hbSensor; -SHT31Sensor sht31Sensor; -VEML7700Sensor veml7700Sensor; -TSL2591Sensor tsl2591Sensor; -OPT3001Sensor opt3001Sensor; -SHT4XSensor sht4xSensor; -RCWL9620Sensor rcwl9620Sensor; +#include "Sensor/CGRadSensSensor.h" +#include "Sensor/RCWL9620Sensor.h" +#include "Sensor/nullSensor.h" + +#if __has_include() +#include "Sensor/AHT10.h" AHT10Sensor aht10Sensor; +#else +NullSensor aht10Sensor; +#endif +#if __has_include() +#include "Sensor/BME280Sensor.h" +BME280Sensor bme280Sensor; +#else +NullSensor bmp280Sensor; +#endif + +#if __has_include() +#include "Sensor/BMP085Sensor.h" +BMP085Sensor bmp085Sensor; +#else +NullSensor bmp085Sensor; +#endif + +#if __has_include() +#include "Sensor/BMP280Sensor.h" +BMP280Sensor bmp280Sensor; +#else +NullSensor bme280Sensor; +#endif + +#if __has_include() +#include "Sensor/BME680Sensor.h" +BME680Sensor bme680Sensor; +#else +NullSensor bme680Sensor; +#endif + +#if __has_include() +#include "Sensor/DPS310Sensor.h" +DPS310Sensor dps310Sensor; +#else +NullSensor dps310Sensor; +#endif + +#if __has_include() +#include "Sensor/MCP9808Sensor.h" +MCP9808Sensor mcp9808Sensor; +#else +NullSensor mcp9808Sensor; +#endif + +#if __has_include() +#include "Sensor/SHT31Sensor.h" +SHT31Sensor sht31Sensor; +#else +NullSensor sht31Sensor; +#endif + +#if __has_include() +#include "Sensor/LPS22HBSensor.h" +LPS22HBSensor lps22hbSensor; +#else +NullSensor lps22hbSensor; +#endif + +#if __has_include() +#include "Sensor/SHTC3Sensor.h" +SHTC3Sensor shtc3Sensor; +#else +NullSensor shtc3Sensor; +#endif + +#if __has_include() +#include "Sensor/VEML7700Sensor.h" +VEML7700Sensor veml7700Sensor; +#else +NullSensor veml7700Sensor; +#endif + +#if __has_include() +#include "Sensor/TSL2591Sensor.h" +TSL2591Sensor tsl2591Sensor; +#else +NullSensor tsl2591Sensor; +#endif + +#if __has_include() +#include "Sensor/OPT3001Sensor.h" +OPT3001Sensor opt3001Sensor; +#else +NullSensor opt3001Sensor; +#endif + +#if __has_include() +#include "Sensor/SHT4XSensor.h" +SHT4XSensor sht4xSensor; +#else +NullSensor sht4xSensor; +#endif + +#if __has_include() +#include "Sensor/MLX90632Sensor.h" MLX90632Sensor mlx90632Sensor; +#else +NullSensor mlx90632Sensor; +#endif + +#if __has_include() +#include "Sensor/DFRobotLarkSensor.h" DFRobotLarkSensor dfRobotLarkSensor; +#else +NullSensor dfRobotLarkSensor; +#endif + +#if __has_include() +#include "Sensor/DFRobotGravitySensor.h" DFRobotGravitySensor dfRobotGravitySensor; +#else +NullSensor dfRobotGravitySensor; +#endif + +#if __has_include() +#include "Sensor/NAU7802Sensor.h" NAU7802Sensor nau7802Sensor; +#else +NullSensor nau7802Sensor; +#endif + +#if __has_include() +#include "Sensor/BMP3XXSensor.h" BMP3XXSensor bmp3xxSensor; +#else +NullSensor bmp3xxSensor; +#endif + +RCWL9620Sensor rcwl9620Sensor; CGRadSensSensor cgRadSens; #endif #ifdef T1000X_SENSOR_EN @@ -122,8 +218,10 @@ int32_t EnvironmentTelemetryModule::runOnce() result = dfRobotGravitySensor.runOnce(); if (bmp085Sensor.hasSensor()) result = bmp085Sensor.runOnce(); +#if __has_include() if (bmp280Sensor.hasSensor()) result = bmp280Sensor.runOnce(); +#endif if (bme280Sensor.hasSensor()) result = bme280Sensor.runOnce(); if (bmp3xxSensor.hasSensor()) @@ -407,10 +505,12 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && bmp085Sensor.getMetrics(m); hasSensor = true; } +#if __has_include() if (bmp280Sensor.hasSensor()) { valid = valid && bmp280Sensor.getMetrics(m); hasSensor = true; } +#endif if (bme280Sensor.hasSensor()) { valid = valid && bme280Sensor.getMetrics(m); hasSensor = true; diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 14901f0af..54ec90dae 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -53,7 +53,7 @@ int32_t PowerTelemetryModule::runOnce() firstTime = 0; uint32_t result = UINT32_MAX; -#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY if (moduleConfig.telemetry.power_measurement_enabled) { LOG_INFO("Power Telemetry: init"); // If sensor is already initialized by EnvironmentTelemetryModule, then we don't need to initialize it again, @@ -175,7 +175,7 @@ bool PowerTelemetryModule::getPowerTelemetry(meshtastic_Telemetry *m) m->which_variant = meshtastic_Telemetry_power_metrics_tag; m->variant.power_metrics = meshtastic_PowerMetrics_init_zero; -#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY if (ina219Sensor.hasSensor()) valid = ina219Sensor.getMetrics(m); if (ina226Sensor.hasSensor()) diff --git a/src/modules/Telemetry/Sensor/AHT10.cpp b/src/modules/Telemetry/Sensor/AHT10.cpp index 4d8c80200..096a131b9 100644 --- a/src/modules/Telemetry/Sensor/AHT10.cpp +++ b/src/modules/Telemetry/Sensor/AHT10.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "AHT10.h" diff --git a/src/modules/Telemetry/Sensor/AHT10.h b/src/modules/Telemetry/Sensor/AHT10.h index d9a133402..b2f0d8ae5 100644 --- a/src/modules/Telemetry/Sensor/AHT10.h +++ b/src/modules/Telemetry/Sensor/AHT10.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/BME280Sensor.cpp b/src/modules/Telemetry/Sensor/BME280Sensor.cpp index 65dab5105..d7b0a8a38 100644 --- a/src/modules/Telemetry/Sensor/BME280Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME280Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "BME280Sensor.h" diff --git a/src/modules/Telemetry/Sensor/BME280Sensor.h b/src/modules/Telemetry/Sensor/BME280Sensor.h index eb78f79f7..d1e21c8d5 100644 --- a/src/modules/Telemetry/Sensor/BME280Sensor.h +++ b/src/modules/Telemetry/Sensor/BME280Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 9237cf0c9..0e0212bc5 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "BME680Sensor.h" diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.h b/src/modules/Telemetry/Sensor/BME680Sensor.h index a5d2b5a48..249c4b3e7 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.h +++ b/src/modules/Telemetry/Sensor/BME680Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP085Sensor.cpp b/src/modules/Telemetry/Sensor/BMP085Sensor.cpp index 7f59f14f0..8087eb4b9 100644 --- a/src/modules/Telemetry/Sensor/BMP085Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BMP085Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "BMP085Sensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP085Sensor.h b/src/modules/Telemetry/Sensor/BMP085Sensor.h index 4ba8c5af1..8dadceab4 100644 --- a/src/modules/Telemetry/Sensor/BMP085Sensor.h +++ b/src/modules/Telemetry/Sensor/BMP085Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP280Sensor.cpp b/src/modules/Telemetry/Sensor/BMP280Sensor.cpp index 56a8bc080..47069b8e0 100644 --- a/src/modules/Telemetry/Sensor/BMP280Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BMP280Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "BMP280Sensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP280Sensor.h b/src/modules/Telemetry/Sensor/BMP280Sensor.h index da85fdc1d..d615411b2 100644 --- a/src/modules/Telemetry/Sensor/BMP280Sensor.h +++ b/src/modules/Telemetry/Sensor/BMP280Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP3XXSensor.cpp b/src/modules/Telemetry/Sensor/BMP3XXSensor.cpp index 69feaf3d9..28a71b48f 100644 --- a/src/modules/Telemetry/Sensor/BMP3XXSensor.cpp +++ b/src/modules/Telemetry/Sensor/BMP3XXSensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "BMP3XXSensor.h" diff --git a/src/modules/Telemetry/Sensor/BMP3XXSensor.h b/src/modules/Telemetry/Sensor/BMP3XXSensor.h index 79939c8d8..6ab0f533d 100644 --- a/src/modules/Telemetry/Sensor/BMP3XXSensor.h +++ b/src/modules/Telemetry/Sensor/BMP3XXSensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #ifndef _BMP3XX_SENSOR_H #define _BMP3XX_SENSOR_H diff --git a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp index c7fa29966..9581057b0 100644 --- a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp +++ b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "DFRobotGravitySensor.h" diff --git a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h index 8bd7335b5..dfd81a913 100644 --- a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h +++ b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h @@ -4,7 +4,7 @@ #define _MT_DFROBOTGRAVITYSENSOR_H #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.cpp b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.cpp index 1d143b03b..d962f1634 100644 --- a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.cpp +++ b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "DFRobotLarkSensor.h" diff --git a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h index 7a988e84a..7b67bc5b6 100644 --- a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h +++ b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h @@ -4,7 +4,7 @@ #define _MT_DFROBOTLARKSENSOR_H #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/DPS310Sensor.cpp b/src/modules/Telemetry/Sensor/DPS310Sensor.cpp index dc5dc4fdf..cc9b83af8 100644 --- a/src/modules/Telemetry/Sensor/DPS310Sensor.cpp +++ b/src/modules/Telemetry/Sensor/DPS310Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "DPS310Sensor.h" diff --git a/src/modules/Telemetry/Sensor/DPS310Sensor.h b/src/modules/Telemetry/Sensor/DPS310Sensor.h index 452975806..e9b4ece89 100644 --- a/src/modules/Telemetry/Sensor/DPS310Sensor.h +++ b/src/modules/Telemetry/Sensor/DPS310Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/INA219Sensor.cpp b/src/modules/Telemetry/Sensor/INA219Sensor.cpp index ea47e265d..d94afbc7c 100644 --- a/src/modules/Telemetry/Sensor/INA219Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA219Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "INA219Sensor.h" diff --git a/src/modules/Telemetry/Sensor/INA219Sensor.h b/src/modules/Telemetry/Sensor/INA219Sensor.h index 9b6a2fcca..908366ce6 100644 --- a/src/modules/Telemetry/Sensor/INA219Sensor.h +++ b/src/modules/Telemetry/Sensor/INA219Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "CurrentSensor.h" diff --git a/src/modules/Telemetry/Sensor/INA226Sensor.cpp b/src/modules/Telemetry/Sensor/INA226Sensor.cpp index 8b1cded60..4b313ba81 100644 --- a/src/modules/Telemetry/Sensor/INA226Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA226Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("INA226.h") #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "INA226.h" diff --git a/src/modules/Telemetry/Sensor/INA260Sensor.cpp b/src/modules/Telemetry/Sensor/INA260Sensor.cpp index 24182b336..9d9a99c00 100644 --- a/src/modules/Telemetry/Sensor/INA260Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA260Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "INA260Sensor.h" diff --git a/src/modules/Telemetry/Sensor/INA260Sensor.h b/src/modules/Telemetry/Sensor/INA260Sensor.h index f436b8f38..ea71c24e0 100644 --- a/src/modules/Telemetry/Sensor/INA260Sensor.h +++ b/src/modules/Telemetry/Sensor/INA260Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/INA3221Sensor.cpp b/src/modules/Telemetry/Sensor/INA3221Sensor.cpp index 7ac11dfde..78081132a 100644 --- a/src/modules/Telemetry/Sensor/INA3221Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA3221Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "INA3221Sensor.h" diff --git a/src/modules/Telemetry/Sensor/INA3221Sensor.h b/src/modules/Telemetry/Sensor/INA3221Sensor.h index 8eeda3e02..69edf8c50 100644 --- a/src/modules/Telemetry/Sensor/INA3221Sensor.h +++ b/src/modules/Telemetry/Sensor/INA3221Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "CurrentSensor.h" diff --git a/src/modules/Telemetry/Sensor/LPS22HBSensor.cpp b/src/modules/Telemetry/Sensor/LPS22HBSensor.cpp index 170fafd39..cf0fbe4a9 100644 --- a/src/modules/Telemetry/Sensor/LPS22HBSensor.cpp +++ b/src/modules/Telemetry/Sensor/LPS22HBSensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "LPS22HBSensor.h" diff --git a/src/modules/Telemetry/Sensor/LPS22HBSensor.h b/src/modules/Telemetry/Sensor/LPS22HBSensor.h index 955f2a1e5..24d75e903 100644 --- a/src/modules/Telemetry/Sensor/LPS22HBSensor.h +++ b/src/modules/Telemetry/Sensor/LPS22HBSensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/MAX17048Sensor.cpp b/src/modules/Telemetry/Sensor/MAX17048Sensor.cpp index 3aacf9cd7..6ab96aa57 100644 --- a/src/modules/Telemetry/Sensor/MAX17048Sensor.cpp +++ b/src/modules/Telemetry/Sensor/MAX17048Sensor.cpp @@ -1,6 +1,6 @@ #include "MAX17048Sensor.h" -#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL) && __has_include() MAX17048Singleton *MAX17048Singleton::GetInstance() { diff --git a/src/modules/Telemetry/Sensor/MAX17048Sensor.h b/src/modules/Telemetry/Sensor/MAX17048Sensor.h index bd109cbb1..6f61421dc 100644 --- a/src/modules/Telemetry/Sensor/MAX17048Sensor.h +++ b/src/modules/Telemetry/Sensor/MAX17048Sensor.h @@ -5,7 +5,7 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL) && __has_include() // Samples to store in a buffer to determine if the battery is charging or discharging #define MAX17048_CHARGING_SAMPLES 3 diff --git a/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp b/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp index f99956925..ceca4be5e 100644 --- a/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp +++ b/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO) +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "MAX30102Sensor.h" diff --git a/src/modules/Telemetry/Sensor/MAX30102Sensor.h b/src/modules/Telemetry/Sensor/MAX30102Sensor.h index 026e30ed0..9981d4006 100644 --- a/src/modules/Telemetry/Sensor/MAX30102Sensor.h +++ b/src/modules/Telemetry/Sensor/MAX30102Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO) +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/MCP9808Sensor.cpp b/src/modules/Telemetry/Sensor/MCP9808Sensor.cpp index 58ce29cd2..906634c40 100644 --- a/src/modules/Telemetry/Sensor/MCP9808Sensor.cpp +++ b/src/modules/Telemetry/Sensor/MCP9808Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "MCP9808Sensor.h" diff --git a/src/modules/Telemetry/Sensor/MCP9808Sensor.h b/src/modules/Telemetry/Sensor/MCP9808Sensor.h index 05bdabf3f..705a71700 100644 --- a/src/modules/Telemetry/Sensor/MCP9808Sensor.h +++ b/src/modules/Telemetry/Sensor/MCP9808Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/MLX90614Sensor.cpp b/src/modules/Telemetry/Sensor/MLX90614Sensor.cpp index d9908fce3..9661b59c2 100644 --- a/src/modules/Telemetry/Sensor/MLX90614Sensor.cpp +++ b/src/modules/Telemetry/Sensor/MLX90614Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "MLX90614Sensor.h" diff --git a/src/modules/Telemetry/Sensor/MLX90614Sensor.h b/src/modules/Telemetry/Sensor/MLX90614Sensor.h index 00f63449e..c2571027e 100644 --- a/src/modules/Telemetry/Sensor/MLX90614Sensor.h +++ b/src/modules/Telemetry/Sensor/MLX90614Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" #include diff --git a/src/modules/Telemetry/Sensor/MLX90632Sensor.cpp b/src/modules/Telemetry/Sensor/MLX90632Sensor.cpp index b7bd6ae61..dfc049023 100644 --- a/src/modules/Telemetry/Sensor/MLX90632Sensor.cpp +++ b/src/modules/Telemetry/Sensor/MLX90632Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "MLX90632Sensor.h" diff --git a/src/modules/Telemetry/Sensor/MLX90632Sensor.h b/src/modules/Telemetry/Sensor/MLX90632Sensor.h index 7b36c44cd..ef7be180a 100644 --- a/src/modules/Telemetry/Sensor/MLX90632Sensor.h +++ b/src/modules/Telemetry/Sensor/MLX90632Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp b/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp index 1329c8d90..ef1756b36 100644 --- a/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp +++ b/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "FSCommon.h" diff --git a/src/modules/Telemetry/Sensor/NAU7802Sensor.h b/src/modules/Telemetry/Sensor/NAU7802Sensor.h index c53a3b31a..cb9e64829 100644 --- a/src/modules/Telemetry/Sensor/NAU7802Sensor.h +++ b/src/modules/Telemetry/Sensor/NAU7802Sensor.h @@ -1,7 +1,7 @@ #include "MeshModule.h" #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/OPT3001Sensor.cpp b/src/modules/Telemetry/Sensor/OPT3001Sensor.cpp index 75c6cd41a..1f0407374 100644 --- a/src/modules/Telemetry/Sensor/OPT3001Sensor.cpp +++ b/src/modules/Telemetry/Sensor/OPT3001Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "OPT3001Sensor.h" diff --git a/src/modules/Telemetry/Sensor/OPT3001Sensor.h b/src/modules/Telemetry/Sensor/OPT3001Sensor.h index 2ac149319..a9da2d705 100644 --- a/src/modules/Telemetry/Sensor/OPT3001Sensor.h +++ b/src/modules/Telemetry/Sensor/OPT3001Sensor.h @@ -1,7 +1,7 @@ #pragma once #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp b/src/modules/Telemetry/Sensor/SHT31Sensor.cpp index b96b94fa8..8619a7905 100644 --- a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp +++ b/src/modules/Telemetry/Sensor/SHT31Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "SHT31Sensor.h" diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.h b/src/modules/Telemetry/Sensor/SHT31Sensor.h index 560b22436..c3d81af95 100644 --- a/src/modules/Telemetry/Sensor/SHT31Sensor.h +++ b/src/modules/Telemetry/Sensor/SHT31Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp b/src/modules/Telemetry/Sensor/SHT4XSensor.cpp index 0fa6021dc..83fdaf6c6 100644 --- a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp +++ b/src/modules/Telemetry/Sensor/SHT4XSensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "SHT4XSensor.h" diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.h b/src/modules/Telemetry/Sensor/SHT4XSensor.h index 62a5cefeb..da608cb82 100644 --- a/src/modules/Telemetry/Sensor/SHT4XSensor.h +++ b/src/modules/Telemetry/Sensor/SHT4XSensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp index 3a7cc48d2..dbebec9d3 100644 --- a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp +++ b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "SHTC3Sensor.h" diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.h b/src/modules/Telemetry/Sensor/SHTC3Sensor.h index 7a760292f..458af6465 100644 --- a/src/modules/Telemetry/Sensor/SHTC3Sensor.h +++ b/src/modules/Telemetry/Sensor/SHTC3Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp index add475d5b..beec3c70b 100644 --- a/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp +++ b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TSL2591Sensor.h" diff --git a/src/modules/Telemetry/Sensor/TSL2591Sensor.h b/src/modules/Telemetry/Sensor/TSL2591Sensor.h index 27bebdfe5..edf7698b1 100644 --- a/src/modules/Telemetry/Sensor/TSL2591Sensor.h +++ b/src/modules/Telemetry/Sensor/TSL2591Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/TelemetrySensor.h b/src/modules/Telemetry/Sensor/TelemetrySensor.h index 08cc1125d..83d7b38b0 100644 --- a/src/modules/Telemetry/Sensor/TelemetrySensor.h +++ b/src/modules/Telemetry/Sensor/TelemetrySensor.h @@ -8,7 +8,9 @@ #include "NodeDB.h" #include +#if !ARCH_PORTDUINO class TwoWire; +#endif #define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 extern std::pair nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1]; @@ -40,7 +42,7 @@ class TelemetrySensor initialized = true; return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - virtual void setup(); + virtual void setup() = 0; public: virtual AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, diff --git a/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp b/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp index 496b49aeb..b075bf405 100644 --- a/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp +++ b/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/VEML7700Sensor.h b/src/modules/Telemetry/Sensor/VEML7700Sensor.h index 97e57334c..f40384ad3 100644 --- a/src/modules/Telemetry/Sensor/VEML7700Sensor.h +++ b/src/modules/Telemetry/Sensor/VEML7700Sensor.h @@ -1,6 +1,6 @@ #include "configuration.h" -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" diff --git a/src/modules/Telemetry/Sensor/nullSensor.cpp b/src/modules/Telemetry/Sensor/nullSensor.cpp new file mode 100644 index 000000000..9522c7fcc --- /dev/null +++ b/src/modules/Telemetry/Sensor/nullSensor.cpp @@ -0,0 +1,23 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include "nullSensor.h" +#include + +NullSensor::NullSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "nullSensor") {} + +int32_t NullSensor::runOnce() +{ + return 0; +} + +void NullSensor::setup() {} + +bool NullSensor::getMetrics(meshtastic_Telemetry *measurement) +{ + return false; +} +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/nullSensor.h b/src/modules/Telemetry/Sensor/nullSensor.h new file mode 100644 index 000000000..94dbcc7f8 --- /dev/null +++ b/src/modules/Telemetry/Sensor/nullSensor.h @@ -0,0 +1,22 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#pragma once + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" + +class NullSensor : public TelemetrySensor +{ + + protected: + virtual void setup() override; + + public: + NullSensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + int32_t runTrigger() { return 0; } +}; + +#endif \ No newline at end of file diff --git a/src/motion/BMA423Sensor.cpp b/src/motion/BMA423Sensor.cpp index d7058bab0..7951a236e 100755 --- a/src/motion/BMA423Sensor.cpp +++ b/src/motion/BMA423Sensor.cpp @@ -1,6 +1,6 @@ #include "BMA423Sensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) && __has_include() using namespace MotionSensorI2C; diff --git a/src/motion/BMA423Sensor.h b/src/motion/BMA423Sensor.h index 455315aa9..b9d7b4aa0 100755 --- a/src/motion/BMA423Sensor.h +++ b/src/motion/BMA423Sensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) && __has_include() #include #include diff --git a/src/motion/BMX160Sensor.cpp b/src/motion/BMX160Sensor.cpp index 3ddbe46ea..39bc04ea1 100755 --- a/src/motion/BMX160Sensor.cpp +++ b/src/motion/BMX160Sensor.cpp @@ -1,10 +1,10 @@ #include "BMX160Sensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C BMX160Sensor::BMX160Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} -#if defined(RAK_4631) && !defined(RAK2560) +#if defined(RAK_4631) && !defined(RAK2560) && __has_include() #if !defined(MESHTASTIC_EXCLUDE_SCREEN) // screen is defined in main.cpp diff --git a/src/motion/BMX160Sensor.h b/src/motion/BMX160Sensor.h index fc5a48aa4..d0efa5ae6 100755 --- a/src/motion/BMX160Sensor.h +++ b/src/motion/BMX160Sensor.h @@ -5,9 +5,9 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C -#if defined(RAK_4631) && !defined(RAK2560) +#if defined(RAK_4631) && !defined(RAK2560) && __has_include() #include "Fusion/Fusion.h" #include diff --git a/src/motion/ICM20948Sensor.cpp b/src/motion/ICM20948Sensor.cpp index 338a4fc5f..946390ddb 100755 --- a/src/motion/ICM20948Sensor.cpp +++ b/src/motion/ICM20948Sensor.cpp @@ -1,6 +1,6 @@ #include "ICM20948Sensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() // Flag when an interrupt has been detected volatile static bool ICM20948_IRQ = false; diff --git a/src/motion/ICM20948Sensor.h b/src/motion/ICM20948Sensor.h index d5e246c8d..8344b0703 100755 --- a/src/motion/ICM20948Sensor.h +++ b/src/motion/ICM20948Sensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() #include diff --git a/src/motion/LIS3DHSensor.cpp b/src/motion/LIS3DHSensor.cpp index 995f74abe..903cc92f7 100755 --- a/src/motion/LIS3DHSensor.cpp +++ b/src/motion/LIS3DHSensor.cpp @@ -1,7 +1,7 @@ #include "LIS3DHSensor.h" #include "NodeDB.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() LIS3DHSensor::LIS3DHSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} diff --git a/src/motion/LIS3DHSensor.h b/src/motion/LIS3DHSensor.h index 603d195a8..924b193e2 100755 --- a/src/motion/LIS3DHSensor.h +++ b/src/motion/LIS3DHSensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() #include diff --git a/src/motion/LSM6DS3Sensor.cpp b/src/motion/LSM6DS3Sensor.cpp index 2dcb4d663..7e2d7dfcd 100755 --- a/src/motion/LSM6DS3Sensor.cpp +++ b/src/motion/LSM6DS3Sensor.cpp @@ -1,7 +1,7 @@ #include "LSM6DS3Sensor.h" #include "NodeDB.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() LSM6DS3Sensor::LSM6DS3Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} diff --git a/src/motion/LSM6DS3Sensor.h b/src/motion/LSM6DS3Sensor.h index 77069ef3c..8bf885149 100755 --- a/src/motion/LSM6DS3Sensor.h +++ b/src/motion/LSM6DS3Sensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() #ifndef LSM6DS3_WAKE_THRESH #define LSM6DS3_WAKE_THRESH 20 diff --git a/src/motion/MPU6050Sensor.cpp b/src/motion/MPU6050Sensor.cpp index c3f2d0b7c..5d4f7bfdb 100755 --- a/src/motion/MPU6050Sensor.cpp +++ b/src/motion/MPU6050Sensor.cpp @@ -1,6 +1,6 @@ #include "MPU6050Sensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() MPU6050Sensor::MPU6050Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} diff --git a/src/motion/MPU6050Sensor.h b/src/motion/MPU6050Sensor.h index 2e6eafecd..2bca72b34 100755 --- a/src/motion/MPU6050Sensor.h +++ b/src/motion/MPU6050Sensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() #include diff --git a/src/motion/MotionSensor.cpp b/src/motion/MotionSensor.cpp index d87380085..54a2f883a 100755 --- a/src/motion/MotionSensor.cpp +++ b/src/motion/MotionSensor.cpp @@ -1,6 +1,6 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C char timeRemainingBuffer[12]; diff --git a/src/motion/MotionSensor.h b/src/motion/MotionSensor.h index 1f4d093bf..90080577f 100755 --- a/src/motion/MotionSensor.h +++ b/src/motion/MotionSensor.h @@ -7,7 +7,7 @@ #include "../configuration.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C #include "../PowerFSM.h" #include "../detect/ScanI2C.h" diff --git a/src/motion/QMA6100PSensor.cpp b/src/motion/QMA6100PSensor.cpp index eb81e16c7..a04837e80 100644 --- a/src/motion/QMA6100PSensor.cpp +++ b/src/motion/QMA6100PSensor.cpp @@ -1,6 +1,6 @@ #include "QMA6100PSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P) // Flag when an interrupt has been detected volatile static bool QMA6100P_IRQ = false; diff --git a/src/motion/QMA6100PSensor.h b/src/motion/QMA6100PSensor.h index 7ba00149c..72e716ef9 100644 --- a/src/motion/QMA6100PSensor.h +++ b/src/motion/QMA6100PSensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P) #include diff --git a/src/motion/STK8XXXSensor.cpp b/src/motion/STK8XXXSensor.cpp index 377ee3c37..d27a1e88d 100755 --- a/src/motion/STK8XXXSensor.cpp +++ b/src/motion/STK8XXXSensor.cpp @@ -1,6 +1,6 @@ #include "STK8XXXSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX) STK8XXXSensor::STK8XXXSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} diff --git a/src/motion/STK8XXXSensor.h b/src/motion/STK8XXXSensor.h index cff98d87d..f54bc7707 100755 --- a/src/motion/STK8XXXSensor.h +++ b/src/motion/STK8XXXSensor.h @@ -4,7 +4,7 @@ #include "MotionSensor.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX) +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX) #ifdef STK8XXX_INT diff --git a/src/platform/portduino/architecture.h b/src/platform/portduino/architecture.h index 3dde87199..a5e263d5a 100644 --- a/src/platform/portduino/architecture.h +++ b/src/platform/portduino/architecture.h @@ -19,4 +19,7 @@ #endif #ifndef HAS_TELEMETRY #define HAS_TELEMETRY 1 +#endif +#ifndef HAS_SENSOR +#define HAS_SENSOR 1 #endif \ No newline at end of file diff --git a/src/power.h b/src/power.h index a21f7d164..d7fa7f8a9 100644 --- a/src/power.h +++ b/src/power.h @@ -45,23 +45,48 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b; #include "soc/sens_reg.h" // needed for adc pin reset #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +#include "modules/Telemetry/Sensor/nullSensor.h" +#if __has_include() #include "modules/Telemetry/Sensor/INA219Sensor.h" -#include "modules/Telemetry/Sensor/INA226Sensor.h" -#include "modules/Telemetry/Sensor/INA260Sensor.h" -#include "modules/Telemetry/Sensor/INA3221Sensor.h" extern INA219Sensor ina219Sensor; +#else +extern NullSensor ina219Sensor; +#endif + +#if __has_include() +#include "modules/Telemetry/Sensor/INA226Sensor.h" extern INA226Sensor ina226Sensor; +#else +extern NullSensor ina226Sensor; +#endif + +#if __has_include() +#include "modules/Telemetry/Sensor/INA260Sensor.h" extern INA260Sensor ina260Sensor; +#else +extern NullSensor ina260Sensor; +#endif + +#if __has_include() +#include "modules/Telemetry/Sensor/INA3221Sensor.h" extern INA3221Sensor ina3221Sensor; +#else +extern NullSensor ina3221Sensor; #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#endif + +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) #include "modules/Telemetry/Sensor/MAX17048Sensor.h" +#if __has_include() extern MAX17048Sensor max17048Sensor; +#else +extern NullSensor max17048Sensor; +#endif #endif -#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO) +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT #include "modules/Telemetry/Sensor/RAK9154Sensor.h" extern RAK9154Sensor rak9154Sensor; #endif From b4e8f7dbb656518aa277869358f56201dc8eb14e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 20:32:19 -0500 Subject: [PATCH 109/238] Update Adafruit BusIO digest to 159f86a (#6681) 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 fb121aafe..0c2524b25 100644 --- a/platformio.ini +++ b/platformio.ini @@ -114,7 +114,7 @@ lib_deps = [environmental_base] lib_deps = # renovate: datasource=git-refs depName=Adafruit BusIO packageName=https://github.com/adafruit/Adafruit_BusIO gitBranch=master - https://github.com/adafruit/Adafruit_BusIO/archive/5e8f137415f473e390c9410421bb54d828898fad.zip + https://github.com/adafruit/Adafruit_BusIO/archive/159f86a3bd64485227f63ef2f60abe35877051d0.zip # renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor adafruit/Adafruit Unified Sensor@1.1.15 # renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library From 72eae42b81722771fdae885b5d9817274e80af96 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 29 Apr 2025 04:31:01 -0700 Subject: [PATCH 110/238] PMSA003I: add support for driving SET pin low while not actively taking a telemetry reading (#6569) * support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading * add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp * fix typos, use arduino gpio defines instead of magic numbers * support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading * add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp * fix typos, use arduino gpio defines instead of magic numbers * RAK4631: add PMSA003I_ENABLE_PIN define * fix indentation --------- Co-authored-by: Ben Meadors --- src/modules/Telemetry/AirQualityTelemetry.cpp | 64 +++++++++++++++---- src/modules/Telemetry/AirQualityTelemetry.h | 14 ++++ variants/rak4631/variant.h | 6 ++ 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/modules/Telemetry/AirQualityTelemetry.cpp b/src/modules/Telemetry/AirQualityTelemetry.cpp index 1ddb9ca9b..fafb28699 100644 --- a/src/modules/Telemetry/AirQualityTelemetry.cpp +++ b/src/modules/Telemetry/AirQualityTelemetry.cpp @@ -14,6 +14,13 @@ #include "main.h" #include +#ifndef PMSA003I_WARMUP_MS +// from the PMSA003I datasheet: +// "Stable data should be got at least 30 seconds after the sensor wakeup +// from the sleep mode because of the fan’s performance." +#define PMSA003I_WARMUP_MS 30000 +#endif + int32_t AirQualityTelemetryModule::runOnce() { /* @@ -34,6 +41,13 @@ int32_t AirQualityTelemetryModule::runOnce() if (moduleConfig.telemetry.air_quality_enabled) { LOG_INFO("Air quality Telemetry: init"); + +#ifdef PMSA003I_ENABLE_PIN + // put the sensor to sleep on startup + pinMode(PMSA003I_ENABLE_PIN, OUTPUT); + digitalWrite(PMSA003I_ENABLE_PIN, LOW); +#endif /* PMSA003I_ENABLE_PIN */ + if (!aqi.begin_I2C()) { #ifndef I2C_NO_RESCAN LOG_WARN("Could not establish i2c connection to AQI sensor. Rescan"); @@ -63,21 +77,45 @@ int32_t AirQualityTelemetryModule::runOnce() if (!moduleConfig.telemetry.air_quality_enabled) return disable(); - if (((lastSentToMesh == 0) || - !Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled( - moduleConfig.telemetry.air_quality_interval, - default_telemetry_broadcast_interval_secs, numOnlineNodes))) && - airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) && - airTime->isTxAllowedAirUtil()) { - sendTelemetry(); - lastSentToMesh = millis(); - } 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) - sendTelemetry(NODENUM_BROADCAST, true); + switch (state) { +#ifdef PMSA003I_ENABLE_PIN + case State::IDLE: + // sensor is in standby; fire it up and sleep + LOG_DEBUG("runOnce(): state = idle"); + digitalWrite(PMSA003I_ENABLE_PIN, HIGH); + state = State::ACTIVE; + + return PMSA003I_WARMUP_MS; +#endif /* PMSA003I_ENABLE_PIN */ + case State::ACTIVE: + // sensor is already warmed up; grab telemetry and send it + LOG_DEBUG("runOnce(): state = active"); + + if (((lastSentToMesh == 0) || + !Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled( + moduleConfig.telemetry.air_quality_interval, + default_telemetry_broadcast_interval_secs, numOnlineNodes))) && + airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) && + airTime->isTxAllowedAirUtil()) { + sendTelemetry(); + lastSentToMesh = millis(); + } 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) + sendTelemetry(NODENUM_BROADCAST, true); + } + +#ifdef PMSA003I_ENABLE_PIN + // put sensor back to sleep + digitalWrite(PMSA003I_ENABLE_PIN, LOW); + state = State::IDLE; +#endif /* PMSA003I_ENABLE_PIN */ + + return sendToPhoneIntervalMs; + default: + return disable(); } } - return sendToPhoneIntervalMs; } bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) diff --git a/src/modules/Telemetry/AirQualityTelemetry.h b/src/modules/Telemetry/AirQualityTelemetry.h index 4e82efac3..0142ee686 100644 --- a/src/modules/Telemetry/AirQualityTelemetry.h +++ b/src/modules/Telemetry/AirQualityTelemetry.h @@ -23,6 +23,14 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf setIntervalFromNow(10 * 1000); aqi = Adafruit_PM25AQI(); nodeStatusObserver.observe(&nodeStatus->onNewStatus); + +#ifdef PMSA003I_ENABLE_PIN + // the PMSA003I sensor uses about 300mW on its own; support powering it off when it's not actively taking + // a reading + state = State::IDLE; +#else + state = State::ACTIVE; +#endif } protected: @@ -42,6 +50,12 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); private: + enum State { + IDLE = 0, + ACTIVE = 1, + }; + + State state; Adafruit_PM25AQI aqi; PM25_AQI_Data data = {0}; bool firstTime = true; diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index bc5541336..0da1c04ea 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -197,6 +197,12 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG */ +// configure the SET pin on the RAK12039 sensor board to disable the sensor while not reading +// air quality telemetry. PIN_NFC2 doesn't seem to be used anywhere else in the codebase, but if +// you're having problems with your node behaving weirdly when a RAK12039 board isn't connected, +// try disabling this. +#define PMSA003I_ENABLE_PIN PIN_NFC2 + #define DETECTION_SENSOR_EN 4 #define USE_SX1262 From 635de2d2296d463fb61fe5a650bd06b94a6559ee Mon Sep 17 00:00:00 2001 From: Jorropo Date: Tue, 29 Apr 2025 13:31:53 +0200 Subject: [PATCH 111/238] udp-multicast: bump platform-native to fix UDP read of unitialized memory bug (#6686) * udp-multicast: bump platform-native to fix UDP read of unitialized memory bug Fixes: #6683 * Update portduino.ini --------- Co-authored-by: Ben Meadors --- arch/portduino/portduino.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 5dc0daf6b..890169c28 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/46f509b96ddce22d1bf38efc93319dfb3e4f5acf.zip + https://github.com/meshtastic/platform-native/archive/e19f77e034590669feaaf26214667b76d0821d06.zip framework = arduino build_src_filter = @@ -48,4 +48,4 @@ build_flags = -std=gnu17 -std=c++17 -lib_ignore = Adafruit NeoPixel \ No newline at end of file +lib_ignore = Adafruit NeoPixel From 216fbf23434a60d200e2519c002ed1d010febdea Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 29 Apr 2025 19:24:00 -0400 Subject: [PATCH 112/238] Update 'Adafruit BusIO' to 1.17.1 (#6694) --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0c2524b25..527140835 100644 --- a/platformio.ini +++ b/platformio.ini @@ -113,8 +113,8 @@ lib_deps = ; Common libs for environmental measurements in telemetry module [environmental_base] lib_deps = - # renovate: datasource=git-refs depName=Adafruit BusIO packageName=https://github.com/adafruit/Adafruit_BusIO gitBranch=master - https://github.com/adafruit/Adafruit_BusIO/archive/159f86a3bd64485227f63ef2f60abe35877051d0.zip + # renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO + adafruit/Adafruit BusIO@1.17.1 # renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor adafruit/Adafruit Unified Sensor@1.1.15 # renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library From a7ef9e9c084e8301c0e42ec7e7b1877848997e2c Mon Sep 17 00:00:00 2001 From: Jorropo Date: Wed, 30 Apr 2025 12:52:42 +0200 Subject: [PATCH 113/238] udp-multicast: remove the thread from the multicast thread API (#6685) * udp-multicast: remove the thread from the multicast thread API The whole API is parallel & asynchronous we don't need to start a thread ourself, the implementation probably does when we call start listening already. * Take copilot advice and call it a handler --------- Co-authored-by: Ben Meadors --- src/main.cpp | 8 ++++---- src/main.h | 4 ++-- src/mesh/Router.cpp | 4 ++-- .../{UdpMulticastThread.h => UdpMulticastHandler.h} | 13 ++----------- src/mesh/wifi/WiFiAPClient.cpp | 4 ++-- 5 files changed, 12 insertions(+), 21 deletions(-) rename src/mesh/udp/{UdpMulticastThread.h => UdpMulticastHandler.h} (85%) diff --git a/src/main.cpp b/src/main.cpp index eb93a70d1..9ef944e65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -124,8 +124,8 @@ extern void tftSetup(void); #endif #ifdef HAS_UDP_MULTICAST -#include "mesh/udp/UdpMulticastThread.h" -UdpMulticastThread *udpThread = nullptr; +#include "mesh/udp/UdpMulticastHandler.h" +UdpMulticastHandler *udpHandler = nullptr; #endif #if defined(TCXO_OPTIONAL) @@ -918,12 +918,12 @@ void setup() #ifdef HAS_UDP_MULTICAST LOG_DEBUG("Start multicast thread"); - udpThread = new UdpMulticastThread(); + udpHandler = new UdpMulticastHandler(); #ifdef ARCH_PORTDUINO // FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call // onNetworkConnected there if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { - udpThread->start(); + udpHandler->start(); } #endif #endif diff --git a/src/main.h b/src/main.h index 3b71cfeea..c3807cfd5 100644 --- a/src/main.h +++ b/src/main.h @@ -51,8 +51,8 @@ extern AudioThread *audioThread; #endif #ifdef HAS_UDP_MULTICAST -#include "mesh/udp/UdpMulticastThread.h" -extern UdpMulticastThread *udpThread; +#include "mesh/udp/UdpMulticastHandler.h" +extern UdpMulticastHandler *udpHandler; #endif // Global Screen singleton. diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 2cc3007a2..fef29388e 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -293,8 +293,8 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) } #if HAS_UDP_MULTICAST - if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { - udpThread->onSend(const_cast(p)); + if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { + udpHandler->onSend(const_cast(p)); } #endif diff --git a/src/mesh/udp/UdpMulticastThread.h b/src/mesh/udp/UdpMulticastHandler.h similarity index 85% rename from src/mesh/udp/UdpMulticastThread.h rename to src/mesh/udp/UdpMulticastHandler.h index 88824dc4d..39bd61021 100644 --- a/src/mesh/udp/UdpMulticastThread.h +++ b/src/mesh/udp/UdpMulticastHandler.h @@ -13,12 +13,11 @@ #endif // HAS_ETHERNET #define UDP_MULTICAST_DEFAUL_PORT 4403 // Default port for UDP multicast is same as TCP api server -#define UDP_MULTICAST_THREAD_INTERVAL_MS 15000 -class UdpMulticastThread : public concurrency::OSThread +class UdpMulticastHandler final { public: - UdpMulticastThread() : OSThread("UdpMulticast") { udpIpAddress = IPAddress(224, 0, 0, 69); } + UdpMulticastHandler() { udpIpAddress = IPAddress(224, 0, 0, 69); } void start() { @@ -71,14 +70,6 @@ class UdpMulticastThread : public concurrency::OSThread return true; } - protected: - int32_t runOnce() override - { - canSleep = true; - // TODO: Implement nodeinfo broadcast - return UDP_MULTICAST_THREAD_INTERVAL_MS; - } - private: IPAddress udpIpAddress; AsyncUDP udp; diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 4d0b74f7c..789f8ac44 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -133,8 +133,8 @@ static void onNetworkConnected() } #if HAS_UDP_MULTICAST - if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { - udpThread->start(); + if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) { + udpHandler->start(); } #endif } From e0b1fdb5e8131010d598f7b74a8058e64f8c3959 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 30 Apr 2025 06:08:10 -0500 Subject: [PATCH 114/238] Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5 (#6699) * Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5. * Update src/mesh/PhoneAPI.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Doot --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mesh/Default.h | 1 + src/mesh/PhoneAPI.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mesh/Default.h b/src/mesh/Default.h index d39886d1c..0daccbb6f 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -6,6 +6,7 @@ #define ONE_MINUTE_MS 60 * 1000 #define THIRTY_SECONDS_MS 30 * 1000 #define FIVE_SECONDS_MS 5 * 1000 +#define TEN_SECONDS_MS 10 * 1000 #define min_default_telemetry_interval_secs 30 * 60 #define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 204886be5..0e18b8ab1 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -649,8 +649,10 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p) meshtastic_QueueStatus qs = router->getQueueStatus(); service->sendQueueStatusToPhone(qs, 0, p.id); return false; - } else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] && - Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) { + } else if (IS_ONE_OF(meshtastic_PortNum_POSITION_APP, meshtastic_PortNum_WAYPOINT_APP, meshtastic_PortNum_ALERT_APP) && + lastPortNumToRadio[p.decoded.portnum] && + Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], TEN_SECONDS_MS)) { + // TODO: [Issue #6700] Make this rate limit throttling scale up / down with the preset LOG_WARN("Rate limit portnum %d", p.decoded.portnum); meshtastic_QueueStatus qs = router->getQueueStatus(); service->sendQueueStatusToPhone(qs, 0, p.id); From 845088e45b573496a2e58475c7141999d8b7962b Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 30 Apr 2025 06:17:24 -0500 Subject: [PATCH 115/238] Add 100 msecond delay in tft_task_handler when deviceScreen is null (#6695) * Add 100 msecond delay in tft_task_handler when deviceScreen is null, to fix 100% usage bug * move portduino tft task creation into tftSetup * remove superfluous check * update platform-native commit --------- Co-authored-by: mverch67 --- arch/portduino/portduino.ini | 2 +- src/graphics/tftSetup.cpp | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 890169c28..6af3a7717 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/e19f77e034590669feaaf26214667b76d0821d06.zip + https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip framework = arduino build_src_filter = diff --git a/src/graphics/tftSetup.cpp b/src/graphics/tftSetup.cpp index cacb02694..a8d51bb82 100644 --- a/src/graphics/tftSetup.cpp +++ b/src/graphics/tftSetup.cpp @@ -11,6 +11,7 @@ #ifdef ARCH_PORTDUINO #include "PortduinoGlue.h" +#include #endif DeviceScreen *deviceScreen = nullptr; @@ -26,12 +27,10 @@ CallbackObserver endSleepObserver = void tft_task_handler(void *param = nullptr) { while (true) { - if (deviceScreen) { - spiLock->lock(); - deviceScreen->task_handler(); - spiLock->unlock(); - deviceScreen->sleep(); - } + spiLock->lock(); + deviceScreen->task_handler(); + spiLock->unlock(); + deviceScreen->sleep(); } } @@ -116,11 +115,15 @@ void tftSetup(void) } #endif + if (deviceScreen) { #ifdef ARCH_ESP32 - tftSleepObserver.observe(¬ifyLightSleep); - endSleepObserver.observe(¬ifyLightSleepEnd); - xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0); + tftSleepObserver.observe(¬ifyLightSleep); + endSleepObserver.observe(¬ifyLightSleepEnd); + xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0); +#elif defined(ARCH_PORTDUINO) + std::thread *tft_task = new std::thread([] { tft_task_handler(); }); #endif + } } #endif \ No newline at end of file From 00e2ac33ad082ae27353aece92c40265ecc58424 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 06:24:47 -0500 Subject: [PATCH 116/238] Update platform-native digest to e19f77e (#6701) 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 6af3a7717..890169c28 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/622341c6de8a239704318b10c3dbb00c21a3eab3.zip + https://github.com/meshtastic/platform-native/archive/e19f77e034590669feaaf26214667b76d0821d06.zip framework = arduino build_src_filter = From 124f4daa71a3cf088a9ccc24d44be5ec8a82cb5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:14:38 +0200 Subject: [PATCH 117/238] Update meshtastic-device-ui digest to 33aa689 (#6705) 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 527140835..73a9bbe1f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/8113d4ff5a63280834acfeb7584f179cdc6376b6.zip + https://github.com/meshtastic/device-ui/archive/33aa6890f7862d81c2bc1658f43eeea7a8081c6e.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From f9fbc3ff862f479fef29628771109a52d3f6601a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 15:55:13 -0500 Subject: [PATCH 118/238] Update platform-native digest to 622341c (#6702) 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 890169c28..6af3a7717 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/e19f77e034590669feaaf26214667b76d0821d06.zip + https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip framework = arduino build_src_filter = From 5c005aaed5910f56d6e47aa6c35e2ba86653d049 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Thu, 1 May 2025 12:28:05 +1200 Subject: [PATCH 119/238] Restore InkHUD to defaults on factory reset (#6637) * Erase InkHUD settings on factory reset * Documentation * Captialn't Lower case m. Also move the include statement to .cpp, because it doesn't really need to be in the .h --- src/graphics/Screen.cpp | 3 --- src/graphics/niche/FlashData.h | 23 ++++++++++++++++++ src/graphics/niche/InkHUD/Events.cpp | 31 ++++++++++++++++++++++-- src/graphics/niche/InkHUD/Events.h | 8 ++++++ src/graphics/niche/InkHUD/docs/README.md | 4 +++ src/modules/AdminModule.cpp | 4 ++- 6 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index ad0b94efe..1ee0c0fdd 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -2840,9 +2840,6 @@ int Screen::handleInputEvent(const InputEvent *event) int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg) { - // Note: only selected admin messages notify this observer - // If you wish to handle a new type of message, you should modify AdminModule.cpp first - switch (arg->which_payload_variant) { // Node removed manually (i.e. via app) case meshtastic_AdminMessage_remove_by_nodenum_tag: diff --git a/src/graphics/niche/FlashData.h b/src/graphics/niche/FlashData.h index 8a63c6108..a27c4aea0 100644 --- a/src/graphics/niche/FlashData.h +++ b/src/graphics/niche/FlashData.h @@ -135,6 +135,29 @@ template class FlashData } }; +// Erase contents of the NicheGraphics data directory +inline void clearFlashData() +{ + +#ifdef FSCom + File dir = FSCom.open("/NicheGraphics"); // Open the directory + File file = dir.openNextFile(); // Attempt to open the first file in the directory + + // While the directory still contains files + while (file) { + std::string path = "/NicheGraphics/"; + path += file.name(); + LOG_DEBUG("Erasing %s", path.c_str()); + file.close(); + FSCom.remove(path.c_str()); + + file = dir.openNextFile(); + } +#else + LOG_ERROR("ERROR: Filesystem not implemented\n"); +#endif +} + } // namespace NicheGraphics #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/Events.cpp b/src/graphics/niche/InkHUD/Events.cpp index ddd01b7e1..d0bd35250 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -3,11 +3,13 @@ #include "./Events.h" #include "RTC.h" +#include "modules/AdminModule.h" #include "modules/TextMessageModule.h" #include "sleep.h" #include "./Applet.h" #include "./SystemApplet.h" +#include "graphics/niche/FlashData.h" using namespace NicheGraphics; @@ -25,6 +27,9 @@ void InkHUD::Events::begin() deepSleepObserver.observe(¬ifyDeepSleep); rebootObserver.observe(¬ifyReboot); textMessageObserver.observe(textMessageModule); +#if !MESHTASTIC_EXCLUDE_ADMIN + adminMessageObserver.observe(adminModule); +#endif #ifdef ARCH_ESP32 lightSleepObserver.observe(¬ifyLightSleep); #endif @@ -117,8 +122,13 @@ int InkHUD::Events::beforeReboot(void *unused) sa->onReboot(); } - inkhud->persistence->saveSettings(); - inkhud->persistence->saveLatestMessage(); + // Save settings to flash, or erase if factory reset in progress + if (!eraseOnReboot) { + inkhud->persistence->saveSettings(); + inkhud->persistence->saveLatestMessage(); + } else { + NicheGraphics::clearFlashData(); + } // Note: no forceUpdate call here // We don't have any final screen to draw, although LogoApplet::onReboot did already display a "rebooting" screen @@ -171,6 +181,23 @@ int InkHUD::Events::onReceiveTextMessage(const meshtastic_MeshPacket *packet) return 0; // Tell caller to continue notifying other observers. (No reason to abort this event) } +int InkHUD::Events::onAdminMessage(const meshtastic_AdminMessage *message) +{ + switch (message->which_payload_variant) { + // Factory reset + // Two possible messages. One preserves BLE bonds, other wipes. Both should clear InkHUD data. + case meshtastic_AdminMessage_factory_reset_device_tag: + case meshtastic_AdminMessage_factory_reset_config_tag: + eraseOnReboot = true; + break; + + default: + break; + } + + return 0; // Tell caller to continue notifying other observers. (No reason to abort this event) +} + #ifdef ARCH_ESP32 // Callback for lightSleepObserver // Make sure the display is not partway through an update when we begin light sleep diff --git a/src/graphics/niche/InkHUD/Events.h b/src/graphics/niche/InkHUD/Events.h index 6a6e9d7a2..489135ea3 100644 --- a/src/graphics/niche/InkHUD/Events.h +++ b/src/graphics/niche/InkHUD/Events.h @@ -33,6 +33,7 @@ class Events int beforeDeepSleep(void *unused); // Prepare for shutdown int beforeReboot(void *unused); // Prepare for reboot int onReceiveTextMessage(const meshtastic_MeshPacket *packet); // Store most recent text message + int onAdminMessage(const meshtastic_AdminMessage *message); // Handle incoming admin messages #ifdef ARCH_ESP32 int beforeLightSleep(void *unused); // Prepare for light sleep #endif @@ -52,10 +53,17 @@ class Events CallbackObserver textMessageObserver = CallbackObserver(this, &Events::onReceiveTextMessage); + // Get notified of incoming admin messages, and handle any which are relevant to InkHUD + CallbackObserver adminMessageObserver = + CallbackObserver(this, &Events::onAdminMessage); + #ifdef ARCH_ESP32 // Get notified when the system is entering light sleep CallbackObserver lightSleepObserver = CallbackObserver(this, &Events::beforeLightSleep); #endif + + // If set, InkHUD's data will be erased during onReboot + bool eraseOnReboot = false; }; } // namespace NicheGraphics::InkHUD diff --git a/src/graphics/niche/InkHUD/docs/README.md b/src/graphics/niche/InkHUD/docs/README.md index 07fe6c942..c3082add1 100644 --- a/src/graphics/niche/InkHUD/docs/README.md +++ b/src/graphics/niche/InkHUD/docs/README.md @@ -502,6 +502,10 @@ Applets themselves do also listen separately for various events, but for the pur Button input is sometimes handled by a system applet. `InkHUD::Events` determines whether the button should be handled by a specific system applet, or should instead trigger a default behavior +#### Factory Reset + +The Events class handles the admin messages(s) which trigger factory reset. We set `Events::eraseOnReboot = true`, which causes `Events::onReboot` to erase the contents of InkHUD's data directory. We do this because some applets (e.g. ThreadedMessageApplet) save their own data to flash, so if we erased earlier, that data would get re-written during reboot. + --- ### `InkHUD::Applet` diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 88109bc78..650910542 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -284,7 +284,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta case meshtastic_AdminMessage_remove_by_nodenum_tag: { LOG_INFO("Client received remove_nodenum command"); nodeDB->removeNodeByNum(r->remove_by_nodenum); - this->notifyObservers(r); // Observed by screen break; } case meshtastic_AdminMessage_set_favorite_node_tag: { @@ -444,6 +443,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp); } + // Allow any observers (e.g. the UI) to respond to this event + notifyObservers(r); + return handled; } From a8ab6e82e63e7452bd0f197e1e045573f9cd2145 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Thu, 1 May 2025 03:50:30 +0200 Subject: [PATCH 120/238] MUI framebuffer support (#6703) Co-authored-by: Ben Meadors --- src/graphics/tftSetup.cpp | 14 ++++++++--- src/platform/portduino/PortduinoGlue.cpp | 2 ++ src/platform/portduino/PortduinoGlue.h | 2 +- variants/portduino/platformio.ini | 31 ++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/graphics/tftSetup.cpp b/src/graphics/tftSetup.cpp index a8d51bb82..b2e92bdae 100644 --- a/src/graphics/tftSetup.cpp +++ b/src/graphics/tftSetup.cpp @@ -43,10 +43,10 @@ void tftSetup(void) #else if (settingsMap[displayPanel] != no_screen) { DisplayDriverConfig displayConfig; - static char *panels[] = {"NOSCREEN", "X11", "ST7789", "ST7735", "ST7735S", "ST7796", - "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; + static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S", + "ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"}; -#ifdef USE_X11 +#if defined(USE_X11) if (settingsMap[displayPanel] == x11) { if (settingsMap[displayWidth] && settingsMap[displayHeight]) displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth], @@ -54,6 +54,14 @@ void tftSetup(void) else displayConfig.device(DisplayDriverConfig::device_t::X11); } else +#elif defined(USE_FRAMEBUFFER) + if (settingsMap[displayPanel] == fb) { + if (settingsMap[displayWidth] && settingsMap[displayHeight]) + displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth], + (uint16_t)settingsMap[displayHeight]); + else + displayConfig.device(DisplayDriverConfig::device_t::FB); + } else #endif { displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 6d0972dc3..4b96e662a 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -531,6 +531,8 @@ bool loadConfig(const char *configPath) settingsMap[displayPanel] = hx8357d; else if (yamlConfig["Display"]["Panel"].as("") == "X11") settingsMap[displayPanel] = x11; + else if (yamlConfig["Display"]["Panel"].as("") == "FB") + settingsMap[displayPanel] = fb; settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as(0); settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as(0); settingsMap[displayDC] = yamlConfig["Display"]["DC"].as(-1); diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index f7239cb73..6393d7294 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -102,7 +102,7 @@ enum configNames { available_directory, mac_address }; -enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; +enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; enum { level_error, level_warn, level_info, level_debug, level_trace }; diff --git a/variants/portduino/platformio.ini b/variants/portduino/platformio.ini index 7a3392eb4..fe89ad6e6 100644 --- a/variants/portduino/platformio.ini +++ b/variants/portduino/platformio.ini @@ -43,6 +43,37 @@ build_src_filter = ${native_base.build_src_filter} - +[env:native-fb] +extends = native_base +build_type = release +lib_deps = + ${native_base.lib_deps} + ${device-ui_base.lib_deps} +board_level = extra +build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections -Wl,--gc-sections + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D RAM_SIZE=8192 + -D USE_FRAMEBUFFER=1 + -D LV_COLOR_DEPTH=32 + -D HAS_TFT=1 + -D HAS_SCREEN=0 + -D LV_BUILD_TEST=0 + -D LV_USE_LOG=0 + -D LV_USE_EVDEV=1 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + -D VIEW_320x240 + -D MAP_FULL_REDRAW + !pkg-config --libs libulfius --silence-errors || : + !pkg-config --libs openssl --silence-errors || : +build_src_filter = + ${native_base.build_src_filter} + - + [env:native-tft-debug] extends = native_base build_type = debug From 987623567ae06ce58e996b474d3659dd88495e05 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Thu, 1 May 2025 13:32:20 +0200 Subject: [PATCH 121/238] router: on linux add a mutex around the queue (#6709) UDP reception happens on an other thread, avoid data races and potential data corruption issues. --- src/mesh/Router.cpp | 8 ++++++++ src/mesh/Router.h | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index fef29388e..bb0858c8b 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -64,6 +64,10 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA */ int32_t Router::runOnce() { +#ifdef ARCH_PORTDUINO + const std::lock_guard lock(queueMutex); +#endif + meshtastic_MeshPacket *mp; while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) { // printPacket("handle fromRadioQ", mp); @@ -80,6 +84,10 @@ int32_t Router::runOnce() */ void Router::enqueueReceivedMessage(meshtastic_MeshPacket *p) { +#ifdef ARCH_PORTDUINO + const std::lock_guard lock(queueMutex); +#endif + // Try enqueue until successful while (!fromRadioQueue.enqueue(p, 0)) { meshtastic_MeshPacket *old_p; diff --git a/src/mesh/Router.h b/src/mesh/Router.h index 58ca50f3d..f4782d863 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -8,6 +8,9 @@ #include "PointerQueue.h" #include "RadioInterface.h" #include "concurrency/OSThread.h" +#ifdef ARCH_PORTDUINO +#include +#endif /** * A mesh aware router that supports multiple interfaces. @@ -19,6 +22,12 @@ class Router : protected concurrency::OSThread, protected PacketHistory /// forwarded to the phone. PointerQueue fromRadioQueue; +#ifdef ARCH_PORTDUINO + /// linux calls enqueueReceivedMessage from an other thread when receiving UDP packets, + /// to avoid a data race with LoRa, lock that method. + std::mutex queueMutex; +#endif + protected: RadioInterface *iface = NULL; From 947191a7979bf394986d3c3920e8fd0da472be58 Mon Sep 17 00:00:00 2001 From: Ferdia McKeogh Date: Fri, 2 May 2025 03:11:09 +0100 Subject: [PATCH 122/238] Add PA1010D GPS support (#6691) --- src/gps/GPS.cpp | 15 +++++++++++++++ src/gps/GPS.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 55f62d8ad..e234fdb4a 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -570,6 +570,19 @@ 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_MTK_PA1010D) { + // PA1010D is used in the Pimoroni GPS board. + + // Enable all constellations. + _serial_gps->write("$PMTK353,1,1,1,1,1*2A\r\n"); + // Above command will reset the GPS and takes longer before it will accept new commands + delay(1000); + // Only ask for RMC and GGA (GNRMC and GNGGA) + _serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n"); + delay(250); + // Enable SBAS / WAAS + _serial_gps->write("$PMTK301,2*2E\r\n"); + delay(250); } else if (gnssModel == GNSS_MODEL_MTK_PA1616S) { // PA1616S is used in some GPS breakout boards from Adafruit // PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here. @@ -1238,9 +1251,11 @@ GnssModel_t GPS::probe(int serialSpeed) _serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n"); delay(20); std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, + {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D}, {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}}; + PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500); uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00}; diff --git a/src/gps/GPS.h b/src/gps/GPS.h index 240cf66d2..9be57017f 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -27,6 +27,7 @@ typedef enum { GNSS_MODEL_UC6580, GNSS_MODEL_UNKNOWN, GNSS_MODEL_MTK_L76B, + GNSS_MODEL_MTK_PA1010D, GNSS_MODEL_MTK_PA1616S, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352, From baae2503d53c1ce107fb69734ad88e8d8808367d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 16:24:21 +0800 Subject: [PATCH 123/238] Upgrade trunk to 1.22.15 (#6608) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 60e422312..92cd5b316 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,6 +1,6 @@ version: 0.1 cli: - version: 1.22.12 + version: 1.22.15 plugins: sources: - id: trunk @@ -8,18 +8,18 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - renovate@39.243.0 + - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.23 + - trufflehog@3.88.26 - yamllint@1.37.0 - bandit@1.8.3 - terrascan@1.19.9 - - trivy@0.61.0 + - trivy@0.61.1 - taplo@0.9.3 - - ruff@0.11.5 + - ruff@0.11.7 - isort@6.0.1 - markdownlint@0.44.0 - - oxipng@9.1.4 + - oxipng@9.1.5 - svgo@3.3.2 - actionlint@1.7.7 - flake8@7.2.0 @@ -28,7 +28,7 @@ lint: - shellcheck@0.10.0 - black@25.1.0 - git-diff-check - - gitleaks@8.24.3 + - gitleaks@8.25.1 - clang-format@16.0.3 ignore: - linters: [ALL] From 7da8aea1df3b87c26d9c3f8002e95adeb83a93eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 06:16:53 -0500 Subject: [PATCH 124/238] chore(deps): update meshtastic-device-ui digest to aa38459 (#6706) 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 73a9bbe1f..cfa6cd4ef 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/33aa6890f7862d81c2bc1658f43eeea7a8081c6e.zip + https://github.com/meshtastic/device-ui/archive/aa38459f4e4c0bc6e4d1bda52d26393f0fcf1b97.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 10693c4569b4bf33e02255c598693569f0950b18 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 2 May 2025 23:20:56 +1200 Subject: [PATCH 125/238] Lock SPI bus while in use by InkHUD (#6719) Co-authored-by: Ben Meadors --- .../niche/Drivers/EInk/LCMEN2R13EFC1.cpp | 16 ++++++++++++++-- src/graphics/niche/Drivers/EInk/SSD16XX.cpp | 15 ++++++++++++++- src/graphics/niche/FlashData.h | 17 ++++++++++++++--- src/graphics/niche/InkHUD/MessageStore.cpp | 14 ++++++++++++++ 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp b/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp index 13a3f452d..fb37544b2 100644 --- a/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp +++ b/src/graphics/niche/Drivers/EInk/LCMEN2R13EFC1.cpp @@ -1,9 +1,11 @@ -#include "./LCMEN2R13EFC1.h" - #ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS +#include "./LCMEN2R13EFC1.h" + #include +#include "SPILock.h" + using namespace NicheGraphics::Drivers; // Look up table: fast refresh, common electrode @@ -150,6 +152,9 @@ void LCMEN213EFC1::reset() void LCMEN213EFC1::sendCommand(const uint8_t command) { + // Take firmware's SPI lock + spiLock->lock(); + spi->beginTransaction(spiSettings); digitalWrite(pin_dc, LOW); // DC pin low indicates command digitalWrite(pin_cs, LOW); @@ -157,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command) digitalWrite(pin_cs, HIGH); digitalWrite(pin_dc, HIGH); spi->endTransaction(); + + spiLock->unlock(); } void LCMEN213EFC1::sendData(uint8_t data) @@ -166,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data) void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size) { + // Take firmware's SPI lock + spiLock->lock(); + spi->beginTransaction(spiSettings); digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command digitalWrite(pin_cs, LOW); @@ -183,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size) digitalWrite(pin_cs, HIGH); digitalWrite(pin_dc, HIGH); spi->endTransaction(); + + spiLock->unlock(); } void LCMEN213EFC1::configFull() diff --git a/src/graphics/niche/Drivers/EInk/SSD16XX.cpp b/src/graphics/niche/Drivers/EInk/SSD16XX.cpp index a2357a80b..d0d030be8 100644 --- a/src/graphics/niche/Drivers/EInk/SSD16XX.cpp +++ b/src/graphics/niche/Drivers/EInk/SSD16XX.cpp @@ -1,6 +1,9 @@ +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + #include "./SSD16XX.h" -#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS +#include "SPILock.h" + using namespace NicheGraphics::Drivers; SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX) @@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command) if (failed) return; + // Take firmware's SPI lock + spiLock->lock(); + spi->beginTransaction(spiSettings); digitalWrite(pin_dc, LOW); // DC pin low indicates command digitalWrite(pin_cs, LOW); @@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command) digitalWrite(pin_cs, HIGH); digitalWrite(pin_dc, HIGH); spi->endTransaction(); + + spiLock->unlock(); } void SSD16XX::sendData(uint8_t data) @@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size) if (failed) return; + // Take firmware's SPI lock + spiLock->lock(); + spi->beginTransaction(spiSettings); digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command digitalWrite(pin_cs, LOW); @@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size) digitalWrite(pin_cs, HIGH); digitalWrite(pin_dc, HIGH); spi->endTransaction(); + + spiLock->unlock(); } void SSD16XX::configFullscreen() diff --git a/src/graphics/niche/FlashData.h b/src/graphics/niche/FlashData.h index a27c4aea0..233d0922e 100644 --- a/src/graphics/niche/FlashData.h +++ b/src/graphics/niche/FlashData.h @@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations #include "configuration.h" +#include "SPILock.h" #include "SafeFile.h" namespace NicheGraphics @@ -46,6 +47,9 @@ template class FlashData public: static bool load(T *data, const char *label) { + // Take firmware's SPI lock + concurrency::LockGuard guard(spiLock); + // Set false if we run into issues bool okay = true; @@ -103,14 +107,18 @@ template class FlashData return okay; } - // Save module's custom data (settings?) to flash. Does use protobufs + // Save module's custom data (settings?) to flash. Doesn't use protobufs + // Takes the firmware's SPI lock, in case the files are stored on SD card + // Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally. static void save(T *data, const char *label) { // Get a filename based on the label std::string filename = getFilename(label); #ifdef FSCom + spiLock->lock(); FSCom.mkdir("/NicheGraphics"); + spiLock->unlock(); auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename. @@ -119,10 +127,10 @@ template class FlashData // Calculate a hash of the data uint32_t hash = getHash(data); + spiLock->lock(); f.write((uint8_t *)data, sizeof(T)); // Write the actual data f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash - - // f.flush(); + spiLock->unlock(); bool writeSucceeded = f.close(); @@ -139,6 +147,9 @@ template class FlashData inline void clearFlashData() { + // Take firmware's SPI lock, in case the files are stored on SD card + concurrency::LockGuard guard(spiLock); + #ifdef FSCom File dir = FSCom.open("/NicheGraphics"); // Open the directory File file = dir.openNextFile(); // Attempt to open the first file in the directory diff --git a/src/graphics/niche/InkHUD/MessageStore.cpp b/src/graphics/niche/InkHUD/MessageStore.cpp index ac6fe1b35..94e0aa661 100644 --- a/src/graphics/niche/InkHUD/MessageStore.cpp +++ b/src/graphics/niche/InkHUD/MessageStore.cpp @@ -22,6 +22,8 @@ InkHUD::MessageStore::MessageStore(std::string label) } // Write the contents of the MessageStore::messages object to flash +// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card. +// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally void InkHUD::MessageStore::saveToFlash() { assert(!filename.empty()); @@ -29,7 +31,9 @@ void InkHUD::MessageStore::saveToFlash() #ifdef FSCom // Make the directory, if doesn't already exist // This is the same directory accessed by NicheGraphics::FlashData + spiLock->lock(); FSCom.mkdir("/NicheGraphics"); + spiLock->unlock(); // Open or create the file // No "full atomic": don't save then rename @@ -37,6 +41,9 @@ void InkHUD::MessageStore::saveToFlash() LOG_INFO("Saving messages in %s", filename.c_str()); + // Take firmware's SPI Lock while writing + spiLock->lock(); + // 1st byte: how many messages will be written to store f.write(messages.size()); @@ -51,6 +58,9 @@ void InkHUD::MessageStore::saveToFlash() LOG_DEBUG("Wrote message %u, length %u, text \"%s\"", (uint32_t)i, min(MAX_MESSAGE_SIZE, m.text.size()), m.text.c_str()); } + // Release firmware's SPI lock, because SafeFile::close needs it + spiLock->unlock(); + bool writeSucceeded = f.close(); if (!writeSucceeded) { @@ -63,6 +73,7 @@ void InkHUD::MessageStore::saveToFlash() // Attempt to load the previous contents of the MessageStore:message deque from flash. // Filename is controlled by the "label" parameter +// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card. void InkHUD::MessageStore::loadFromFlash() { // Hopefully redundant. Initial intention is to only load / save once per boot. @@ -70,6 +81,9 @@ void InkHUD::MessageStore::loadFromFlash() #ifdef FSCom + // Take the firmware's SPI Lock, in case filesystem is on SD card + concurrency::LockGuard guard(spiLock); + // Check that the file *does* actually exist if (!FSCom.exists(filename.c_str())) { LOG_WARN("'%s' not found. Using default values", filename.c_str()); From 152b8b1b0235bc461c6e4451fbcdac0987b8bf90 Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 2 May 2025 13:53:25 -0400 Subject: [PATCH 126/238] Revert "router: on linux add a mutex around the queue (#6709)" (#6726) This reverts commit 987623567ae06ce58e996b474d3659dd88495e05. --- src/mesh/Router.cpp | 8 -------- src/mesh/Router.h | 9 --------- 2 files changed, 17 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index bb0858c8b..fef29388e 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -64,10 +64,6 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA */ int32_t Router::runOnce() { -#ifdef ARCH_PORTDUINO - const std::lock_guard lock(queueMutex); -#endif - meshtastic_MeshPacket *mp; while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) { // printPacket("handle fromRadioQ", mp); @@ -84,10 +80,6 @@ int32_t Router::runOnce() */ void Router::enqueueReceivedMessage(meshtastic_MeshPacket *p) { -#ifdef ARCH_PORTDUINO - const std::lock_guard lock(queueMutex); -#endif - // Try enqueue until successful while (!fromRadioQueue.enqueue(p, 0)) { meshtastic_MeshPacket *old_p; diff --git a/src/mesh/Router.h b/src/mesh/Router.h index f4782d863..58ca50f3d 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -8,9 +8,6 @@ #include "PointerQueue.h" #include "RadioInterface.h" #include "concurrency/OSThread.h" -#ifdef ARCH_PORTDUINO -#include -#endif /** * A mesh aware router that supports multiple interfaces. @@ -22,12 +19,6 @@ class Router : protected concurrency::OSThread, protected PacketHistory /// forwarded to the phone. PointerQueue fromRadioQueue; -#ifdef ARCH_PORTDUINO - /// linux calls enqueueReceivedMessage from an other thread when receiving UDP packets, - /// to avoid a data race with LoRa, lock that method. - std::mutex queueMutex; -#endif - protected: RadioInterface *iface = NULL; From 9d31d9f43b25b5f2f388546f28ab64d0ce05ce48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 3 May 2025 22:18:39 +0200 Subject: [PATCH 127/238] chore(deps): update meshtastic-device-ui digest to b9e2ad1 (#6729) 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 cfa6cd4ef..fcece8639 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/aa38459f4e4c0bc6e4d1bda52d26393f0fcf1b97.zip + https://github.com/meshtastic/device-ui/archive/b9e2ad1222db9f5a5080248b2f018c250f0efae5.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From d75c91a760afbc1dd9f5192776c284338f52a2e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 08:39:59 -0500 Subject: [PATCH 128/238] [create-pull-request] automated change (#6732) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/protobufs b/protobufs index 27fac3914..078ac8dfb 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 27fac39141d99fe727a0a1824c5397409b1aea75 +Subproject commit 078ac8dfbe5f7533d7755cbe2ca3d08d86e5af34 diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index d5031cb89..dbf6ddb2e 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -79,7 +79,10 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode { /* NMEA messages specifically tailored for CalTopo */ meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO = 5, /* Ecowitt WS85 weather station */ - meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6 + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6, + /* VE.Direct is a serial protocol used by Victron Energy products + https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7 } meshtastic_ModuleConfig_SerialConfig_Serial_Mode; /* TODO: REPLACE */ @@ -467,8 +470,8 @@ extern "C" { #define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) #define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85+1)) +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT+1)) #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK From 8bb1f3e869efbd76abae794630d31352fe4896c8 Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 4 May 2025 14:18:48 -0400 Subject: [PATCH 129/238] Update template for event userprefs (#6720) --- userPrefs.jsonc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/userPrefs.jsonc b/userPrefs.jsonc index d522ad272..eb6dc64b6 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -1,21 +1,21 @@ { // "USERPREFS_BUTTON_PIN": "36", // "USERPREFS_CHANNELS_TO_WRITE": "3", - // "USERPREFS_CHANNEL_0_DOWNLINK_ENABLED": "true", - // "USERPREFS_CHANNEL_0_NAME": "DEFCONnect", + // "USERPREFS_CHANNEL_0_DOWNLINK_ENABLED": "false", + // "USERPREFS_CHANNEL_0_NAME": "REPLACEME", // "USERPREFS_CHANNEL_0_PRECISION": "14", // "USERPREFS_CHANNEL_0_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1 }", // "USERPREFS_CHANNEL_0_UPLINK_ENABLED": "true", - // "USERPREFS_CHANNEL_1_DOWNLINK_ENABLED": "true", - // "USERPREFS_CHANNEL_1_NAME": "REPLACEME", + // "USERPREFS_CHANNEL_1_DOWNLINK_ENABLED": "false", + // "USERPREFS_CHANNEL_1_NAME": "Node Build Chat", // "USERPREFS_CHANNEL_1_PRECISION": "14", - // "USERPREFS_CHANNEL_1_PSK": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }", - // "USERPREFS_CHANNEL_1_UPLINK_ENABLED": "true", - // "USERPREFS_CHANNEL_2_DOWNLINK_ENABLED": "true", - // "USERPREFS_CHANNEL_2_NAME": "REPLACEME", + // "USERPREFS_CHANNEL_1_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa2 }", + // "USERPREFS_CHANNEL_1_UPLINK_ENABLED": "false", + // "USERPREFS_CHANNEL_2_DOWNLINK_ENABLED": "false", + // "USERPREFS_CHANNEL_2_NAME": "Equipment Exchange", // "USERPREFS_CHANNEL_2_PRECISION": "14", - // "USERPREFS_CHANNEL_2_PSK": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }", - // "USERPREFS_CHANNEL_2_UPLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_2_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa3 }", + // "USERPREFS_CHANNEL_2_UPLINK_ENABLED": "false", // "USERPREFS_CONFIG_GPS_MODE": "meshtastic_Config_PositionConfig_GpsMode_ENABLED", // "USERPREFS_CONFIG_LORA_IGNORE_MQTT": "true", // "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US", From 055fdcb7f6f3f8e8c8b8810a072bf5c5a54a6cd7 Mon Sep 17 00:00:00 2001 From: Austin Date: Sun, 4 May 2025 20:08:39 -0400 Subject: [PATCH 130/238] Renovate: Add changelogs for device-ui, cleanup (#6733) --- arch/esp32/esp32.ini | 2 +- arch/esp32/esp32c6.ini | 4 ++-- arch/nrf52/nrf52.ini | 3 ++- arch/portduino/portduino.ini | 2 +- platformio.ini | 2 +- renovate.json | 8 +++++++- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 3a6dc8323..a6eff7bf9 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -59,7 +59,7 @@ lib_deps = # renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto - rweather/Crypto@^0.4.0 + rweather/Crypto@0.4.0 lib_ignore = segger_rtt diff --git a/arch/esp32/esp32c6.ini b/arch/esp32/esp32c6.ini index 7c7e3e923..26b5c0f5b 100644 --- a/arch/esp32/esp32c6.ini +++ b/arch/esp32/esp32c6.ini @@ -1,7 +1,7 @@ [esp32c6_base] extends = esp32_base platform = - # renovate: datasource=git-refs depName=ESP32c6 platform-espressif32 packageName=https://github.com/Jason2866/platform-espressif32 gitBranch=Arduino/IDF5 + # Do not renovate until we have switched to pioarduino tagged builds https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip build_flags = ${arduino_base.build_flags} @@ -32,7 +32,7 @@ lib_deps = # renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto - rweather/Crypto@^0.4.0 + rweather/Crypto@0.4.0 build_src_filter = ${esp32_base.build_src_filter} - diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index d49d8920c..4a77ec4b2 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -28,7 +28,8 @@ build_src_filter = lib_deps= ${arduino_base.lib_deps} ${radiolib_base.lib_deps} - rweather/Crypto@^0.4.0 + # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto + rweather/Crypto@0.4.0 lib_ignore = BluetoothOTA diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 6af3a7717..a19c50319 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -25,7 +25,7 @@ lib_deps = ${radiolib_base.lib_deps} ${environmental_base.lib_deps} # renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto - rweather/Crypto@^0.4.0 + rweather/Crypto@0.4.0 # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX lovyan03/LovyanGFX@^1.2.0 # renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main diff --git a/platformio.ini b/platformio.ini index fcece8639..636ef3c25 100644 --- a/platformio.ini +++ b/platformio.ini @@ -107,7 +107,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 + # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master https://github.com/meshtastic/device-ui/archive/b9e2ad1222db9f5a5080248b2f018c250f0efae5.zip ; Common libs for environmental measurements in telemetry module diff --git a/renovate.json b/renovate.json index 11d35aff8..e88bfb4e1 100644 --- a/renovate.json +++ b/renovate.json @@ -69,5 +69,11 @@ "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}" } ], - "packageRules": [] + "packageRules": [ + { + "matchPackageNames": ["meshtastic/device-ui"], + "reviewers": ["mverch67"], + "changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}" + } + ] } From a32e45f8f2082d2b009298018802bd646383d2a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 05:16:51 -0500 Subject: [PATCH 131/238] Upgrade trunk (#6737) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 92cd5b316..c55635d9c 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -16,7 +16,7 @@ lint: - terrascan@1.19.9 - trivy@0.61.1 - taplo@0.9.3 - - ruff@0.11.7 + - ruff@0.11.8 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.5 From 2d6181fca0efabacb56ccc5a01f35df0ccc3cdbd Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 5 May 2025 07:03:36 -0400 Subject: [PATCH 132/238] update bosch bsec2 (#6727) Co-authored-by: Ben Meadors --- platformio.ini | 8 ++++---- variants/Dongle_nRF52840-pca10059-v1/platformio.ini | 1 - variants/ELECROW-ThinkNode-M1/platformio.ini | 2 -- variants/ME25LS01-4Y10TD/platformio.ini | 1 - variants/ME25LS01-4Y10TD_e-ink/platformio.ini | 1 - variants/MS24SF1/platformio.ini | 1 - variants/MakePython_nRF52840_eink/platformio.ini | 1 - variants/MakePython_nRF52840_oled/platformio.ini | 1 - variants/Seeed_Solar_Node/platformio.ini | 1 - variants/canaryone/platformio.ini | 1 - variants/diy/platformio.ini | 3 --- variants/ec_catsniffer/platformio.ini | 1 - variants/feather_diy/platformio.ini | 1 - variants/feather_rp2040_rfm95/platformio.ini | 1 - variants/heltec_mesh_node_t114/platformio.ini | 1 - variants/heltec_mesh_pocket/platformio.ini | 4 ---- variants/meshlink/platformio.ini | 1 - variants/meshlink_eink/platformio.ini | 1 - variants/monteops_hw1/platformio.ini | 1 - variants/nano-g2-ultra/platformio.ini | 1 - variants/nibble_rp2040/platformio.ini | 1 - variants/rak11310/platformio.ini | 1 - variants/rak2560/platformio.ini | 1 - variants/rak4631/platformio.ini | 1 - variants/rak4631_epaper/platformio.ini | 1 - variants/rak4631_epaper_onrxtx/platformio.ini | 1 - variants/rak4631_eth_gw/platformio.ini | 1 - variants/rak_wismeshtap/platformio.ini | 1 - variants/rp2040-lora/platformio.ini | 1 - variants/rpipico-slowclock/platformio.ini | 1 - variants/rpipico/platformio.ini | 1 - variants/rpipico2/platformio.ini | 1 - variants/rpipico2w/platformio.ini | 1 - variants/rpipicow/platformio.ini | 1 - variants/seeed_xiao_nrf52840_kit/platformio.ini | 1 - variants/senselora_rp2040/platformio.ini | 1 - variants/t-echo/platformio.ini | 2 -- variants/tlora_c6/platformio.ini | 1 - variants/tracker-t1000-e/platformio.ini | 1 - variants/wio-sdk-wm1110/platformio.ini | 1 - variants/wio-t1000-s/platformio.ini | 1 - variants/wio-tracker-wm1110/platformio.ini | 1 - variants/xiao_ble/platformio.ini | 1 - 43 files changed, 4 insertions(+), 53 deletions(-) diff --git a/platformio.ini b/platformio.ini index 636ef3c25..ba41b386d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -148,7 +148,7 @@ lib_deps = # renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library adafruit/Adafruit MLX90614 Library@2.1.5 # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library - boschsensortec/BME68x Sensor Library@1.1.40407 + boschsensortec/BME68x Sensor Library@1.2.40408 # renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221 https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip # renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass @@ -185,7 +185,7 @@ lib_deps = sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 ClosedCube OPT3001@1.1.2 - # renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library - https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip + # renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script + https://github.com/meshtastic/Bosch-BSEC2-Library/archive/e16952dfe5addd4287e1eb8c4f6ecac0fa3dd3de.zip # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master - https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip \ No newline at end of file + https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip diff --git a/variants/Dongle_nRF52840-pca10059-v1/platformio.ini b/variants/Dongle_nRF52840-pca10059-v1/platformio.ini index 9e87fd237..ad944779d 100644 --- a/variants/Dongle_nRF52840-pca10059-v1/platformio.ini +++ b/variants/Dongle_nRF52840-pca10059-v1/platformio.ini @@ -3,7 +3,6 @@ board_level = extra extends = nrf52840_base board = nordic_pca10059 build_flags = ${nrf52840_base.build_flags} -Ivariants/Dongle_nRF52840-pca10059-v1 -D NORDIC_PCA10059 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DEINK_DISPLAY_MODEL=GxEPD2_420_M01 -DEINK_WIDTH=300 -DEINK_HEIGHT=400 diff --git a/variants/ELECROW-ThinkNode-M1/platformio.ini b/variants/ELECROW-ThinkNode-M1/platformio.ini index 86fbde398..2e9a20dfe 100644 --- a/variants/ELECROW-ThinkNode-M1/platformio.ini +++ b/variants/ELECROW-ThinkNode-M1/platformio.ini @@ -9,7 +9,6 @@ debug_tool = jlink build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1 -DELECROW_ThinkNode_M1 -DGPS_POWER_TOGGLE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DUSE_EINK -DEINK_DISPLAY_MODEL=GxEPD2_154_D67 -DEINK_WIDTH=200 @@ -39,7 +38,6 @@ build_flags = ${inkhud.build_flags} -I variants/ELECROW-ThinkNode-M1 -D ELECROW_ThinkNode_M1 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} ${inkhud.build_src_filter} diff --git a/variants/ME25LS01-4Y10TD/platformio.ini b/variants/ME25LS01-4Y10TD/platformio.ini index bd764e107..b452f0ad8 100644 --- a/variants/ME25LS01-4Y10TD/platformio.ini +++ b/variants/ME25LS01-4Y10TD/platformio.ini @@ -4,7 +4,6 @@ board = me25ls01-4y10td board_level = extra ; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e build_flags = ${nrf52840_base.build_flags} -Ivariants/ME25LS01-4Y10TD -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DME25LS01_4Y10TD - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ME25LS01-4Y10TD> diff --git a/variants/ME25LS01-4Y10TD_e-ink/platformio.ini b/variants/ME25LS01-4Y10TD_e-ink/platformio.ini index fb9bd27d5..f9788a521 100644 --- a/variants/ME25LS01-4Y10TD_e-ink/platformio.ini +++ b/variants/ME25LS01-4Y10TD_e-ink/platformio.ini @@ -4,7 +4,6 @@ board = me25ls01-4y10td board_level = extra ; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e build_flags = ${nrf52840_base.build_flags} -Ivariants/ME25LS01-4Y10TD_e-ink -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DME25LS01_4Y10TD - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -DEINK_DISPLAY_MODEL=GxEPD2_420_GDEY042T81 -DEINK_WIDTH=400 diff --git a/variants/MS24SF1/platformio.ini b/variants/MS24SF1/platformio.ini index e109a3270..10e8d2c95 100644 --- a/variants/MS24SF1/platformio.ini +++ b/variants/MS24SF1/platformio.ini @@ -4,7 +4,6 @@ board = ms24sf1 board_level = extra ; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e build_flags = ${nrf52840_base.build_flags} -Ivariants/MS24SF1 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MS24SF1> diff --git a/variants/MakePython_nRF52840_eink/platformio.ini b/variants/MakePython_nRF52840_eink/platformio.ini index 9e2d5bbf7..ef97172e9 100644 --- a/variants/MakePython_nRF52840_eink/platformio.ini +++ b/variants/MakePython_nRF52840_eink/platformio.ini @@ -3,7 +3,6 @@ board_level = extra extends = nrf52840_base board = nordic_pca10059 build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_eink -D PRIVATE_HW - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -D PIN_EINK_EN -DEINK_DISPLAY_MODEL=GxEPD2_290_T5D -DEINK_WIDTH=296 diff --git a/variants/MakePython_nRF52840_oled/platformio.ini b/variants/MakePython_nRF52840_oled/platformio.ini index 25dd36c08..57b9ecb79 100644 --- a/variants/MakePython_nRF52840_oled/platformio.ini +++ b/variants/MakePython_nRF52840_oled/platformio.ini @@ -3,7 +3,6 @@ board_level = extra extends = nrf52840_base board = nordic_pca10059 build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_oled -D PRIVATE_HW - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_oled> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/Seeed_Solar_Node/platformio.ini b/variants/Seeed_Solar_Node/platformio.ini index 9651d3a77..5ee0a5e8f 100644 --- a/variants/Seeed_Solar_Node/platformio.ini +++ b/variants/Seeed_Solar_Node/platformio.ini @@ -6,7 +6,6 @@ build_flags = ${nrf52840_base.build_flags} -I $PROJECT_DIR/variants/Seeed_Solar_Node -D SEEED_SOLAR_NODE -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/Seeed_Solar_Node> lib_deps = diff --git a/variants/canaryone/platformio.ini b/variants/canaryone/platformio.ini index 5e01c3763..ad11305db 100644 --- a/variants/canaryone/platformio.ini +++ b/variants/canaryone/platformio.ini @@ -6,7 +6,6 @@ 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/canaryone - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/canaryone> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini index 825c464a2..d8ceee9cc 100644 --- a/variants/diy/platformio.ini +++ b/variants/diy/platformio.ini @@ -50,7 +50,6 @@ board_level = extra build_flags = ${nrf52840_base.build_flags} -I variants/diy/nrf52_promicro_diy_xtal -D NRF52_PROMICRO_DIY - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/nrf52_promicro_diy_xtal> lib_deps = ${nrf52840_base.lib_deps} @@ -64,7 +63,6 @@ board = promicro-nrf52840 build_flags = ${nrf52840_base.build_flags} -I variants/diy/nrf52_promicro_diy_tcxo -D NRF52_PROMICRO_DIY - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/nrf52_promicro_diy_tcxo> lib_deps = ${nrf52840_base.lib_deps} @@ -77,7 +75,6 @@ extends = nrf52840_base board_level = extra build_flags = ${nrf52840_base.build_flags} -Ivariants/diy/seeed-xiao-nrf52840-wio-sx1262 -D PRIVATE_HW -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/seeed-xiao-nrf52840-wio-sx1262> lib_deps = diff --git a/variants/ec_catsniffer/platformio.ini b/variants/ec_catsniffer/platformio.ini index 9afb44236..6db9abe90 100644 --- a/variants/ec_catsniffer/platformio.ini +++ b/variants/ec_catsniffer/platformio.ini @@ -8,7 +8,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/ec_catsniffer -DDEBUG_RP2040_PORT=Serial # -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags}, -g diff --git a/variants/feather_diy/platformio.ini b/variants/feather_diy/platformio.ini index 82dbb317c..84c582ab0 100644 --- a/variants/feather_diy/platformio.ini +++ b/variants/feather_diy/platformio.ini @@ -3,7 +3,6 @@ extends = nrf52840_base board = adafruit_feather_nrf52840 build_flags = ${nrf52840_base.build_flags} -Ivariants/feather_diy -Dfeather_diy - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/feather_diy> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/feather_rp2040_rfm95/platformio.ini b/variants/feather_rp2040_rfm95/platformio.ini index a28ad7655..db1eb4f02 100644 --- a/variants/feather_rp2040_rfm95/platformio.ini +++ b/variants/feather_rp2040_rfm95/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/feather_rp2040_rfm95 -DDEBUG_RP2040_PORT=Serial -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags} diff --git a/variants/heltec_mesh_node_t114/platformio.ini b/variants/heltec_mesh_node_t114/platformio.ini index 4f83d8516..3ba97bd04 100644 --- a/variants/heltec_mesh_node_t114/platformio.ini +++ b/variants/heltec_mesh_node_t114/platformio.ini @@ -6,7 +6,6 @@ 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/heltec_mesh_node_t114 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE -DHELTEC_T114 diff --git a/variants/heltec_mesh_pocket/platformio.ini b/variants/heltec_mesh_pocket/platformio.ini index 53f56e973..6632c10fe 100644 --- a/variants/heltec_mesh_pocket/platformio.ini +++ b/variants/heltec_mesh_pocket/platformio.ini @@ -6,7 +6,6 @@ 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/heltec_mesh_pocket - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DHELTEC_MESH_POCKET -DHELTEC_MESH_POCKET_BATTERY_5000 -DUSE_EINK @@ -36,7 +35,6 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pock build_flags = ${inkhud.build_flags} ${nrf52840_base.build_flags} - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -I variants/heltec_mesh_pocket -D HELTEC_MESH_POCKET -D HELTEC_MESH_POCKET_BATTERY_5000 @@ -53,7 +51,6 @@ 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/heltec_mesh_pocket - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DHELTEC_MESH_POCKET -DHELTEC_MESH_POCKET_BATTERY_10000 -DUSE_EINK @@ -83,7 +80,6 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_pock build_flags = ${inkhud.build_flags} ${nrf52840_base.build_flags} - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -I variants/heltec_mesh_pocket -D HELTEC_MESH_POCKET -D HELTEC_MESH_POCKET_BATTERY_10000 diff --git a/variants/meshlink/platformio.ini b/variants/meshlink/platformio.ini index ec3506b0e..384858576 100644 --- a/variants/meshlink/platformio.ini +++ b/variants/meshlink/platformio.ini @@ -6,7 +6,6 @@ extends = nrf52840_base board = meshlink ;board_check = true build_flags = ${nrf52840_base.build_flags} -I variants/meshlink -D MESHLINK - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -D EINK_DISPLAY_MODEL=GxEPD2_213_B74 -D EINK_WIDTH=250 diff --git a/variants/meshlink_eink/platformio.ini b/variants/meshlink_eink/platformio.ini index f8ee96fc3..550b1e2fc 100644 --- a/variants/meshlink_eink/platformio.ini +++ b/variants/meshlink_eink/platformio.ini @@ -6,7 +6,6 @@ extends = nrf52840_base board = meshlink ;board_check = true build_flags = ${nrf52840_base.build_flags} -I variants/meshlink_eink -D MESHLINK - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -D EINK_DISPLAY_MODEL=GxEPD2_213_B74 -D EINK_WIDTH=250 diff --git a/variants/monteops_hw1/platformio.ini b/variants/monteops_hw1/platformio.ini index 1464ca7e7..82567f614 100644 --- a/variants/monteops_hw1/platformio.ini +++ b/variants/monteops_hw1/platformio.ini @@ -4,7 +4,6 @@ board_level = extra extends = nrf52840_base board = wiscore_rak4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/monteops_hw1 -D MONTEOPS_HW1 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/monteops_hw1> + + + lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nano-g2-ultra/platformio.ini b/variants/nano-g2-ultra/platformio.ini index 913b38e3f..7da168b47 100644 --- a/variants/nano-g2-ultra/platformio.ini +++ b/variants/nano-g2-ultra/platformio.ini @@ -5,7 +5,6 @@ board = nano-g2-ultra debug_tool = jlink build_flags = ${nrf52840_base.build_flags} -Ivariants/nano-g2-ultra -D NANO_G2_ULTRA - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nano-g2-ultra> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nibble_rp2040/platformio.ini b/variants/nibble_rp2040/platformio.ini index ad987895f..c3a1923c5 100644 --- a/variants/nibble_rp2040/platformio.ini +++ b/variants/nibble_rp2040/platformio.ini @@ -10,7 +10,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/nibble_rp2040 -DDEBUG_RP2040_PORT=Serial -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags}, -g diff --git a/variants/rak11310/platformio.ini b/variants/rak11310/platformio.ini index c87304e61..fd7e842cc 100644 --- a/variants/rak11310/platformio.ini +++ b/variants/rak11310/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/rak11310 -DDEBUG_RP2040_PORT=Serial -DRV3028_RTC=0x52 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" build_src_filter = ${rp2040_base.build_src_filter} +<../variants/rak11310> + + + lib_deps = ${rp2040_base.lib_deps} diff --git a/variants/rak2560/platformio.ini b/variants/rak2560/platformio.ini index faed231f1..8a720ce5a 100644 --- a/variants/rak2560/platformio.ini +++ b/variants/rak2560/platformio.ini @@ -4,7 +4,6 @@ extends = nrf52840_base board = wiscore_rak4631 board_check = true build_flags = ${nrf52840_base.build_flags} -Ivariants/rak2560 -D RAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -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 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 1c6bdabcf..f2d68e704 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -4,7 +4,6 @@ extends = nrf52840_base board = wiscore_rak4631 board_check = true build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -DEINK_DISPLAY_MODEL=GxEPD2_213_BN -DEINK_WIDTH=250 diff --git a/variants/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini index b851691ed..7c8a299bb 100644 --- a/variants/rak4631_epaper/platformio.ini +++ b/variants/rak4631_epaper/platformio.ini @@ -3,7 +3,6 @@ extends = nrf52840_base board = wiscore_rak4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631_epaper -D RAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DEINK_DISPLAY_MODEL=GxEPD2_213_BN -DEINK_WIDTH=250 -DEINK_HEIGHT=122 diff --git a/variants/rak4631_epaper_onrxtx/platformio.ini b/variants/rak4631_epaper_onrxtx/platformio.ini index 8612a3f3d..c749fc686 100644 --- a/variants/rak4631_epaper_onrxtx/platformio.ini +++ b/variants/rak4631_epaper_onrxtx/platformio.ini @@ -4,7 +4,6 @@ board_level = extra extends = nrf52840_base board = wiscore_rak4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631_epaper -D RAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -D PIN_EINK_EN=34 -D EINK_DISPLAY_MODEL=GxEPD2_213_BN -D EINK_WIDTH=250 diff --git a/variants/rak4631_eth_gw/platformio.ini b/variants/rak4631_eth_gw/platformio.ini index e3da21c55..492ca374b 100644 --- a/variants/rak4631_eth_gw/platformio.ini +++ b/variants/rak4631_eth_gw/platformio.ini @@ -4,7 +4,6 @@ extends = nrf52840_base board = wiscore_rak4631 board_check = true build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631_eth_gw -D RAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -DEINK_DISPLAY_MODEL=GxEPD2_213_BN -DEINK_WIDTH=250 diff --git a/variants/rak_wismeshtap/platformio.ini b/variants/rak_wismeshtap/platformio.ini index 78472783e..6ed97c7ad 100644 --- a/variants/rak_wismeshtap/platformio.ini +++ b/variants/rak_wismeshtap/platformio.ini @@ -3,7 +3,6 @@ extends = nrf52840_base board = wiscore_rak4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/rak_wismeshtap -DWISMESH_TAP -DRAK_4631 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -DEINK_DISPLAY_MODEL=GxEPD2_213_BN -DEINK_WIDTH=250 diff --git a/variants/rp2040-lora/platformio.ini b/variants/rp2040-lora/platformio.ini index 4c578fb2b..7ac5b2cac 100644 --- a/variants/rp2040-lora/platformio.ini +++ b/variants/rp2040-lora/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/rp2040-lora -DDEBUG_RP2040_PORT=Serial -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags}, -g diff --git a/variants/rpipico-slowclock/platformio.ini b/variants/rpipico-slowclock/platformio.ini index c21994249..c56f9e78c 100644 --- a/variants/rpipico-slowclock/platformio.ini +++ b/variants/rpipico-slowclock/platformio.ini @@ -19,7 +19,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/rpipico-slowclock -DDEBUG_RP2040_PORT=Serial2 -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" -g -DNO_USB lib_deps = diff --git a/variants/rpipico/platformio.ini b/variants/rpipico/platformio.ini index 9c62ebcb5..e34cfa43b 100644 --- a/variants/rpipico/platformio.ini +++ b/variants/rpipico/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${rp2040_base.build_flags} -Ivariants/rpipico -DDEBUG_RP2040_PORT=Serial -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags}, -g diff --git a/variants/rpipico2/platformio.ini b/variants/rpipico2/platformio.ini index de4954ea2..066809a91 100644 --- a/variants/rpipico2/platformio.ini +++ b/variants/rpipico2/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${rp2350_base.build_flags} -Ivariants/rpipico2 -DDEBUG_RP2040_PORT=Serial -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m33" lib_deps = ${rp2350_base.lib_deps} debug_build_flags = ${rp2350_base.build_flags}, -g diff --git a/variants/rpipico2w/platformio.ini b/variants/rpipico2w/platformio.ini index 282be1a42..0fac1e9ce 100644 --- a/variants/rpipico2w/platformio.ini +++ b/variants/rpipico2w/platformio.ini @@ -21,7 +21,6 @@ build_flags = ${rp2350_base.build_flags} -DARDUINO_RASPBERRY_PI_PICO_2W -DARDUINO_ARCH_RP2040 -DHAS_WIFI=1 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m33" -fexceptions # for exception handling in MQTT -DHAS_UDP_MULTICAST=1 build_src_filter = ${rp2350_base.build_src_filter} + diff --git a/variants/rpipicow/platformio.ini b/variants/rpipicow/platformio.ini index 4b714434a..e59944b5d 100644 --- a/variants/rpipicow/platformio.ini +++ b/variants/rpipicow/platformio.ini @@ -8,7 +8,6 @@ build_flags = ${rp2040_base.build_flags} -DRPI_PICO -Ivariants/rpipicow -DHW_SPI1_DEVICE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" -fexceptions # for exception handling in MQTT -DHAS_UDP_MULTICAST=1 build_src_filter = ${rp2040_base.build_src_filter} + diff --git a/variants/seeed_xiao_nrf52840_kit/platformio.ini b/variants/seeed_xiao_nrf52840_kit/platformio.ini index 41956249b..0a8bee31c 100644 --- a/variants/seeed_xiao_nrf52840_kit/platformio.ini +++ b/variants/seeed_xiao_nrf52840_kit/platformio.ini @@ -3,7 +3,6 @@ extends = nrf52840_base board = xiao_ble_sense build_flags = ${nrf52840_base.build_flags} -Ivariants/seeed_xiao_nrf52840_kit -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DSEEED_XIAO_NRF52840_KIT - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/seeed_xiao_nrf52840_kit> lib_deps = diff --git a/variants/senselora_rp2040/platformio.ini b/variants/senselora_rp2040/platformio.ini index 852ecbbb9..b05fc1f8b 100644 --- a/variants/senselora_rp2040/platformio.ini +++ b/variants/senselora_rp2040/platformio.ini @@ -9,6 +9,5 @@ build_flags = ${rp2040_base.build_flags} -DSENSELORA_RP2040 -Ivariants/senselora_rp2040 -DDEBUG_RP2040_PORT=Serial - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} \ No newline at end of file diff --git a/variants/t-echo/platformio.ini b/variants/t-echo/platformio.ini index 59fd52ccd..85c3b5799 100644 --- a/variants/t-echo/platformio.ini +++ b/variants/t-echo/platformio.ini @@ -8,7 +8,6 @@ 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/t-echo -DGPS_POWER_TOGGLE - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DEINK_DISPLAY_MODEL=GxEPD2_154_D67 -DEINK_WIDTH=200 -DEINK_HEIGHT=200 @@ -33,7 +32,6 @@ build_flags = ${nrf52840_base.build_flags} ${inkhud.build_flags} -I variants/t-echo - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" build_src_filter = ${nrf52_base.build_src_filter} ${inkhud.build_src_filter} diff --git a/variants/tlora_c6/platformio.ini b/variants/tlora_c6/platformio.ini index d042cd78b..2da10138a 100644 --- a/variants/tlora_c6/platformio.ini +++ b/variants/tlora_c6/platformio.ini @@ -7,4 +7,3 @@ build_flags = -I variants/tlora_c6 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=1 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/esp32c3" \ No newline at end of file diff --git a/variants/tracker-t1000-e/platformio.ini b/variants/tracker-t1000-e/platformio.ini index 64da61434..b1f11d524 100644 --- a/variants/tracker-t1000-e/platformio.ini +++ b/variants/tracker-t1000-e/platformio.ini @@ -2,7 +2,6 @@ extends = nrf52840_base board = tracker-t1000-e build_flags = ${nrf52840_base.build_flags} -Ivariants/tracker-t1000-e -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DTRACKER_T1000_E - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL=1 -DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 diff --git a/variants/wio-sdk-wm1110/platformio.ini b/variants/wio-sdk-wm1110/platformio.ini index e77455bcf..4e1415678 100644 --- a/variants/wio-sdk-wm1110/platformio.ini +++ b/variants/wio-sdk-wm1110/platformio.ini @@ -10,7 +10,6 @@ extra_scripts = # Remove adafruit USB serial from the build (it is incompatible with using the ch340 serial chip on this board) build_unflags = ${nrf52840_base:build_unflags} -DUSBCON -DUSE_TINYUSB build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-sdk-wm1110 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DWIO_WM1110 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. -DCFG_TUD_CDC=0 board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld diff --git a/variants/wio-t1000-s/platformio.ini b/variants/wio-t1000-s/platformio.ini index cb1cf86f7..2eab1e1c5 100644 --- a/variants/wio-t1000-s/platformio.ini +++ b/variants/wio-t1000-s/platformio.ini @@ -4,7 +4,6 @@ extends = nrf52840_base board = wio-t1000-s board_level = extra build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-t1000-s -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DWIO_WM1110 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/wio-t1000-s> diff --git a/variants/wio-tracker-wm1110/platformio.ini b/variants/wio-tracker-wm1110/platformio.ini index 614fea588..a6960b435 100644 --- a/variants/wio-tracker-wm1110/platformio.ini +++ b/variants/wio-tracker-wm1110/platformio.ini @@ -3,7 +3,6 @@ extends = nrf52840_base board = wio-tracker-wm1110 build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-tracker-wm1110 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DWIO_WM1110 - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/wio-tracker-wm1110> diff --git a/variants/xiao_ble/platformio.ini b/variants/xiao_ble/platformio.ini index 6c47780d5..6fa1dd611 100644 --- a/variants/xiao_ble/platformio.ini +++ b/variants/xiao_ble/platformio.ini @@ -4,7 +4,6 @@ extends = nrf52840_base board = xiao_ble_sense board_level = extra build_flags = ${nrf52840_base.build_flags} -Ivariants/xiao_ble -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -D EBYTE_E22 -DEBYTE_E22_900M30S -DPRIVATE_HW - -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld build_src_filter = ${nrf52_base.build_src_filter} +<../variants/xiao_ble> lib_deps = From a2903921cd2cd2d949764318b931d7b5acd7b7dc Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 6 May 2025 12:09:01 -0400 Subject: [PATCH 133/238] Renovate: fix device-ui match (#6748) --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index e88bfb4e1..3403e7211 100644 --- a/renovate.json +++ b/renovate.json @@ -71,7 +71,7 @@ ], "packageRules": [ { - "matchPackageNames": ["meshtastic/device-ui"], + "matchDepNames": ["meshtastic/device-ui"], "reviewers": ["mverch67"], "changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}" } From fdbe16f650f12e3b635b444933e4b244808256ee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 11:09:14 -0500 Subject: [PATCH 134/238] Bump release version (#6743) * automated bumps * Bump org.meshtastic.meshtasticd, fix GHA --------- Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> Co-authored-by: vidplace7 --- .github/workflows/release_channels.yml | 16 ++++++---------- bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ debian/changelog | 8 ++++++-- version.properties | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release_channels.yml b/.github/workflows/release_channels.yml index 12d66b9c2..6f216b411 100644 --- a/.github/workflows/release_channels.yml +++ b/.github/workflows/release_channels.yml @@ -63,21 +63,17 @@ jobs: with: python-version: 3.x - - name: Get release version string - run: | - echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT - echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT - echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT - id: version - env: - BUILD_LOCATION: local - - name: Bump version.properties run: | # Bump version.properties chmod +x ./bin/bump_version.py ./bin/bump_version.py + - name: Get new release version string + run: | + echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT + id: new_version + - name: Ensure debian deps are installed run: | sudo apt-get update -y --fix-missing @@ -94,7 +90,7 @@ jobs: # Bump org.meshtastic.meshtasticd.metainfo.xml pip install -r bin/bump_metainfo/requirements.txt -q chmod +x ./bin/bump_metainfo/bump_metainfo.py - ./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.version.outputs.short }}" + ./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}" env: PIP_DISABLE_PIP_VERSION_CHECK: 1 diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 2cfba3523..b98b54dd4 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7 diff --git a/debian/changelog b/debian/changelog index 3ec57b805..8fce06c14 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -meshtasticd (2.5.22.0) UNRELEASED; urgency=medium +meshtasticd (2.6.8.0) UNRELEASED; urgency=medium + [ Austin Lane ] * Initial packaging * GitHub Actions Automatic version bump * GitHub Actions Automatic version bump * GitHub Actions Automatic version bump * GitHub Actions Automatic version bump - -- Austin Lane Wed, 05 Feb 2025 01:10:33 +0000 + [ ] + * GitHub Actions Automatic version bump + + -- Tue, 06 May 2025 01:32:49 +0000 diff --git a/version.properties b/version.properties index 5baa63dc2..bedba21b7 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 7 +build = 8 From dd2cf633b0e3e3df348e1aaef91fb009879cfe67 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 11:09:25 -0500 Subject: [PATCH 135/238] Upgrade trunk (#6745) Co-authored-by: sachaw <11172820+sachaw@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 c55635d9c..364ed746b 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,8 +10,8 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.26 - - yamllint@1.37.0 + - trufflehog@3.88.27 + - yamllint@1.37.1 - bandit@1.8.3 - terrascan@1.19.9 - trivy@0.61.1 From 1e81ebed06ca954a22ea8046732e86a5d3b8844c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 11:14:45 -0500 Subject: [PATCH 136/238] chore(deps): update meshtastic/device-ui digest to 35576e1 (#6747) 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 ba41b386d..70a607f2f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/b9e2ad1222db9f5a5080248b2f018c250f0efae5.zip + https://github.com/meshtastic/device-ui/archive/35576e131e250f259878ea81819a90df837d1307.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 867f50ab111cdb07269c123e9ecaf70b1d5fb2e3 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 6 May 2025 13:03:01 -0400 Subject: [PATCH 137/238] Don't run `test-native` for event firmwares (#6749) --- .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 a9c4cbb52..9b9877e04 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -149,6 +149,7 @@ jobs: secrets: inherit test-native: + if: ${{ !contains(github.ref_name, 'event/') }} uses: ./.github/workflows/test_native.yml docker-deb-amd64: From 62421a83fd602fc2c5fc17ed655de8ce1fe0d224 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 6 May 2025 13:12:25 -0400 Subject: [PATCH 138/238] Fix EVENT_MODE on mqttless targets (#6750) --- src/mesh/Channels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 4d061f80f..2ba3499f1 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -345,7 +345,7 @@ void Channels::setChannel(const meshtastic_Channel &c) bool Channels::anyMqttEnabled() { -#if USERPREFS_EVENT_MODE +#if USERPREFS_EVENT_MODE && !MESHTASTIC_EXCLUDE_MQTT // Don't publish messages on the public MQTT broker if we are in event mode if (mqtt && mqtt->isUsingDefaultServer()) { return false; From 57d6c1fa8512bf18c1a2483d2362857b1705c065 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 6 May 2025 18:05:22 -0400 Subject: [PATCH 139/238] Fix event templates (names, PSKs) (#6753) --- userPrefs.jsonc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/userPrefs.jsonc b/userPrefs.jsonc index eb6dc64b6..06c4a7eec 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -7,14 +7,14 @@ // "USERPREFS_CHANNEL_0_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1 }", // "USERPREFS_CHANNEL_0_UPLINK_ENABLED": "true", // "USERPREFS_CHANNEL_1_DOWNLINK_ENABLED": "false", - // "USERPREFS_CHANNEL_1_NAME": "Node Build Chat", + // "USERPREFS_CHANNEL_1_NAME": "NodeChat", // "USERPREFS_CHANNEL_1_PRECISION": "14", - // "USERPREFS_CHANNEL_1_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa2 }", + // "USERPREFS_CHANNEL_1_PSK": "{ 0x4e, 0x22, 0x1d, 0x8b, 0xc3, 0x09, 0x1b, 0xe2, 0x11, 0x9c, 0x89, 0x12, 0xf2, 0x25, 0x19, 0x5d, 0x15, 0x3e, 0x30, 0x7b, 0x86, 0xb6, 0xec, 0xc4, 0x6a, 0xc3, 0x96, 0x5e, 0x9e, 0x10, 0x9d, 0xd5 }", // "USERPREFS_CHANNEL_1_UPLINK_ENABLED": "false", // "USERPREFS_CHANNEL_2_DOWNLINK_ENABLED": "false", - // "USERPREFS_CHANNEL_2_NAME": "Equipment Exchange", + // "USERPREFS_CHANNEL_2_NAME": "YardSale", // "USERPREFS_CHANNEL_2_PRECISION": "14", - // "USERPREFS_CHANNEL_2_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa3 }", + // "USERPREFS_CHANNEL_2_PSK": "{ 0x15, 0x6f, 0xfe, 0x46, 0xd4, 0x56, 0x63, 0x8a, 0x54, 0x43, 0x13, 0xf2, 0xef, 0x6c, 0x63, 0x89, 0xf0, 0x06, 0x30, 0x52, 0xce, 0x36, 0x5e, 0xb1, 0xe8, 0xbb, 0x86, 0xe6, 0x26, 0x5b, 0x1d, 0x58 }", // "USERPREFS_CHANNEL_2_UPLINK_ENABLED": "false", // "USERPREFS_CONFIG_GPS_MODE": "meshtastic_Config_PositionConfig_GpsMode_ENABLED", // "USERPREFS_CONFIG_LORA_IGNORE_MQTT": "true", From 86217111b26885b2f92235388afc5d41575de94d Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Wed, 7 May 2025 04:28:18 -0700 Subject: [PATCH 140/238] Update SECURITY.md (#6757) --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index fb4d9005a..5092595e1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,8 @@ | Firmware Version | Supported | | ---------------- | ------------------ | -| 2.5.x | :white_check_mark: | -| <= 2.4.x | :x: | +| 2.6.x | :white_check_mark: | +| <= 2.5.x | :x: | ## Reporting a Vulnerability From 6f256c06f6ce078137bb6b6a06b60714a90964f5 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 7 May 2025 09:26:10 -0500 Subject: [PATCH 141/238] Fix warning --- src/modules/SerialModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index e088b4612..8d280581c 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -513,7 +513,7 @@ void SerialModule::processWXSerial() // Extract the current line char line[meshtastic_Constants_DATA_PAYLOAD_LEN]; memset(line, '\0', sizeof(line)); - if (lineEnd - lineStart < sizeof(line) - 1) { + if ((size_t)(lineEnd - lineStart) < sizeof(line) - 1) { memcpy(line, &serialBytes[lineStart], lineEnd - lineStart); ParsedLine parsed = parseLine(line); From b657ba1abbaad875ba11877cbc35e45ee737c031 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 13:27:44 -0500 Subject: [PATCH 142/238] chore(deps): update sparkfun 9dof imu breakout icm 20948 to v1.3.2 (#6761) 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 70a607f2f..706e01b44 100644 --- a/platformio.ini +++ b/platformio.ini @@ -182,7 +182,7 @@ lib_deps = # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library - sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0 + sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 ClosedCube OPT3001@1.1.2 # renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script From 3a6fc668d8d799313fdcf068c5f201fe983f0566 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 7 May 2025 18:38:42 -0500 Subject: [PATCH 143/238] 20948 compass support (#6707) * Add __has_include blocks for sensors * Put BMP and BME back in the right sensors * Split environmental_base to environmental_extra, to compile the working sensor libs for Native * Remove hard-coded checks for ARCH_PORTDUINO * Un-clobber bmx160 * Move BusIO to environmental_extra due to Armv7 compile error * Move to forked BusIO for the moment * Switch to Meshtastic ICM-20948 lib for Portduino support * Use 20948 for compass direction * Compass is more than just RAK4631 * Cleanup for 20948 compass * use Meshtastic branch of 20948 lib * Check for HAS_SCREEN for showing calibration screen * No accelerometerThread on STM32 --- platformio.ini | 8 +-- src/ButtonThread.cpp | 2 +- src/main.cpp | 11 +++- src/main.h | 2 +- src/modules/AdminModule.cpp | 2 +- src/motion/AccelerometerThread.h | 10 +-- src/motion/BMX160Sensor.cpp | 2 +- src/motion/ICM20948Sensor.cpp | 103 +++++++++++++++++++++++++++++++ src/motion/ICM20948Sensor.h | 4 ++ src/motion/MotionSensor.cpp | 2 +- src/motion/MotionSensor.h | 2 +- 11 files changed, 126 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 706e01b44..1673dfc78 100644 --- a/platformio.ini +++ b/platformio.ini @@ -161,8 +161,10 @@ lib_deps = robtillaart/INA226@0.6.4 # renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 - -; (not included in native / portduino) + # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library + sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 + + ; (not included in native / portduino) [environmental_extra] lib_deps = # renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library @@ -181,8 +183,6 @@ lib_deps = adafruit/Adafruit SHT4x Library@1.0.5 # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 - # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library - sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 ClosedCube OPT3001@1.1.2 # renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 04200a7df..352885dbe 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -255,7 +255,7 @@ int32_t ButtonThread::runOnce() digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); break; #endif -#if defined(RAK_4631) +#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN // 5 clicks: start accelerometer/magenetometer calibration for 30 seconds case 5: if (accelerometerThread) { diff --git a/src/main.cpp b/src/main.cpp index 9ef944e65..452cb3526 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,7 +105,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr; #include "AmbientLightingThread.h" #include "PowerFSMThread.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C #include "motion/AccelerometerThread.h" AccelerometerThread *accelerometerThread = nullptr; #endif @@ -692,7 +692,7 @@ void setup() } #endif -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if !defined(ARCH_STM32WL) auto acc_info = i2cScanner->firstAccelerometer(); accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found; LOG_DEBUG("acc_info = %i", acc_info.type); @@ -807,7 +807,7 @@ void setup() #endif #if !MESHTASTIC_EXCLUDE_I2C -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) +#if !defined(ARCH_STM32WL) if (acc_info.type != ScanI2C::DeviceType::NONE) { accelerometerThread = new AccelerometerThread(acc_info.type); } @@ -1300,7 +1300,12 @@ void setup() LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap()); LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram()); #endif +#if !defined(ARCH_STM32WL) + if (accelerometerThread) + accelerometerThread->calibrate(30); +#endif } + #endif uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes) uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to shutdown from python or mobile client) diff --git a/src/main.h b/src/main.h index c3807cfd5..beeb1f940 100644 --- a/src/main.h +++ b/src/main.h @@ -58,7 +58,7 @@ extern UdpMulticastHandler *udpHandler; // Global Screen singleton. extern graphics::Screen *screen; -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C #include "motion/AccelerometerThread.h" extern AccelerometerThread *accelerometerThread; #endif diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 650910542..0e1e1555b 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -38,7 +38,7 @@ #include "modules/PositionModule.h" #endif -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C #include "motion/AccelerometerThread.h" #endif diff --git a/src/motion/AccelerometerThread.h b/src/motion/AccelerometerThread.h index dd6413d64..02e5b0bd4 100755 --- a/src/motion/AccelerometerThread.h +++ b/src/motion/AccelerometerThread.h @@ -4,7 +4,7 @@ #include "configuration.h" -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C +#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C #include "../concurrency/OSThread.h" #ifdef HAS_BMA423 @@ -81,14 +81,6 @@ class AccelerometerThread : public concurrency::OSThread return; } -#ifndef RAK_4631 - if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) { - LOG_DEBUG("AccelerometerThread Disable due to no interested configurations"); - disable(); - return; - } -#endif - switch (device.type) { #ifdef HAS_BMA423 case ScanI2C::DeviceType::BMA423: diff --git a/src/motion/BMX160Sensor.cpp b/src/motion/BMX160Sensor.cpp index 39bc04ea1..a3909ea3a 100755 --- a/src/motion/BMX160Sensor.cpp +++ b/src/motion/BMX160Sensor.cpp @@ -4,7 +4,7 @@ BMX160Sensor::BMX160Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} -#if defined(RAK_4631) && !defined(RAK2560) && __has_include() +#if !defined(RAK2560) && __has_include() #if !defined(MESHTASTIC_EXCLUDE_SCREEN) // screen is defined in main.cpp diff --git a/src/motion/ICM20948Sensor.cpp b/src/motion/ICM20948Sensor.cpp index 946390ddb..d03633124 100755 --- a/src/motion/ICM20948Sensor.cpp +++ b/src/motion/ICM20948Sensor.cpp @@ -1,6 +1,11 @@ #include "ICM20948Sensor.h" #if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() +#if !defined(MESHTASTIC_EXCLUDE_SCREEN) + +// screen is defined in main.cpp +extern graphics::Screen *screen; +#endif // Flag when an interrupt has been detected volatile static bool ICM20948_IRQ = false; @@ -41,6 +46,88 @@ int32_t ICM20948Sensor::runOnce() int32_t ICM20948Sensor::runOnce() { +#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN + float magX = 0, magY = 0, magZ = 0; + if (sensor->dataReady()) { + sensor->getAGMT(); + magX = sensor->agmt.mag.axes.x; + magY = sensor->agmt.mag.axes.y; + magZ = sensor->agmt.mag.axes.z; + } + + if (doCalibration) { + + if (!showingScreen) { + powerFSM.trigger(EVENT_PRESS); // keep screen alive during calibration + showingScreen = true; + screen->startAlert((FrameCallback)drawFrameCalibration); + } + + if (magX > highestX) + highestX = magX; + if (magX < lowestX) + lowestX = magX; + if (magY > highestY) + highestY = magY; + if (magY < lowestY) + lowestY = magY; + if (magZ > highestZ) + highestZ = magZ; + if (magZ < lowestZ) + lowestZ = magZ; + + uint32_t now = millis(); + if (now > endCalibrationAt) { + doCalibration = false; + endCalibrationAt = 0; + showingScreen = false; + screen->endAlert(); + } + + // LOG_DEBUG("ICM20948 min_x: %.4f, max_X: %.4f, min_Y: %.4f, max_Y: %.4f, min_Z: %.4f, max_Z: %.4f", lowestX, highestX, + // lowestY, highestY, lowestZ, highestZ); + } + + magX -= (highestX + lowestX) / 2; + magY -= (highestY + lowestY) / 2; + magZ -= (highestZ + lowestZ) / 2; + FusionVector ga, ma; + ga.axis.x = (sensor->agmt.acc.axes.x); + ga.axis.y = -(sensor->agmt.acc.axes.y); + ga.axis.z = -(sensor->agmt.acc.axes.z); + ma.axis.x = magX; + ma.axis.y = magY; + ma.axis.z = magZ; + + // If we're set to one of the inverted positions + if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) { + ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ); + ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ); + } + + float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma); + + switch (config.display.compass_orientation) { + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED: + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0: + break; + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90: + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED: + heading += 90; + break; + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180: + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED: + heading += 180; + break; + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270: + case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED: + heading += 270; + break; + } + + screen->setHeading(heading); +#endif + // Wake on motion using polling - this is not as efficient as using hardware interrupt pin (see above) auto status = sensor->setBank(0); if (sensor->status != ICM_20948_Stat_Ok) { @@ -64,6 +151,17 @@ int32_t ICM20948Sensor::runOnce() #endif +void ICM20948Sensor::calibrate(uint16_t forSeconds) +{ +#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN + LOG_DEBUG("BMX160 calibration started for %is", forSeconds); + + doCalibration = true; + uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided + endCalibrationAt = millis() + calibrateFor; + screen->setEndCalibration(endCalibrationAt); +#endif +} // ---------------------------------------------------------------------- // ICM20948Singleton // ---------------------------------------------------------------------- @@ -121,6 +219,11 @@ bool ICM20948Singleton::init(ScanI2C::FoundDevice device) return false; } + if (startupMagnetometer(false) != ICM_20948_Stat_Ok) { + LOG_DEBUG("ICM20948 init magnetometer - %s", statusString()); + return false; + } + #ifdef ICM_20948_INT_PIN // Active low diff --git a/src/motion/ICM20948Sensor.h b/src/motion/ICM20948Sensor.h index 8344b0703..27ce4f451 100755 --- a/src/motion/ICM20948Sensor.h +++ b/src/motion/ICM20948Sensor.h @@ -6,6 +6,7 @@ #if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include() +#include "Fusion/Fusion.h" #include // Set the default gyro scale - dps250, dps500, dps1000, dps2000 @@ -80,6 +81,8 @@ class ICM20948Sensor : public MotionSensor { private: ICM20948Singleton *sensor = nullptr; + bool showingScreen = false; + float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0; public: explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice); @@ -89,6 +92,7 @@ class ICM20948Sensor : public MotionSensor // Called each time our sensor gets a chance to run virtual int32_t runOnce() override; + virtual void calibrate(uint16_t forSeconds) override; }; #endif diff --git a/src/motion/MotionSensor.cpp b/src/motion/MotionSensor.cpp index 54a2f883a..56738d355 100755 --- a/src/motion/MotionSensor.cpp +++ b/src/motion/MotionSensor.cpp @@ -31,7 +31,7 @@ ScanI2C::I2CPort MotionSensor::devicePort() return device.address.port; } -#if defined(RAK_4631) & !MESHTASTIC_EXCLUDE_SCREEN +#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN void MotionSensor::drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { // int x_offset = display->width() / 2; diff --git a/src/motion/MotionSensor.h b/src/motion/MotionSensor.h index 90080577f..5039f2551 100755 --- a/src/motion/MotionSensor.h +++ b/src/motion/MotionSensor.h @@ -49,7 +49,7 @@ class MotionSensor // Register a button press when a double-tap is detected virtual void buttonPress(); -#if defined(RAK_4631) & !MESHTASTIC_EXCLUDE_SCREEN +#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN // draw an OLED frame (currently only used by the RAK4631 BMX160 sensor) static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); #endif From ff2a12d5795b7bd3a7d5c66056d5034f7f0d4da2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 08:32:01 +0800 Subject: [PATCH 144/238] chore(deps): update adafruit bme280 to v2.3.0 (#6708) 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 1673dfc78..8ceca3d87 100644 --- a/platformio.ini +++ b/platformio.ini @@ -122,7 +122,7 @@ lib_deps = # renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library adafruit/Adafruit BMP085 Library@1.2.4 # renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library - adafruit/Adafruit BME280 Library@2.2.4 + adafruit/Adafruit BME280 Library@2.3.0 # renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310 adafruit/Adafruit DPS310@1.1.5 # renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library From ca9bf6b31aca8de3011d52bfe5a7ceebb8635171 Mon Sep 17 00:00:00 2001 From: Tom <116762865+NomDeTom@users.noreply.github.com> Date: Thu, 8 May 2025 03:20:15 +0100 Subject: [PATCH 145/238] Update XIAO_NRF_KIT RXEN Pin definition (#6717) The XIAO NRF kit comes with a hat which has a slightly different pinout than the one supplied with the XIAO S3. At the last update, the RXEN pin was not moved with the rest. --- variants/seeed_xiao_nrf52840_kit/variant.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variants/seeed_xiao_nrf52840_kit/variant.h b/variants/seeed_xiao_nrf52840_kit/variant.h index 20362cb52..869c3d405 100644 --- a/variants/seeed_xiao_nrf52840_kit/variant.h +++ b/variants/seeed_xiao_nrf52840_kit/variant.h @@ -114,8 +114,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define SX126X_TXEN RADIOLIB_NC -#define SX126X_RXEN D4 -#define SX126X_DIO2_AS_RF_SWITCH // DIO2 is used to control the RF switch really necessary!!! +#define SX126X_RXEN D5 // This is used to control the RX side of the RF switch +#define SX126X_DIO2_AS_RF_SWITCH // DIO2 is used to control the TX side of the RF switch #define SX126X_DIO3_TCXO_VOLTAGE 1.8 /* From 981ecfdb61bd231c47988bdec9c55e28bdaeef79 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 7 May 2025 21:20:32 -0500 Subject: [PATCH 146/238] Add client notification before role based power saving (sleep) (#6759) * Add client notification before role based power saving (sleep) * Unsigned --- src/modules/PositionModule.cpp | 11 +++++++++-- src/modules/Telemetry/EnvironmentTelemetry.cpp | 12 ++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index acbc3143d..0b1bdcc46 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -370,9 +370,16 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER, meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) && config.power.is_power_saving) { - LOG_DEBUG("Start next execution in 5s, then sleep"); + meshtastic_ClientNotification *notification = clientNotificationPool.allocZeroed(); + notification->level = meshtastic_LogRecord_Level_INFO; + notification->time = getValidTime(RTCQualityFromNet); + sprintf(notification->message, "Sending position and sleeping for %us interval in a moment", + Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs) / + 1000U); + service->sendClientNotification(notification); sleepOnNextExecution = true; - setIntervalFromNow(5000); + LOG_DEBUG("Start next execution in 5s, then sleep"); + setIntervalFromNow(FIVE_SECONDS_MS); } } diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 32c660bbf..56f9d7433 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -675,9 +675,17 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) service->sendToMesh(p, RX_SRC_LOCAL, true); if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) { - LOG_DEBUG("Start next execution in 5s, then sleep"); + meshtastic_ClientNotification *notification = clientNotificationPool.allocZeroed(); + notification->level = meshtastic_LogRecord_Level_INFO; + notification->time = getValidTime(RTCQualityFromNet); + sprintf(notification->message, "Sending telemetry and sleeping for %us interval in a moment", + Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval, + default_telemetry_broadcast_interval_secs) / + 1000U); + service->sendClientNotification(notification); sleepOnNextExecution = true; - setIntervalFromNow(5000); + LOG_DEBUG("Start next execution in 5s, then sleep"); + setIntervalFromNow(FIVE_SECONDS_MS); } } return true; From 3aee4bfc6bf2a67fe2c18664dcae2ee7d4fafb21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 19:01:03 +0800 Subject: [PATCH 147/238] Upgrade trunk (#6758) Co-authored-by: sachaw <11172820+sachaw@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 364ed746b..ca38c978a 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,11 +10,11 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.27 + - trufflehog@3.88.28 - yamllint@1.37.1 - bandit@1.8.3 - terrascan@1.19.9 - - trivy@0.61.1 + - trivy@0.62.1 - taplo@0.9.3 - ruff@0.11.8 - isort@6.0.1 From c2a38357f174f301f344f960ed43a9d6f368b537 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 14:54:58 +0200 Subject: [PATCH 148/238] chore(deps): update meshtastic/device-ui digest to 09b1780 (#6782) 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 8ceca3d87..042853ec6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/35576e131e250f259878ea81819a90df837d1307.zip + https://github.com/meshtastic/device-ui/archive/09b1780c8f944cffbc18a8ec5713cdfe03278503.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 23fe093a6556a9be577fedfa63ec7411711283dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 11:49:01 -0400 Subject: [PATCH 149/238] chore(config): migrate renovate config (#6784) * chore(config): migrate config renovate.json * Prettier: Ignore renovate --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: vidplace7 --- .trunk/configs/.prettierignore | 1 + renovate.json | 44 ++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 .trunk/configs/.prettierignore diff --git a/.trunk/configs/.prettierignore b/.trunk/configs/.prettierignore new file mode 100644 index 000000000..a63a557a4 --- /dev/null +++ b/.trunk/configs/.prettierignore @@ -0,0 +1 @@ +renovate.json diff --git a/renovate.json b/renovate.json index 3403e7211..e90462cc3 100644 --- a/renovate.json +++ b/renovate.json @@ -9,15 +9,21 @@ "workarounds:all" ], "forkProcessing": "enabled", - "ignoreDeps": ["protobufs"], + "ignoreDeps": [ + "protobufs" + ], "git-submodules": { "enabled": true }, "pip_requirements": { - "fileMatch": ["bin/bump_metainfo/requirements.txt"] + "managerFilePatterns": [ + "/bin/bump_metainfo/requirements.txt/" + ] }, "commitMessageTopic": "{{depName}}", - "labels": ["dependencies"], + "labels": [ + "dependencies" + ], "customDatasources": { "pio": { "description": "PlatformIO Registry", @@ -32,8 +38,12 @@ { "customType": "regex", "description": "Match meshtastic/web version", - "fileMatch": ["bin/web.version"], - "matchStrings": ["(?.+)$"], + "managerFilePatterns": [ + "/bin/web.version/" + ], + "matchStrings": [ + "(?.+)$" + ], "datasourceTemplate": "github-releases", "depNameTemplate": "meshtastic/web", "versioningTemplate": "semver-coerced" @@ -41,7 +51,9 @@ { "customType": "regex", "description": "Match normal PIO dependencies", - "fileMatch": [".*\\.ini$"], + "managerFilePatterns": [ + "/.*\\.ini$/" + ], "matchStrings": [ "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s+?.+?@(?.+?)\\s" ], @@ -50,9 +62,11 @@ { "customType": "regex", "description": "Match PIO zipped dependencies with github tag ref", - "fileMatch": [".*\\.ini$"], + "managerFilePatterns": [ + "/.*\\.ini$/" + ], "matchStrings": [ - "# renovate: datasource=github-tags(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s+?https:\/\/.+?archive\/(?.+?).zip\\s" + "# renovate: datasource=github-tags(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s+?https://.+?archive/(?.+?).zip\\s" ], "datasourceTemplate": "github-tags", "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}" @@ -60,9 +74,11 @@ { "customType": "regex", "description": "Match PIO zipped dependencies with git commit ref", - "fileMatch": [".*\\.ini$"], + "managerFilePatterns": [ + "/.*\\.ini$/" + ], "matchStrings": [ - "# renovate: datasource=git-refs(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\sgitBranch=(?.+?)\\s+?https:\/\/.+?archive\/(?.+?).zip\\s" + "# renovate: datasource=git-refs(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\sgitBranch=(?.+?)\\s+?https://.+?archive/(?.+?).zip\\s" ], "datasourceTemplate": "git-refs", "currentValueTemplate": "{{{gitBranch}}}", @@ -71,8 +87,12 @@ ], "packageRules": [ { - "matchDepNames": ["meshtastic/device-ui"], - "reviewers": ["mverch67"], + "matchDepNames": [ + "meshtastic/device-ui" + ], + "reviewers": [ + "mverch67" + ], "changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}" } ] From 7c9296b0f43348204f8f1356e8a9fb8bec57b12c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 18:48:39 +0200 Subject: [PATCH 150/238] chore(deps): update meshtastic/device-ui digest to 027f5a5 (#6783) 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 042853ec6..427ff1702 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/09b1780c8f944cffbc18a8ec5713cdfe03278503.zip + https://github.com/meshtastic/device-ui/archive/027f5a5bace46e75a8208239b20655140dc186df.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From b17bb49a6333facf9dee585ac3dd914c13cfcf8f Mon Sep 17 00:00:00 2001 From: Austin Date: Sat, 10 May 2025 17:21:23 -0400 Subject: [PATCH 151/238] Actions: Fix end to end tests (#6776) --- .github/workflows/tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0f0ee0af4..28b6a40a5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,7 +5,10 @@ on: - cron: 0 0 * * * # Run every day at midnight workflow_dispatch: {} -permissions: read-all +permissions: + contents: read + actions: read + checks: write jobs: native-tests: @@ -44,7 +47,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 - name: Setup pnpm uses: pnpm/action-setup@v4 From b208e1924fb82c9ab9eb273a8679b0edfdc11821 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 00:59:38 +0200 Subject: [PATCH 152/238] chore(deps): update meshtastic/device-ui digest to 7dee10a (#6786) 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 427ff1702..b78ecdc1a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/027f5a5bace46e75a8208239b20655140dc186df.zip + https://github.com/meshtastic/device-ui/archive/7dee10ad31a0c6ea04880cba399e240be743d752.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 62e1974d092453d481dfa2546bcb34180707a029 Mon Sep 17 00:00:00 2001 From: Tom <116762865+NomDeTom@users.noreply.github.com> Date: Sun, 11 May 2025 10:17:37 +0100 Subject: [PATCH 153/238] Add clarifying note about AHT20 also being included with AHT10 library (#6787) * Update AHT10.h Add clarifying note about AHT20 also being included * Update AHT10.cpp Add clarifying note about AHT20 also being included --- src/modules/Telemetry/Sensor/AHT10.cpp | 6 +++++- src/modules/Telemetry/Sensor/AHT10.h | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/Telemetry/Sensor/AHT10.cpp b/src/modules/Telemetry/Sensor/AHT10.cpp index 096a131b9..35934533b 100644 --- a/src/modules/Telemetry/Sensor/AHT10.cpp +++ b/src/modules/Telemetry/Sensor/AHT10.cpp @@ -1,3 +1,7 @@ +/* + * Worth noting that both the AHT10 and AHT20 are supported without alteration. + */ + #include "configuration.h" #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() @@ -41,4 +45,4 @@ bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement) return true; } -#endif \ No newline at end of file +#endif diff --git a/src/modules/Telemetry/Sensor/AHT10.h b/src/modules/Telemetry/Sensor/AHT10.h index b2f0d8ae5..a6fa19952 100644 --- a/src/modules/Telemetry/Sensor/AHT10.h +++ b/src/modules/Telemetry/Sensor/AHT10.h @@ -1,3 +1,7 @@ +/* + * Worth noting that both the AHT10 and AHT20 are supported without alteration. + */ + #include "configuration.h" #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() @@ -20,4 +24,4 @@ class AHT10Sensor : public TelemetrySensor virtual bool getMetrics(meshtastic_Telemetry *measurement) override; }; -#endif \ No newline at end of file +#endif From 2a06b058fdd7dca02667635ba9415030b675b9cc Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 11 May 2025 15:18:53 -0500 Subject: [PATCH 154/238] Only send nodes on want_config of 69421 (#6792) --- src/mesh/PhoneAPI.cpp | 28 +++++++++++++++++++++++----- src/mesh/PhoneAPI.h | 3 ++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 0e18b8ab1..db01e95f3 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -54,7 +54,13 @@ void PhoneAPI::handleStartConfig() } // even if we were already connected - restart our state machine - state = STATE_SEND_MY_INFO; + if (config_nonce == SPECIAL_NONCE_ONLY_NODES) { + // If client only wants node info, jump directly to sending nodes + state = STATE_SEND_OWN_NODEINFO; + LOG_INFO("Client only wants node info, skipping other config"); + } else { + state = STATE_SEND_MY_INFO; + } pauseBluetoothLogging = true; spiLock->lock(); filesManifest = getFiles("/", 10); @@ -224,7 +230,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) // Should allow us to resume sending NodeInfo in STATE_SEND_OTHER_NODEINFOS nodeInfoForPhone.num = 0; } - state = STATE_SEND_METADATA; + if (config_nonce == SPECIAL_NONCE_ONLY_NODES) { + // If client only wants node info, jump directly to sending nodes + state = STATE_SEND_OTHER_NODEINFOS; + } else { + state = STATE_SEND_METADATA; + } break; } @@ -388,8 +399,14 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) config_state++; // Advance when we have sent all of our ModuleConfig objects if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) { - // Clients sending special nonce don't want to see other nodeinfos - state = config_nonce == SPECIAL_NONCE ? STATE_SEND_FILEMANIFEST : STATE_SEND_OTHER_NODEINFOS; + // Handle special nonce behaviors: + // - SPECIAL_NONCE_ONLY_CONFIG: Skip node info, go directly to file manifest + // - SPECIAL_NONCE_ONLY_NODES: After sending nodes, skip to complete + if (config_nonce == SPECIAL_NONCE_ONLY_CONFIG) { + state = STATE_SEND_FILEMANIFEST; + } else { + state = STATE_SEND_OTHER_NODEINFOS; + } config_state = 0; } break; @@ -415,7 +432,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) case STATE_SEND_FILEMANIFEST: { LOG_DEBUG("FromRadio=STATE_SEND_FILEMANIFEST"); // last element - if (config_state == filesManifest.size()) { // also handles an empty filesManifest + if (config_state == filesManifest.size() || + config_nonce == SPECIAL_NONCE_ONLY_NODES) { // also handles an empty filesManifest config_state = 0; filesManifest.clear(); // Skip to complete packet diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 681b244c8..0d7772d17 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -18,7 +18,8 @@ #error "meshtastic_ToRadio_size is too large for our BLE packets" #endif -#define SPECIAL_NONCE 69420 +#define SPECIAL_NONCE_ONLY_CONFIG 69420 +#define SPECIAL_NONCE_ONLY_NODES 69421 // ( ͡° ͜ʖ ͡°) /** * Provides our protobuf based API which phone/PC clients can use to talk to our device From b9fcd9da233ad5b7438f2b836b612eba15b149ef Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 11 May 2025 18:08:29 -0500 Subject: [PATCH 155/238] Add some no-nonsense coercion for self-reporting node values (#6793) * Add some no-nonsense coercion for self-reporting node values * Update src/mesh/PhoneAPI.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mesh/PhoneAPI.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index db01e95f3..e2acd8463 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -565,9 +565,12 @@ 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 + bool isUs = nodeInfoForPhone.num == nodeDB->getNodeNum(); + nodeInfoForPhone.hops_away = isUs ? 0 : nodeInfoForPhone.hops_away; + nodeInfoForPhone.last_heard = isUs ? getValidTime(RTCQualityFromNet) : nodeInfoForPhone.last_heard; + nodeInfoForPhone.snr = isUs ? 0 : nodeInfoForPhone.snr; + nodeInfoForPhone.via_mqtt = isUs ? false : nodeInfoForPhone.via_mqtt; + nodeInfoForPhone.is_favorite = nodeInfoForPhone.is_favorite || isUs; // Our node is always a favorite } } return true; // Always say we have something, because we might need to advance our state machine From e1417cff2e8796b3c8c7af5988b7955ae59d9054 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 06:59:26 -0500 Subject: [PATCH 156/238] [create-pull-request] automated change (#6804) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/admin.pb.cpp | 3 +++ src/mesh/generated/meshtastic/admin.pb.h | 28 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/protobufs b/protobufs index 078ac8dfb..816595c8b 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 078ac8dfbe5f7533d7755cbe2ca3d08d86e5af34 +Subproject commit 816595c8bbdfc3b4388e11348ccd043294d58705 diff --git a/src/mesh/generated/meshtastic/admin.pb.cpp b/src/mesh/generated/meshtastic/admin.pb.cpp index 2e527f669..9bf40870f 100644 --- a/src/mesh/generated/meshtastic/admin.pb.cpp +++ b/src/mesh/generated/meshtastic/admin.pb.cpp @@ -15,6 +15,9 @@ PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO) PB_BIND(meshtastic_NodeRemoteHardwarePinsResponse, meshtastic_NodeRemoteHardwarePinsResponse, 2) +PB_BIND(meshtastic_SharedContact, meshtastic_SharedContact, AUTO) + + diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index efe60f493..09499b075 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -99,6 +99,14 @@ typedef struct _meshtastic_NodeRemoteHardwarePinsResponse { meshtastic_NodeRemoteHardwarePin node_remote_hardware_pins[16]; } meshtastic_NodeRemoteHardwarePinsResponse; +typedef struct _meshtastic_SharedContact { + /* The node number of the contact */ + uint32_t node_num; + /* The User of the contact */ + bool has_user; + meshtastic_User user; +} meshtastic_SharedContact; + typedef PB_BYTES_ARRAY_T(8) meshtastic_AdminMessage_session_passkey_t; /* This message is handled by the Admin module and is responsible for all settings/channel read/write operations. This message is used to do settings operations to both remote AND local nodes. @@ -202,6 +210,8 @@ typedef struct _meshtastic_AdminMessage { bool begin_edit_settings; /* Commits an open transaction for any edits made to config, module config, owner, and channel settings */ bool commit_edit_settings; + /* Add a contact (User) to the nodedb */ + meshtastic_SharedContact add_contact; /* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ int32_t factory_reset_device; /* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) @@ -252,13 +262,16 @@ extern "C" { + /* Initializer values for message structs */ #define meshtastic_AdminMessage_init_default {0, {0}, {0, {0}}} #define meshtastic_HamParameters_init_default {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} +#define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default} #define meshtastic_AdminMessage_init_zero {0, {0}, {0, {0}}} #define meshtastic_HamParameters_init_zero {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} +#define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_HamParameters_call_sign_tag 1 @@ -266,6 +279,8 @@ extern "C" { #define meshtastic_HamParameters_frequency_tag 3 #define meshtastic_HamParameters_short_name_tag 4 #define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag 1 +#define meshtastic_SharedContact_node_num_tag 1 +#define meshtastic_SharedContact_user_tag 2 #define meshtastic_AdminMessage_get_channel_request_tag 1 #define meshtastic_AdminMessage_get_channel_response_tag 2 #define meshtastic_AdminMessage_get_owner_request_tag 3 @@ -310,6 +325,7 @@ extern "C" { #define meshtastic_AdminMessage_remove_ignored_node_tag 48 #define meshtastic_AdminMessage_begin_edit_settings_tag 64 #define meshtastic_AdminMessage_commit_edit_settings_tag 65 +#define meshtastic_AdminMessage_add_contact_tag 66 #define meshtastic_AdminMessage_factory_reset_device_tag 94 #define meshtastic_AdminMessage_reboot_ota_seconds_tag 95 #define meshtastic_AdminMessage_exit_simulator_tag 96 @@ -365,6 +381,7 @@ X(a, STATIC, ONEOF, UINT32, (payload_variant,set_ignored_node,set_ignored X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_ignored_node,remove_ignored_node), 48) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \ X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \ @@ -390,6 +407,7 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101) #define meshtastic_AdminMessage_payload_variant_set_fixed_position_MSGTYPE meshtastic_Position #define meshtastic_AdminMessage_payload_variant_get_ui_config_response_MSGTYPE meshtastic_DeviceUIConfig #define meshtastic_AdminMessage_payload_variant_store_ui_config_MSGTYPE meshtastic_DeviceUIConfig +#define meshtastic_AdminMessage_payload_variant_add_contact_MSGTYPE meshtastic_SharedContact #define meshtastic_HamParameters_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, call_sign, 1) \ @@ -405,20 +423,30 @@ X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 1) #define meshtastic_NodeRemoteHardwarePinsResponse_DEFAULT NULL #define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin +#define meshtastic_SharedContact_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, node_num, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, user, 2) +#define meshtastic_SharedContact_CALLBACK NULL +#define meshtastic_SharedContact_DEFAULT NULL +#define meshtastic_SharedContact_user_MSGTYPE meshtastic_User + extern const pb_msgdesc_t meshtastic_AdminMessage_msg; extern const pb_msgdesc_t meshtastic_HamParameters_msg; extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg; +extern const pb_msgdesc_t meshtastic_SharedContact_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg #define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg #define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg +#define meshtastic_SharedContact_fields &meshtastic_SharedContact_msg /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size #define meshtastic_AdminMessage_size 511 #define meshtastic_HamParameters_size 31 #define meshtastic_NodeRemoteHardwarePinsResponse_size 496 +#define meshtastic_SharedContact_size 121 #ifdef __cplusplus } /* extern "C" */ From cc66f7c79ba976dc780cd2082258c6c5c4126fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 13 May 2025 14:15:52 +0200 Subject: [PATCH 157/238] Crowpanel 4.3, 5.0, 7.0 support (#6611) * SD software SPI control * fix notification crash; * allow wake on touch * don't build non-MUI variants * use pwm buzzer * Finalize support for Crowpanel TFT 2.4, 2.8 and 3.5 * add hardware ID for TFT panels * Add stubs for the bigger panels. WIP! * fix braces * elecrow 4.3, 5.0, 7.0 support * completed implementation 4.3, 5.0, 7.0 variants * NodeDB default config & simplified light sleep macros * trunk fmt * remove flags * removed leftovers (note: rtc gpios are only needed for deep sleep; the remove section caused issues with the elecrows) --------- Co-authored-by: mverch67 Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com> Co-authored-by: Austin --- boards/crowpanel.json | 4 +- src/graphics/ScreenFonts.h | 4 +- src/mesh/NodeDB.cpp | 4 +- src/sleep.cpp | 35 ++++--- variants/elecrow_panel/pins_arduino.h | 14 +-- variants/elecrow_panel/platformio.ini | 73 ++++++------- variants/elecrow_panel/variant.h | 141 ++++---------------------- variants/mesh-tab/variant.h | 3 +- variants/rak_wismeshtap/variant.h | 3 + variants/t-deck/variant.h | 1 + variants/t-watch-s3/variant.h | 2 + variants/unphone/variant.h | 3 + 12 files changed, 98 insertions(+), 189 deletions(-) diff --git a/boards/crowpanel.json b/boards/crowpanel.json index 570961ed7..75b097ef7 100644 --- a/boards/crowpanel.json +++ b/boards/crowpanel.json @@ -8,8 +8,8 @@ "core": "esp32", "extra_flags": [ "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_CDC_ON_BOOT=0", + "-DARDUINO_USB_MODE=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=0" ], diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index 0be0dc814..3373a47a7 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -65,8 +65,8 @@ #endif #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) || \ - defined(ILI9488_CS) && !defined(DISPLAY_FORCE_SMALL_FONTS) + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS)) && \ + !defined(DISPLAY_FORCE_SMALL_FONTS) // The screen is bigger so use bigger fonts #define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19 #define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28 diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 67f0da600..b64cb0fe1 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -584,7 +584,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32); #if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \ - defined(ELECROW)) && \ + defined(ELECROW_PANEL)) && \ HAS_TFT // switch BT off by default; use TFT programming mode or hotkey to enable config.bluetooth.enabled = false; @@ -689,7 +689,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) || defined(ELECROW) +#if defined(USE_POWERSAVE) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; diff --git a/src/sleep.cpp b/src/sleep.cpp index 2985db0c2..8ffb08b04 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -24,6 +24,7 @@ #include "mesh/wifi/WiFiAPClient.h" #endif #include "rom/rtc.h" +#include #include #include @@ -284,6 +285,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN pinMode(LORA_CS, OUTPUT); digitalWrite(LORA_CS, HIGH); gpio_hold_en((gpio_num_t)LORA_CS); +#elif defined(ELECROW_PANEL) + // Elecrow panels do not use LORA_CS, do nothing #else if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) { // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep @@ -400,7 +403,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef INPUTDRIVER_ENCODER_BTN gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL); #endif -#if defined(T_WATCH_S3) || defined(ELECROW) +#if defined(WAKE_ON_TOUCH) gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif enableLoraInterrupt(); @@ -433,11 +436,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r // Disable wake-on-button interrupt. Re-attach normal button-interrupts gpio_wakeup_disable(pin); #endif - -#if defined(T_WATCH_S3) || defined(ELECROW) +#if defined(INPUTDRIVER_ENCODER_BTN) + gpio_wakeup_disable((gpio_num_t)INPUTDRIVER_ENCODER_BTN); +#endif +#if defined(WAKE_ON_TOUCH) 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); @@ -506,23 +510,24 @@ bool shouldLoraWake(uint32_t msecToWake) void enableLoraInterrupt() { + esp_err_t res; #if SOC_PM_SUPPORT_EXT_WAKEUP && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) - gpio_pulldown_en((gpio_num_t)LORA_DIO1); + res = gpio_pulldown_en((gpio_num_t)LORA_DIO1); + if (res != ESP_OK) { + LOG_ERROR("gpio_pulldown_en(LORA_DIO1) result %d", res); + } #if defined(LORA_RESET) && (LORA_RESET != RADIOLIB_NC) - gpio_pullup_en((gpio_num_t)LORA_RESET); + res = gpio_pullup_en((gpio_num_t)LORA_RESET); + if (res != ESP_OK) { + LOG_ERROR("gpio_pullup_en(LORA_RESET) result %d", res); + } #endif -#if defined(LORA_CS) && (LORA_CS != RADIOLIB_NC) +#if defined(LORA_CS) && (LORA_CS != RADIOLIB_NC) && !defined(ELECROW_PANEL) gpio_pullup_en((gpio_num_t)LORA_CS); #endif - 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", 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", LORA_DIO1); - gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); - } + LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt", LORA_DIO1); + gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); #elif defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) if (radioType != RF95_RADIO) { diff --git a/variants/elecrow_panel/pins_arduino.h b/variants/elecrow_panel/pins_arduino.h index b98530378..81c9e0a2c 100644 --- a/variants/elecrow_panel/pins_arduino.h +++ b/variants/elecrow_panel/pins_arduino.h @@ -3,13 +3,11 @@ #include -// static const uint8_t LED_BUILTIN = -1; +static const uint8_t TX = 43; +static const uint8_t RX = 44; -// static const uint8_t TX = 43; -// static const uint8_t RX = 44; - -static const uint8_t SDA = 39; -static const uint8_t SCL = 40; +static const uint8_t SDA = 15; +static const uint8_t SCL = 16; // Default SPI will be mapped to Radio static const uint8_t SS = -1; @@ -17,13 +15,9 @@ static const uint8_t MOSI = 48; static const uint8_t MISO = 47; static const uint8_t SCK = 41; -#ifndef CROW_SELECT static const uint8_t SPI_MOSI = 6; static const uint8_t SPI_SCK = 5; static const uint8_t SPI_MISO = 4; -static const uint8_t SPI_CS = 7; // SD does not support -1 -static const uint8_t SDCARD_CS = SPI_CS; -#endif static const uint8_t A0 = 1; static const uint8_t A1 = 2; diff --git a/variants/elecrow_panel/platformio.ini b/variants/elecrow_panel/platformio.ini index 66dc35c3b..963174560 100644 --- a/variants/elecrow_panel/platformio.ini +++ b/variants/elecrow_panel/platformio.ini @@ -4,10 +4,8 @@ board = crowpanel board_check = true upload_protocol = esptool board_build.partitions = default_16MB.csv ; must be here for some reason, board.json is not enough !? - build_flags = ${esp32s3_base.build_flags} -Os -I variants/elecrow_panel - -D ELECROW -D ELECROW_PANEL -D CONFIG_ARDUHAL_LOG_COLORS -D RADIOLIB_DEBUG_SPI=0 @@ -22,15 +20,15 @@ build_flags = ${esp32s3_base.build_flags} -Os -D MESHTASTIC_EXCLUDE_SOCKETAPI=1 -D MESHTASTIC_EXCLUDE_SCREEN=1 -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 -; -D INPUTDRIVER_BUTTON_TYPE=0 -D HAS_TELEMETRY=0 -D CONFIG_DISABLE_HAL_LOCKS=1 + -D USE_PIN_BUZZER -D HAS_SCREEN=0 -D HAS_TFT=1 -D RAM_SIZE=6144 - -D LV_LVGL_H_INCLUDE_SIMPLE - -D LV_CONF_INCLUDE_SIMPLE - -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE -D LV_USE_SYSMON=0 -D LV_USE_PROFILER=0 -D LV_USE_PERF_MONITOR=0 @@ -40,29 +38,44 @@ build_flags = ${esp32s3_base.build_flags} -Os -D USE_LOG_DEBUG -D LOG_DEBUG_INC=\"DebugConfiguration.h\" -D USE_PACKET_API + -D HAS_SDCARD + -D SD_SPI_FREQUENCY=75000000 lib_deps = ${esp32s3_base.lib_deps} ${device-ui_base.lib_deps} - earlephilhower/ESP8266Audio@^1.9.9 - earlephilhower/ESP8266SAM@^1.0.1 - lovyan03/LovyanGFX@^1.2.0 - hideakitai/TCA9534@^0.1.1 + earlephilhower/ESP8266Audio@1.9.9 + earlephilhower/ESP8266SAM@1.0.1 + lovyan03/LovyanGFX@1.2.0 ; note: v1.2.7 breaks the elecrow 7" display functionality + hideakitai/TCA9534@0.1.1 -[env:elecrow-24-28-tft] +[crowpanel_small] ; 2.4, 2.8, 3.5 inch extends = crowpanel_base - build_flags = ${crowpanel_base.build_flags} - -D TFT_HEIGHT=320 ; needed in variant.h - -D HAS_SDCARD + -D CROW_SELECT=1 -D SDCARD_USE_SOFT_SPI + -D SDCARD_CS=7 -D SPI_DRIVER_SELECT=2 - -D USE_PIN_BUZZER -; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! - -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch -D LGFX_DRIVER_TEMPLATE -D LGFX_DRIVER=LGFX_GENERIC -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" + -D VIEW_320x240 + -D MAP_FULL_REDRAW + +[crowpanel_large] ; 4.3, 5.0, 7.0 inch +extends = crowpanel_base +build_flags = + ${crowpanel_base.build_flags} + -D CROW_SELECT=2 + -D SDCARD_CS=7 + -D LGFX_DRIVER=LGFX_ELECROW70 + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_ELECROW70.h\" + -D DISPLAY_SET_RESOLUTION + +[env:elecrow-adv-24-28-tft] +extends = crowpanel_small +build_flags = + ${crowpanel_small.build_flags} -D SPI_FREQUENCY=80000000 -D LGFX_SCREEN_WIDTH=240 -D LGFX_SCREEN_HEIGHT=320 @@ -81,25 +94,12 @@ build_flags = -D LGFX_TOUCH_INT=47 -D LGFX_TOUCH_RST=48 -D LGFX_TOUCH_ROTATION=0 - -D VIEW_320x240 - -D MAP_FULL_REDRAW - -[env:elecrow-35-tft] -extends = crowpanel_base +[env:elecrow-adv-35-tft] +extends = crowpanel_small build_flags = - ${crowpanel_base.build_flags} - -D TFT_HEIGHT=480 ; needed in variant.h - -D HAS_SDCARD - -D SDCARD_USE_SOFT_SPI - -D SPI_DRIVER_SELECT=2 - -D USE_PIN_BUZZER -; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! - -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch + ${crowpanel_small.build_flags} -D LV_CACHE_DEF_SIZE=2097152 - -D LGFX_DRIVER_TEMPLATE - -D LGFX_DRIVER=LGFX_GENERIC - -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" -D SPI_FREQUENCY=60000000 -D LGFX_SCREEN_WIDTH=320 -D LGFX_SCREEN_HEIGHT=480 @@ -119,5 +119,10 @@ build_flags = -D LGFX_TOUCH_RST=48 -D LGFX_TOUCH_ROTATION=0 -D DISPLAY_SET_RESOLUTION + +; 4.3, 5.0, 7.0 inch 800x480 IPS (V1) +[env:elecrow-adv1-43-50-70-tft] +extends = crowpanel_large +build_flags = + ${crowpanel_large.build_flags} -D VIEW_320x240 - -D MAP_FULL_REDRAW diff --git a/variants/elecrow_panel/variant.h b/variants/elecrow_panel/variant.h index b1035ed31..99069b723 100644 --- a/variants/elecrow_panel/variant.h +++ b/variants/elecrow_panel/variant.h @@ -1,124 +1,14 @@ #define I2C_SDA 15 #define I2C_SCL 16 -#if TFT_HEIGHT == 320 && not defined(HAS_TFT) // 2.4 and 2.8 TFT -// ST7789 TFT LCD -#define ST7789_CS 40 -#define ST7789_RS 41 // DC -#define ST7789_SDA 39 // MOSI -#define ST7789_SCK 42 -#define ST7789_RESET -1 -#define ST7789_MISO 38 -#define ST7789_BUSY -1 -#define ST7789_BL 38 -#define ST7789_SPI_HOST SPI2_HOST -#define TFT_BL 38 -#define SPI_FREQUENCY 60000000 -#define SPI_READ_FREQUENCY 16000000 -#define TFT_OFFSET_ROTATION 0 -#define SCREEN_ROTATE -#define TFT_DUMMY_READ_PIXELS 8 -#define SCREEN_TRANSITION_FRAMERATE 5 -#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness - -#define HAS_TOUCHSCREEN 1 +#if CROW_SELECT == 1 +#define WAKE_ON_TOUCH #define SCREEN_TOUCH_INT 47 -#define SCREEN_TOUCH_RST 48 -#define TOUCH_I2C_PORT 0 -#define TOUCH_SLAVE_ADDRESS 0x38 // FT5x06 +#define USE_POWERSAVE +#define SLEEP_TIME 180 #endif -#if TFT_HEIGHT == 480 && not defined(HAS_TFT) // 3.5 TFT -// ILI9488 TFT LCD -#define ILI9488_CS 40 -#define ILI9488_RS 41 // DC -#define ILI9488_SDA 39 // MOSI -#define ILI9488_SCK 42 -#define ILI9488_RESET -1 -#define ILI9488_MISO 38 -#define ILI9488_BUSY -1 -#define ILI9488_BL 38 -#define ILI9488_SPI_HOST SPI2_HOST -#define TFT_BL 38 -#define SPI_FREQUENCY 40000000 -#define SPI_READ_FREQUENCY 16000000 -#define TFT_OFFSET_ROTATION 0 -#define SCREEN_ROTATE -#define TFT_DUMMY_READ_PIXELS 8 -#define SCREEN_TRANSITION_FRAMERATE 5 -#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness - -#define HAS_TOUCHSCREEN 1 -#define SCREEN_TOUCH_INT 47 -#define SCREEN_TOUCH_RST 48 -#define TOUCH_I2C_PORT 0 -#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 -#endif - -#ifdef CROW_SELECT -#define ST72xx_DE 42 -#define ST72xx_VSYNC 41 -#define ST72xx_HSYNC 40 -#define ST72xx_PCLK 39 -#define ST72xx_R0 7 -#define ST72xx_R1 17 -#define ST72xx_R2 18 -#define ST72xx_R3 3 -#define ST72xx_R4 46 -#define ST72xx_G0 9 -#define ST72xx_G1 10 -#define ST72xx_G2 11 -#define ST72xx_G3 12 -#define ST72xx_G4 13 -#define ST72xx_G5 14 -#define ST72xx_B0 21 -#define ST72xx_B1 47 -#define ST72xx_B2 48 -#define ST72xx_B3 45 -#define ST72xx_B4 38 - -#define HAS_TOUCHSCREEN 1 -#define TOUCH_I2C_PORT 0 -#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 -#endif - -#if defined(CROW_SELECT) && CROW_SELECT == 1 // 4.3 TFT 800x480 -#define ST7265_HSYNC_POLARITY 0 -#define ST7265_HSYNC_FRONT_PORCH 24 -#define ST7265_HSYNC_PULSE_WIDTH 8 -#define ST7265_HSYNC_BACK_PORCH 24 -#define ST7265_VSYNC_POLARITY 1 -#define ST7265_VSYNC_FRONT_PORCH 24 -#define ST7265_VSYNC_PULSE_WIDTH 8 -#define ST7265_VSYNC_BACK_PORCH 24 -#define ST7265_PCLK_ACTIVE_NEG 1 -#endif - -#if defined(CROW_SELECT) && CROW_SELECT == 2 // 5.0 TFT 800x480 -#define ST7262_HSYNC_POLARITY 0 -#define ST7262_HSYNC_FRONT_PORCH 8 -#define ST7262_HSYNC_PULSE_WIDTH 4 -#define ST7262_HSYNC_BACK_PORCH 8 -#define ST7262_VSYNC_POLARITY 0 -#define ST7262_VSYNC_FRONT_PORCH 8 -#define ST7262_VSYNC_PULSE_WIDTH 4 -#define ST7262_VSYNC_BACK_PORCH 8 -#define ST7262_PCLK_ACTIVE_NEG 0 -#endif - -#if defined(CROW_SELECT) && CROW_SELECT == 3 // 7.0 TFT 800x480 -#define SC7277_HSYNC_POLARITY 0 -#define SC7277_HSYNC_FRONT_PORCH 8 -#define SC7277_HSYNC_PULSE_WIDTH 4 -#define SC7277_HSYNC_BACK_PORCH 8 -#define SC7277_VSYNC_POLARITY 0 -#define SC7277_VSYNC_FRONT_PORCH 8 -#define SC7277_VSYNC_PULSE_WIDTH 4 -#define SC7277_VSYNC_BACK_PORCH 8 -#define SC7277_PCLK_ACTIVE_NEG 0 -#endif - -#if TFT_HEIGHT == 320 // 2.4-2.8 have I2S audio +#if CROW_SELECT == 1 // dac / amp // #define HAS_I2S // didn't get I2S sound working #define PIN_BUZZER 8 // using pwm buzzer instead (nobody will notice, lol) @@ -131,10 +21,16 @@ #endif // GPS via UART1 connector -#define HAS_GPS 1 #define GPS_DEFAULT_NOT_PRESENT 1 +#define HAS_GPS 1 +#if CROW_SELECT == 1 #define GPS_RX_PIN 18 #define GPS_TX_PIN 17 +#else +// GPIOs shared with LoRa or MIC module +#define GPS_RX_PIN 19 +#define GPS_TX_PIN 20 +#endif // Extension Slot Layout, viewed from above (2.4-3.5) // DIO1/IO1 o o IO2/NRESET @@ -158,9 +54,11 @@ // LoRa #define USE_SX1262 -#define LORA_CS 0 // GND -#if TFT_HEIGHT == 320 || TFT_HEIGHT == 480 // 2.4 - 3.5 TFT +#if CROW_SELECT == 1 +// 2.4", 2.8, 3.5""" +#define HW_SPI1_DEVICE +#define LORA_CS 0 #define LORA_SCK 10 #define LORA_MISO 9 #define LORA_MOSI 3 @@ -173,6 +71,8 @@ #define SENSOR_POWER_CTRL_PIN 45 #define SENSOR_POWER_ON LOW #else +// 4.3", 5.0", 7.0" +#define LORA_CS 0 #define LORA_SCK 5 #define LORA_MISO 4 #define LORA_MOSI 6 @@ -182,14 +82,9 @@ #define LORA_DIO2 2 // SX1262 BUSY #endif -#define HW_SPI1_DEVICE #define SX126X_CS LORA_CS #define SX126X_DIO1 LORA_DIO1 #define SX126X_BUSY LORA_DIO2 #define SX126X_RESET LORA_RESET #define SX126X_DIO2_AS_RF_SWITCH - #define SX126X_DIO3_TCXO_VOLTAGE 3.3 - -#define USE_VIRTUAL_KEYBOARD 1 -#define DISPLAY_CLOCK_FRAME 1 \ No newline at end of file diff --git a/variants/mesh-tab/variant.h b/variants/mesh-tab/variant.h index 533c931bc..63ef17d85 100644 --- a/variants/mesh-tab/variant.h +++ b/variants/mesh-tab/variant.h @@ -3,7 +3,8 @@ #define HAS_TOUCHSCREEN 1 -#define SLEEP_TIME 120 +#define USE_POWERSAVE +#define SLEEP_TIME 180 // Analog pins #define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage diff --git a/variants/rak_wismeshtap/variant.h b/variants/rak_wismeshtap/variant.h index c21a11ac1..1980dc4a1 100644 --- a/variants/rak_wismeshtap/variant.h +++ b/variants/rak_wismeshtap/variant.h @@ -305,6 +305,9 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG #define HAS_TOUCHSCREEN 1 #define SCREEN_TOUCH_INT WB_IO6 +#define USE_POWERSAVE +#define SLEEP_TIME 120 + #define CANNED_MESSAGE_MODULE_ENABLE 1 #define USE_VIRTUAL_KEYBOARD 1 /*---------------------------------------------------------------------------- diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 5b2c13a91..a21c786b3 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -31,6 +31,7 @@ #define TOUCH_I2C_PORT 0 #define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#define USE_POWERSAVE #define SLEEP_TIME 120 #ifndef HAS_TFT diff --git a/variants/t-watch-s3/variant.h b/variants/t-watch-s3/variant.h index 5a6aebfa2..578c23c0a 100644 --- a/variants/t-watch-s3/variant.h +++ b/variants/t-watch-s3/variant.h @@ -24,7 +24,9 @@ #define SCREEN_TOUCH_USE_I2C1 #define TOUCH_I2C_PORT 1 #define TOUCH_SLAVE_ADDRESS 0x38 +#define WAKE_ON_TOUCH +#define USE_POWERSAVE #define SLEEP_TIME 180 #define I2C_SDA1 39 // Used for capacitive touch diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h index 7b39a5aa5..eaf142721 100644 --- a/variants/unphone/variant.h +++ b/variants/unphone/variant.h @@ -41,6 +41,9 @@ #define USE_XPT2046 1 #define TOUCH_CS 38 +#define USE_POWERSAVE +#define SLEEP_TIME 180 + #define HAS_GPS \ 0 // the unphone doesn't have a gps module by default (though // GPS featherwing -- https://www.adafruit.com/product/3133 From a7415791a56cca7816c52ee7cda74e532dcccd11 Mon Sep 17 00:00:00 2001 From: Chris Vogel Date: Tue, 13 May 2025 15:10:57 +0200 Subject: [PATCH 158/238] device-install.sh: detect t-eth-elite as s3 device (#6767) device-install.sh: detect t-eth-elite as s3 device fixes https://github.com/meshtastic/firmware/issues/6754#issuecomment-2857468902 Thanks @mverch67! --- bin/device-install.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bin/device-install.sh b/bin/device-install.sh index a43ccbdb4..7fa5ffdbb 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -43,6 +43,16 @@ S3_VARIANTS=( "wireless-tracker" "station-g2" "unphone" + "t-eth-elite" + "mesh-tab" + "dreamcatcher" + "ESP32-S3-Pico" + "seeed-sensecap-indicator" + "heltec_capsule_sensor_v3" + "vision-master" + "icarus" + "tracksenger" + "elecrow-adv" ) # Determine the correct esptool command to use From 0a8bd1e4bee9b24f9a41203f9490fe1ac4390f3f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 05:33:51 -0500 Subject: [PATCH 159/238] Add contact admin message (for QR code) (#6806) --- src/mesh/NodeDB.cpp | 20 ++++++++++++++++++++ src/mesh/NodeDB.h | 2 ++ src/modules/AdminModule.cpp | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index b64cb0fe1..0495fa7aa 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1455,6 +1455,26 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS notifyObservers(true); // Force an update whether or not our node counts have changed } +/** + * Update the node database with a new contact + */ +void NodeDB::addFromContact(meshtastic_SharedContact contact) +{ + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(contact.node_num); + if (!info) { + return; + } + info->num = contact.node_num; + info->last_heard = getValidTime(RTCQualityNTP); + info->has_user = true; + info->user = TypeConversions::ConvertToUserLite(contact.user); + info->is_favorite = true; + updateGUIforNode = info; + powerFSM.trigger(EVENT_NODEDB_UPDATED); + notifyObservers(true); // Force an update whether or not our node counts have changed + saveNodeDatabaseToDisk(); +} + /** Update user info and channel for this node based on received user data */ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelIndex) diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 291c3804b..4dbda6a9f 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -110,6 +110,8 @@ class NodeDB /// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw void updateFrom(const meshtastic_MeshPacket &p); + void addFromContact(const meshtastic_SharedContact); + /** Update position info for this node based on received position data */ void updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src = RX_SRC_RADIO); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 0e1e1555b..cbf82ae73 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -286,6 +286,11 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta nodeDB->removeNodeByNum(r->remove_by_nodenum); break; } + case meshtastic_AdminMessage_add_contact_tag: { + LOG_INFO("Client received add_contact command"); + nodeDB->addFromContact(r->add_contact); + break; + } case meshtastic_AdminMessage_set_favorite_node_tag: { LOG_INFO("Client received set_favorite_node command"); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->set_favorite_node); From d9ad2322e8898ff5d9454b2ab3ef1f23a2d32005 Mon Sep 17 00:00:00 2001 From: Richard Zhang <129845637+Richard3366@users.noreply.github.com> Date: Wed, 14 May 2025 19:29:05 +0800 Subject: [PATCH 160/238] Fixes BUG #6243 Heltec Tracker (#6781) * fix wireless tracker screen issues * fix SHTC3 BUG * Remove the 32K crystal oscillator option for the Wireless Paper and Vision Master series. * Correct spelling errors * Update src/graphics/Screen.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Ben Meadors Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/graphics/Screen.cpp | 10 ++++++++++ src/modules/Telemetry/Sensor/SHTC3Sensor.cpp | 2 +- variants/heltec_vision_master_e213/variant.h | 1 - variants/heltec_vision_master_e290/variant.h | 1 - variants/heltec_vision_master_t190/variant.h | 1 - variants/heltec_wireless_paper/variant.h | 1 - variants/heltec_wireless_paper_v1/variant.h | 1 - 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 1ee0c0fdd..4f73c79be 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1612,6 +1612,9 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) #ifdef T_WATCH_S3 PMU->enablePowerOutput(XPOWERS_ALDO2); #endif +#ifdef HELTEC_TRACKER_V1_X + uint8_t tft_vext_enabled=digitalRead(VEXT_ENABLE); +#endif #if !ARCH_PORTDUINO dispdev->displayOn(); #endif @@ -1622,6 +1625,13 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) #endif dispdev->displayOn(); +#ifdef HELTEC_TRACKER_V1_X + // If the TFT VEXT power is not enabled, initialize the UI. + if(!tft_vext_enabled) + { + ui->init(); + } +#endif #ifdef USE_ST7789 pinMode(VTFT_CTRL, OUTPUT); digitalWrite(VTFT_CTRL, LOW); diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp index dbebec9d3..e9c4d2a0b 100644 --- a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp +++ b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp @@ -15,7 +15,7 @@ int32_t SHTC3Sensor::runOnce() if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - status = shtc3.begin(); + status = shtc3.begin(nodeTelemetrySensorsMap[sensorType].second); return initI2CSensor(); } diff --git a/variants/heltec_vision_master_e213/variant.h b/variants/heltec_vision_master_e213/variant.h index 49b8e91f5..ebb2c341f 100644 --- a/variants/heltec_vision_master_e213/variant.h +++ b/variants/heltec_vision_master_e213/variant.h @@ -31,7 +31,6 @@ #define ADC_CHANNEL ADC1_GPIO7_CHANNEL #define ADC_MULTIPLIER 4.9 * 1.03 #define ADC_ATTENUATION ADC_ATTEN_DB_2_5 -#define HAS_32768HZ // LoRa #define USE_SX1262 diff --git a/variants/heltec_vision_master_e290/variant.h b/variants/heltec_vision_master_e290/variant.h index 9d6041539..02986d26b 100644 --- a/variants/heltec_vision_master_e290/variant.h +++ b/variants/heltec_vision_master_e290/variant.h @@ -30,7 +30,6 @@ #define ADC_CHANNEL ADC1_GPIO7_CHANNEL #define ADC_MULTIPLIER 4.9 * 1.03 #define ADC_ATTENUATION ADC_ATTEN_DB_2_5 -#define HAS_32768HZ // LoRa #define USE_SX1262 diff --git a/variants/heltec_vision_master_t190/variant.h b/variants/heltec_vision_master_t190/variant.h index 1da3f9971..788466919 100644 --- a/variants/heltec_vision_master_t190/variant.h +++ b/variants/heltec_vision_master_t190/variant.h @@ -47,7 +47,6 @@ #define ADC_CHANNEL ADC1_GPIO6_CHANNEL #define ADC_MULTIPLIER 4.9 * 1.03 // Voltage divider is roughly 1:1 #define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // Voltage divider output is quite high -#define HAS_32768HZ // LoRa #define USE_SX1262 diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h index 0385945e6..bbfd54ada 100644 --- a/variants/heltec_wireless_paper/variant.h +++ b/variants/heltec_wireless_paper/variant.h @@ -28,7 +28,6 @@ #define ADC_MULTIPLIER 2 // Voltage divider is roughly 1:1 #define BAT_MEASURE_ADC_UNIT 2 // Use ADC2 #define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high -#define HAS_32768HZ #define ADC_CTRL_ENABLED LOW #define NO_EXT_GPIO 1 diff --git a/variants/heltec_wireless_paper_v1/variant.h b/variants/heltec_wireless_paper_v1/variant.h index fe8f391df..4505395c9 100644 --- a/variants/heltec_wireless_paper_v1/variant.h +++ b/variants/heltec_wireless_paper_v1/variant.h @@ -29,7 +29,6 @@ #define ADC_MULTIPLIER 2 // Voltage divider is roughly 1:1 #define BAT_MEASURE_ADC_UNIT 2 // Use ADC2 #define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high -#define HAS_32768HZ #define ADC_CTRL_ENABLED LOW #define NO_EXT_GPIO 1 From 94af3bd1ab8eb94d2aaa9be3e510b591768b0623 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 06:31:18 -0500 Subject: [PATCH 161/238] Formatting --- src/graphics/Screen.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 4f73c79be..61999ee79 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1613,7 +1613,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) PMU->enablePowerOutput(XPOWERS_ALDO2); #endif #ifdef HELTEC_TRACKER_V1_X - uint8_t tft_vext_enabled=digitalRead(VEXT_ENABLE); + uint8_t tft_vext_enabled = digitalRead(VEXT_ENABLE); #endif #if !ARCH_PORTDUINO dispdev->displayOn(); @@ -1627,9 +1627,8 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) dispdev->displayOn(); #ifdef HELTEC_TRACKER_V1_X // If the TFT VEXT power is not enabled, initialize the UI. - if(!tft_vext_enabled) - { - ui->init(); + if (!tft_vext_enabled) { + ui->init(); } #endif #ifdef USE_ST7789 From b1955c34aa80dd7e2ed9e08a7e17b1bd532f793b Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Wed, 14 May 2025 04:32:24 -0700 Subject: [PATCH 162/238] Update Seeed Solar Node (#6763) * Update Seeed Solar Node * Update Seeed Solar Node * updates * updates * updates --------- Co-authored-by: Ben Meadors --- boards/{Seeed_Solar_Node.json => seeed_solar_node.json} | 4 ++-- .../{Seeed_Solar_Node => seeed_solar_node}/platformio.ini | 8 ++++---- .../{Seeed_Solar_Node => seeed_solar_node}/variant.cpp | 0 variants/{Seeed_Solar_Node => seeed_solar_node}/variant.h | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename boards/{Seeed_Solar_Node.json => seeed_solar_node.json} (94%) rename variants/{Seeed_Solar_Node => seeed_solar_node}/platformio.ini (76%) rename variants/{Seeed_Solar_Node => seeed_solar_node}/variant.cpp (100%) rename variants/{Seeed_Solar_Node => seeed_solar_node}/variant.h (100%) diff --git a/boards/Seeed_Solar_Node.json b/boards/seeed_solar_node.json similarity index 94% rename from boards/Seeed_Solar_Node.json rename to boards/seeed_solar_node.json index e1b502cfa..e77fbd077 100644 --- a/boards/Seeed_Solar_Node.json +++ b/boards/seeed_solar_node.json @@ -10,7 +10,7 @@ "hwids": [["0x2886", "0x0059"]], "usb_product": "XIAO-BOOT", "mcu": "nrf52840", - "variant": "Seeed_Solar_Node", + "variant": "seeed_solar_node", "bsp": { "name": "adafruit" }, @@ -31,7 +31,7 @@ "openocd_target": "nrf52840-mdk-rs" }, "frameworks": ["arduino"], - "name": "Seeed_Solar_Node", + "name": "seeed_solar_node", "upload": { "maximum_ram_size": 248832, "maximum_size": 815104, diff --git a/variants/Seeed_Solar_Node/platformio.ini b/variants/seeed_solar_node/platformio.ini similarity index 76% rename from variants/Seeed_Solar_Node/platformio.ini rename to variants/seeed_solar_node/platformio.ini index 5ee0a5e8f..eb91a435f 100644 --- a/variants/Seeed_Solar_Node/platformio.ini +++ b/variants/seeed_solar_node/platformio.ini @@ -1,13 +1,13 @@ -[env:Seeed_Solar_Node] -board = Seeed_Solar_Node +[env:seeed_solar_node] +board = seeed_solar_node extends = nrf52840_base ;board_level = extra build_flags = ${nrf52840_base.build_flags} - -I $PROJECT_DIR/variants/Seeed_Solar_Node + -I $PROJECT_DIR/variants/seeed_solar_node -D SEEED_SOLAR_NODE -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld -build_src_filter = ${nrf52_base.build_src_filter} +<../variants/Seeed_Solar_Node> +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/seeed_solar_node> lib_deps = ${nrf52840_base.lib_deps} debug_tool = jlink diff --git a/variants/Seeed_Solar_Node/variant.cpp b/variants/seeed_solar_node/variant.cpp similarity index 100% rename from variants/Seeed_Solar_Node/variant.cpp rename to variants/seeed_solar_node/variant.cpp diff --git a/variants/Seeed_Solar_Node/variant.h b/variants/seeed_solar_node/variant.h similarity index 100% rename from variants/Seeed_Solar_Node/variant.h rename to variants/seeed_solar_node/variant.h From feafd2bc0c94a6e85077543c20a5a626e1e7eea6 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Wed, 14 May 2025 23:33:51 +1200 Subject: [PATCH 163/238] Protect T-Echo's touch button against phantom presses in OLED UI (#6735) * Guard T-Echo touch button during LoRa TX * Guard for T-Echo only --------- Co-authored-by: Ben Meadors --- src/ButtonThread.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 352885dbe..8db52c074 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -300,14 +300,23 @@ int32_t ButtonThread::runOnce() #ifdef BUTTON_PIN_TOUCH case BUTTON_EVENT_TOUCH_LONG_PRESSED: { LOG_BUTTON("Touch press!"); - if (screen) { - // Wake if asleep - if (powerFSM.getState() == &stateDARK) - powerFSM.trigger(EVENT_PRESS); + // Ignore if: no screen + if (!screen) + break; - // Update display (legacy behaviour) - screen->forceDisplay(); - } +#ifdef TTGO_T_ECHO + // Ignore if: TX in progress + // Uncommon T-Echo hardware bug, LoRa TX triggers touch button + if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending()) + break; +#endif + + // Wake if asleep + if (powerFSM.getState() == &stateDARK) + powerFSM.trigger(EVENT_PRESS); + + // Update display (legacy behaviour) + screen->forceDisplay(); break; } #endif // BUTTON_PIN_TOUCH From f16402dec152df25c35c953186418321e8bb26bb Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 14 May 2025 14:39:46 -0400 Subject: [PATCH 164/238] MQTT userprefs (#6802) --- src/mesh/Channels.cpp | 2 +- src/mesh/Default.h | 2 ++ src/mesh/NodeDB.cpp | 30 +++++++++++++++++++++++++++++- src/mqtt/MQTT.cpp | 7 +++++++ src/mqtt/MQTT.h | 2 ++ userPrefs.jsonc | 7 +++++++ 6 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 2ba3499f1..70e4127d8 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -347,7 +347,7 @@ bool Channels::anyMqttEnabled() { #if USERPREFS_EVENT_MODE && !MESHTASTIC_EXCLUDE_MQTT // Don't publish messages on the public MQTT broker if we are in event mode - if (mqtt && mqtt->isUsingDefaultServer()) { + if (mqtt && mqtt->isUsingDefaultServer() && mqtt->isUsingDefaultRootTopic()) { return false; } #endif diff --git a/src/mesh/Default.h b/src/mesh/Default.h index 0daccbb6f..bc2aa785f 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -26,6 +26,8 @@ #define default_mqtt_username "meshdev" #define default_mqtt_password "large4cats" #define default_mqtt_root "msh" +#define default_mqtt_encryption_enabled true +#define default_mqtt_tls_enabled false #define IF_ROUTER(routerVal, normalVal) \ ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) ? (routerVal) : (normalVal)) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 0495fa7aa..f22f7bf91 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -761,11 +761,39 @@ void NodeDB::installDefaultModuleConfig() moduleConfig.has_canned_message = true; +#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT + moduleConfig.mqtt.enabled = true; +#endif +#ifdef USERPREFS_MQTT_ADDRESS + strncpy(moduleConfig.mqtt.address, USERPREFS_MQTT_ADDRESS, sizeof(moduleConfig.mqtt.address)); +#else strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(moduleConfig.mqtt.address)); +#endif +#ifdef USERPREFS_MQTT_USERNAME + strncpy(moduleConfig.mqtt.username, USERPREFS_MQTT_USERNAME, sizeof(moduleConfig.mqtt.username)); +#else strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username)); +#endif +#ifdef USERPREFS_MQTT_PASSWORD + strncpy(moduleConfig.mqtt.password, USERPREFS_MQTT_PASSWORD, sizeof(moduleConfig.mqtt.password)); +#else strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password)); +#endif +#ifdef USERPREFS_MQTT_ROOT_TOPIC + strncpy(moduleConfig.mqtt.root, USERPREFS_MQTT_ROOT_TOPIC, sizeof(moduleConfig.mqtt.root)); +#else strncpy(moduleConfig.mqtt.root, default_mqtt_root, sizeof(moduleConfig.mqtt.root)); - moduleConfig.mqtt.encryption_enabled = true; +#endif +#ifdef USERPREFS_MQTT_ENCRYPTION_ENABLED + moduleConfig.mqtt.encryption_enabled = USERPREFS_MQTT_ENCRYPTION_ENABLED; +#else + moduleConfig.mqtt.encryption_enabled = default_mqtt_encryption_enabled; +#endif +#ifdef USERPREFS_MQTT_TLS_ENABLED + moduleConfig.mqtt.tls_enabled = USERPREFS_MQTT_TLS_ENABLED; +#else + moduleConfig.mqtt.tls_enabled = default_mqtt_tls_enabled; +#endif moduleConfig.has_neighbor_info = true; moduleConfig.neighbor_info.enabled = false; diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index fb92789ee..3776f59f5 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -256,6 +256,11 @@ bool isDefaultServer(const String &host) return host.length() == 0 || host == default_mqtt_address; } +bool isDefaultRootTopic(const String &root) +{ + return root.length() == 0 || root == default_mqtt_root; +} + struct PubSubConfig { explicit PubSubConfig(const meshtastic_ModuleConfig_MQTTConfig &config) { @@ -387,10 +392,12 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE) cryptTopic = moduleConfig.mqtt.root + cryptTopic; jsonTopic = moduleConfig.mqtt.root + jsonTopic; mapTopic = moduleConfig.mqtt.root + mapTopic; + isConfiguredForDefaultRootTopic = isDefaultRootTopic(moduleConfig.mqtt.root); } else { cryptTopic = "msh" + cryptTopic; jsonTopic = "msh" + jsonTopic; mapTopic = "msh" + mapTopic; + isConfiguredForDefaultRootTopic = true; } if (moduleConfig.mqtt.map_reporting_enabled && moduleConfig.mqtt.has_map_report_settings) { diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 0c260dc9c..2b11f479d 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -58,6 +58,7 @@ class MQTT : private concurrency::OSThread void start() { setIntervalFromNow(0); }; bool isUsingDefaultServer() { return isConfiguredForDefaultServer; } + bool isUsingDefaultRootTopic() { return isConfiguredForDefaultRootTopic; } /// Validate the meshtastic_ModuleConfig_MQTTConfig. static bool isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config) { return isValidConfig(config, nullptr); } @@ -71,6 +72,7 @@ class MQTT : private concurrency::OSThread int reconnectCount = 0; bool isConfiguredForDefaultServer = true; + bool isConfiguredForDefaultRootTopic = true; virtual int32_t runOnce() override; diff --git a/userPrefs.jsonc b/userPrefs.jsonc index 06c4a7eec..a349a5700 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -44,5 +44,12 @@ // "USERPREFS_NETWORK_WIFI_ENABLED": "true", // "USERPREFS_NETWORK_WIFI_SSID": "wifi_ssid", // "USERPREFS_NETWORK_WIFI_PSK": "wifi_psk", + // "USERPREFS_MQTT_ENABLED": "1", + // "USERPREFS_MQTT_ADDRESS": "'mqtt.meshtastic.org'", + // "USERPREFS_MQTT_USERNAME": "meshdev", + // "USERPREFS_MQTT_PASSWORD": "large4cats", + // "USERPREFS_MQTT_ENCRYPTION_ENABLED": "true", + // "USERPREFS_MQTT_TLS_ENABLED": "false", + // "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME", "USERPREFS_TZ_STRING": "tzplaceholder " } From bc313da064abee20474a8e078d865ffd18658916 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 13:48:14 -0500 Subject: [PATCH 165/238] [create-pull-request] automated change (#6810) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/admin.pb.h | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 19 ++++++++++++------- src/mesh/generated/meshtastic/mesh.pb.h | 15 ++++++++++----- src/mesh/generated/meshtastic/telemetry.pb.h | 8 +++++--- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/protobufs b/protobufs index 816595c8b..8cb3e62a0 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 816595c8bbdfc3b4388e11348ccd043294d58705 +Subproject commit 8cb3e62a0d35d470e3d5d9950c0f1d85ccb35b22 diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 09499b075..0a46e6275 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -446,7 +446,7 @@ extern const pb_msgdesc_t meshtastic_SharedContact_msg; #define meshtastic_AdminMessage_size 511 #define meshtastic_HamParameters_size 31 #define meshtastic_NodeRemoteHardwarePinsResponse_size 496 -#define meshtastic_SharedContact_size 121 +#define meshtastic_SharedContact_size 123 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 83563a9fc..5e92cacd0 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -58,6 +58,9 @@ typedef struct _meshtastic_UserLite { /* The public key of the user's device. This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ meshtastic_UserLite_public_key_t public_key; + /* Whether or not the node can be messaged */ + bool has_is_unmessagable; + bool is_unmessagable; } meshtastic_UserLite; typedef struct _meshtastic_NodeInfoLite { @@ -183,14 +186,14 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} -#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 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}} #define meshtastic_NodeDatabase_init_default {0, {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_BackupPreferences_init_default {0, 0, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default, false, meshtastic_ChannelFile_init_default, false, meshtastic_User_init_default} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} -#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 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}} #define meshtastic_NodeDatabase_init_zero {0, {0}} @@ -210,6 +213,7 @@ extern "C" { #define meshtastic_UserLite_is_licensed_tag 5 #define meshtastic_UserLite_role_tag 6 #define meshtastic_UserLite_public_key_tag 7 +#define meshtastic_UserLite_is_unmessagable_tag 9 #define meshtastic_NodeInfoLite_num_tag 1 #define meshtastic_NodeInfoLite_user_tag 2 #define meshtastic_NodeInfoLite_position_tag 3 @@ -259,7 +263,8 @@ X(a, STATIC, SINGULAR, STRING, short_name, 3) \ X(a, STATIC, SINGULAR, UENUM, hw_model, 4) \ X(a, STATIC, SINGULAR, BOOL, is_licensed, 5) \ X(a, STATIC, SINGULAR, UENUM, role, 6) \ -X(a, STATIC, SINGULAR, BYTES, public_key, 7) +X(a, STATIC, SINGULAR, BYTES, public_key, 7) \ +X(a, STATIC, OPTIONAL, BOOL, is_unmessagable, 9) #define meshtastic_UserLite_CALLBACK NULL #define meshtastic_UserLite_DEFAULT NULL @@ -350,12 +355,12 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2263 +#define meshtastic_BackupPreferences_size 2265 #define meshtastic_ChannelFile_size 718 -#define meshtastic_DeviceState_size 1720 -#define meshtastic_NodeInfoLite_size 188 +#define meshtastic_DeviceState_size 1722 +#define meshtastic_NodeInfoLite_size 190 #define meshtastic_PositionLite_size 28 -#define meshtastic_UserLite_size 96 +#define meshtastic_UserLite_size 98 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 6fa0b60b0..572a6f5d5 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -609,6 +609,9 @@ typedef struct _meshtastic_User { /* The public key of the user's device. This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ meshtastic_User_public_key_t public_key; + /* Whether or not the node can be messaged */ + bool has_is_unmessagable; + bool is_unmessagable; } meshtastic_User; /* A message used in a traceroute */ @@ -1204,7 +1207,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_Position_init_default {false, 0, false, 0, false, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, false, 0, false, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} @@ -1229,7 +1232,7 @@ extern "C" { #define meshtastic_resend_chunks_init_default {{{NULL}, NULL}} #define meshtastic_ChunkedPayloadResponse_init_default {0, 0, {0}} #define meshtastic_Position_init_zero {false, 0, false, 0, false, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, false, 0, false, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} @@ -1286,6 +1289,7 @@ extern "C" { #define meshtastic_User_is_licensed_tag 6 #define meshtastic_User_role_tag 7 #define meshtastic_User_public_key_tag 8 +#define meshtastic_User_is_unmessagable_tag 9 #define meshtastic_RouteDiscovery_route_tag 1 #define meshtastic_RouteDiscovery_snr_towards_tag 2 #define meshtastic_RouteDiscovery_route_back_tag 3 @@ -1457,7 +1461,8 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \ X(a, STATIC, SINGULAR, UENUM, hw_model, 5) \ X(a, STATIC, SINGULAR, BOOL, is_licensed, 6) \ X(a, STATIC, SINGULAR, UENUM, role, 7) \ -X(a, STATIC, SINGULAR, BYTES, public_key, 8) +X(a, STATIC, SINGULAR, BYTES, public_key, 8) \ +X(a, STATIC, OPTIONAL, BOOL, is_unmessagable, 9) #define meshtastic_User_CALLBACK NULL #define meshtastic_User_DEFAULT NULL @@ -1786,14 +1791,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_MyNodeInfo_size 77 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 319 +#define meshtastic_NodeInfo_size 321 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 #define meshtastic_ToRadio_size 504 -#define meshtastic_User_size 113 +#define meshtastic_User_size 115 #define meshtastic_Waypoint_size 165 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index dcc511ea6..be3fa0907 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -87,7 +87,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* Infineon DPS310 High accuracy pressure and temperature */ meshtastic_TelemetrySensorType_DPS310 = 36, /* RAKWireless RAK12035 Soil Moisture Sensor Module */ - meshtastic_TelemetrySensorType_RAK12035 = 37 + meshtastic_TelemetrySensorType_RAK12035 = 37, + /* MAX17261 lipo battery gauge */ + meshtastic_TelemetrySensorType_MAX17261 = 38 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -324,8 +326,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RAK12035 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RAK12035+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17261 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17261+1)) From 1af4a0bdc9ab66081a6ccb5e1444e1d15b807083 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 14:10:45 -0500 Subject: [PATCH 166/238] Upgrade trunk (#6797) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index ca38c978a..4aa5527be 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,13 +10,13 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.28 + - trufflehog@3.88.29 - yamllint@1.37.1 - bandit@1.8.3 - terrascan@1.19.9 - trivy@0.62.1 - taplo@0.9.3 - - ruff@0.11.8 + - ruff@0.11.9 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.5 @@ -28,7 +28,7 @@ lint: - shellcheck@0.10.0 - black@25.1.0 - git-diff-check - - gitleaks@8.25.1 + - gitleaks@8.26.0 - clang-format@16.0.3 ignore: - linters: [ALL] From a51a6b8c475cdd654dc3c12ccff33340be6709cd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 14:41:37 -0500 Subject: [PATCH 167/238] [create-pull-request] automated change (#6812) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 16 ++++++++++------ src/mesh/generated/meshtastic/mqtt.pb.h | 13 +++++++++---- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/protobufs b/protobufs index 8cb3e62a0..47ec99aa4 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 8cb3e62a0d35d470e3d5d9950c0f1d85ccb35b22 +Subproject commit 47ec99aa4c4a2e3fff71fd5170663f0848deb021 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 5e92cacd0..d29fb17a7 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -355,7 +355,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2265 +#define meshtastic_BackupPreferences_size 2267 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1722 #define meshtastic_NodeInfoLite_size 190 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 6a59b8eb0..53d8d7d80 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -188,7 +188,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_LocalConfig_size #define meshtastic_LocalConfig_size 743 -#define meshtastic_LocalModuleConfig_size 667 +#define meshtastic_LocalModuleConfig_size 669 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index dbf6ddb2e..e8ae48072 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -112,6 +112,8 @@ typedef struct _meshtastic_ModuleConfig_MapReportSettings { uint32_t publish_interval_secs; /* Bits of precision for the location sent (default of 32 is full precision). */ uint32_t position_precision; + /* Whether we have opted-in to report our location to the map */ + bool should_report_location; } meshtastic_ModuleConfig_MapReportSettings; /* MQTT Client Config */ @@ -505,7 +507,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}} #define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_default} -#define meshtastic_ModuleConfig_MapReportSettings_init_default {0, 0} +#define meshtastic_ModuleConfig_MapReportSettings_init_default {0, 0, 0} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}} #define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0, 0} #define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0} @@ -521,7 +523,7 @@ extern "C" { #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_zero} -#define meshtastic_ModuleConfig_MapReportSettings_init_zero {0, 0} +#define meshtastic_ModuleConfig_MapReportSettings_init_zero {0, 0, 0} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}} #define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0, 0} #define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0} @@ -539,6 +541,7 @@ extern "C" { /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_ModuleConfig_MapReportSettings_publish_interval_secs_tag 1 #define meshtastic_ModuleConfig_MapReportSettings_position_precision_tag 2 +#define meshtastic_ModuleConfig_MapReportSettings_should_report_location_tag 3 #define meshtastic_ModuleConfig_MQTTConfig_enabled_tag 1 #define meshtastic_ModuleConfig_MQTTConfig_address_tag 2 #define meshtastic_ModuleConfig_MQTTConfig_username_tag 3 @@ -702,7 +705,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, map_report_settings, 11) #define meshtastic_ModuleConfig_MapReportSettings_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, publish_interval_secs, 1) \ -X(a, STATIC, SINGULAR, UINT32, position_precision, 2) +X(a, STATIC, SINGULAR, UINT32, position_precision, 2) \ +X(a, STATIC, SINGULAR, BOOL, should_report_location, 3) #define meshtastic_ModuleConfig_MapReportSettings_CALLBACK NULL #define meshtastic_ModuleConfig_MapReportSettings_DEFAULT NULL @@ -890,8 +894,8 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_CannedMessageConfig_size 49 #define meshtastic_ModuleConfig_DetectionSensorConfig_size 44 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 42 -#define meshtastic_ModuleConfig_MQTTConfig_size 222 -#define meshtastic_ModuleConfig_MapReportSettings_size 12 +#define meshtastic_ModuleConfig_MQTTConfig_size 224 +#define meshtastic_ModuleConfig_MapReportSettings_size 14 #define meshtastic_ModuleConfig_NeighborInfoConfig_size 10 #define meshtastic_ModuleConfig_PaxcounterConfig_size 30 #define meshtastic_ModuleConfig_RangeTestConfig_size 10 @@ -899,7 +903,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 #define meshtastic_ModuleConfig_TelemetryConfig_size 46 -#define meshtastic_ModuleConfig_size 225 +#define meshtastic_ModuleConfig_size 227 #define meshtastic_RemoteHardwarePin_size 21 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mqtt.pb.h b/src/mesh/generated/meshtastic/mqtt.pb.h index 1726bc470..c5b10f1f5 100644 --- a/src/mesh/generated/meshtastic/mqtt.pb.h +++ b/src/mesh/generated/meshtastic/mqtt.pb.h @@ -54,6 +54,9 @@ typedef struct _meshtastic_MapReport { uint32_t position_precision; /* Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT) */ uint16_t num_online_local_nodes; + /* User has opted in to share their location (map report) with the mqtt server + Controlled by map_report.should_report_location */ + bool has_opted_report_location; } meshtastic_MapReport; @@ -63,9 +66,9 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_ServiceEnvelope_init_default {NULL, NULL, NULL} -#define meshtastic_MapReport_init_default {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0} +#define meshtastic_MapReport_init_default {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ServiceEnvelope_init_zero {NULL, NULL, NULL} -#define meshtastic_MapReport_init_zero {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0} +#define meshtastic_MapReport_init_zero {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0, 0} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_ServiceEnvelope_packet_tag 1 @@ -84,6 +87,7 @@ extern "C" { #define meshtastic_MapReport_altitude_tag 11 #define meshtastic_MapReport_position_precision_tag 12 #define meshtastic_MapReport_num_online_local_nodes_tag 13 +#define meshtastic_MapReport_has_opted_report_location_tag 14 /* Struct field encoding specification for nanopb */ #define meshtastic_ServiceEnvelope_FIELDLIST(X, a) \ @@ -107,7 +111,8 @@ X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 9) \ X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 10) \ X(a, STATIC, SINGULAR, INT32, altitude, 11) \ X(a, STATIC, SINGULAR, UINT32, position_precision, 12) \ -X(a, STATIC, SINGULAR, UINT32, num_online_local_nodes, 13) +X(a, STATIC, SINGULAR, UINT32, num_online_local_nodes, 13) \ +X(a, STATIC, SINGULAR, BOOL, has_opted_report_location, 14) #define meshtastic_MapReport_CALLBACK NULL #define meshtastic_MapReport_DEFAULT NULL @@ -121,7 +126,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 +#define meshtastic_MapReport_size 110 #ifdef __cplusplus } /* extern "C" */ From fc64bea6982a1d6f31b39e4def84e28e26e93988 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 15:28:09 -0500 Subject: [PATCH 168/238] Unmessagable implementation and defaults (#6811) * Unmessagable implementation and defaults * Router and router late are unmessagable by default * Update src/modules/AdminModule.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mesh/NodeDB.cpp | 16 ++++++++++++++++ src/modules/AdminModule.cpp | 10 +++++++++- src/modules/NodeInfoModule.cpp | 5 +++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index f22f7bf91..48d22c65d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -819,10 +819,19 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role) initConfigIntervals(); initModuleConfigIntervals(); config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY; + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; + } else if (role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; } else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; config.display.screen_on_secs = 1; config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY; } else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; moduleConfig.telemetry.environment_measurement_enabled = true; moduleConfig.telemetry.environment_update_interval = 300; } else if (role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) { @@ -837,7 +846,12 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role) (meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP); moduleConfig.telemetry.device_update_interval = ONE_DAY; + } else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; } else if (role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; config.device.node_info_broadcast_secs = ONE_DAY; config.position.position_broadcast_smart_enabled = true; config.position.position_broadcast_secs = 3 * 60; // Every 3 minutes @@ -970,6 +984,8 @@ void NodeDB::installDefaultDeviceState() #endif snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr)); + owner.has_is_unmessagable = true; + owner.is_unmessagable = false; } // We reserve a few nodenums for future use diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index cbf82ae73..0fac15b15 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -504,6 +504,12 @@ void AdminModule::handleSetOwner(const meshtastic_User &o) sendWarning(licensedModeMessage); } } + if (owner.has_is_unmessagable != o.has_is_unmessagable || + (o.has_is_unmessagable && owner.is_unmessagable != o.is_unmessagable)) { + changed = 1; + owner.has_is_unmessagable = o.has_is_unmessagable || o.has_is_unmessagable; + owner.is_unmessagable = o.is_unmessagable; + } if (changed) { // If nothing really changed, don't broadcast on the network or write to flash service->reloadOwner(!hasOpenEditTransaction); @@ -553,8 +559,10 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) sendWarning(warning); } // If we're setting router role for the first time, install its intervals - if (existingRole != c.payload_variant.device.role) + if (existingRole != c.payload_variant.device.role) { nodeDB->installRoleDefaults(c.payload_variant.device.role); + changes |= SEGMENT_NODEDATABASE | SEGMENT_DEVICESTATE; // Some role defaults affect owner + } if (config.device.node_info_broadcast_secs < min_node_info_broadcast_secs) { LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d", min_node_info_broadcast_secs); config.device.node_info_broadcast_secs = min_node_info_broadcast_secs; diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index ce4a6bd06..5142f2db0 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -86,6 +86,11 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply() u.public_key.bytes[0] = 0; u.public_key.size = 0; } + // Coerce unmessagable for Repeater role + if (u.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + u.has_is_unmessagable = true; + u.is_unmessagable = true; + } LOG_INFO("Send owner %s/%s/%s", u.id, u.long_name, u.short_name); lastSentToMesh = millis(); From 7cffd9ba7083468816a63d3485c70e1a698dcda3 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 15:31:28 -0500 Subject: [PATCH 169/238] Added new map report opt-in for compliance and limit map report (and default) to one hour (#6813) * Added new map report opt-in for compliance and limit map report (and default) to one hour * Trunk --- src/mesh/Default.h | 1 + src/mesh/NodeDB.cpp | 5 +++++ src/modules/AdminModule.cpp | 2 +- src/mqtt/MQTT.cpp | 4 +++- src/mqtt/MQTT.h | 4 ++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/mesh/Default.h b/src/mesh/Default.h index bc2aa785f..208f992c8 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -21,6 +21,7 @@ #define default_neighbor_info_broadcast_secs 6 * 60 * 60 #define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour #define min_neighbor_info_broadcast_secs 4 * 60 * 60 +#define default_map_publish_interval_secs 60 * 60 #define default_mqtt_address "mqtt.meshtastic.org" #define default_mqtt_username "meshdev" diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 48d22c65d..4b1a6d64d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -328,6 +328,11 @@ NodeDB::NodeDB() moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue( moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs); } + if (moduleConfig.mqtt.has_map_report_settings && + moduleConfig.mqtt.map_report_settings.publish_interval_secs < default_map_publish_interval_secs) { + moduleConfig.mqtt.map_report_settings.publish_interval_secs = default_map_publish_interval_secs; + } + // Ensure that the neighbor info update interval is coerced to the minimum moduleConfig.neighbor_info.update_interval = Default::getConfiguredOrMinimumValue(moduleConfig.neighbor_info.update_interval, min_neighbor_info_broadcast_secs); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 0fac15b15..3ff4fa74d 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -504,7 +504,7 @@ void AdminModule::handleSetOwner(const meshtastic_User &o) sendWarning(licensedModeMessage); } } - if (owner.has_is_unmessagable != o.has_is_unmessagable || + if (owner.has_is_unmessagable != o.has_is_unmessagable || (o.has_is_unmessagable && owner.is_unmessagable != o.is_unmessagable)) { changed = 1; owner.has_is_unmessagable = o.has_is_unmessagable || o.has_is_unmessagable; diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 3776f59f5..713077272 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -769,7 +769,8 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me void MQTT::perhapsReportToMap() { - if (!moduleConfig.mqtt.map_reporting_enabled || !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly())) + if (!moduleConfig.mqtt.map_reporting_enabled || !moduleConfig.mqtt.map_report_settings.should_report_location || + !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly())) return; if (Throttle::isWithinTimespanMs(last_report_to_map, map_publish_interval_msecs)) @@ -801,6 +802,7 @@ void MQTT::perhapsReportToMap() mapReport.region = config.lora.region; mapReport.modem_preset = config.lora.modem_preset; mapReport.has_default_channel = channels.hasDefaultChannel(); + mapReport.has_opted_report_location = true; // Set position with precision (same as in PositionModule) if (map_position_precision < 32 && map_position_precision > 0) { diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 2b11f479d..7d5715602 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -1,5 +1,6 @@ #pragma once +#include "Default.h" #include "configuration.h" #include "concurrency/OSThread.h" @@ -105,8 +106,7 @@ class MQTT : private concurrency::OSThread std::string mapTopic = "/2/map/"; // For protobuf-encoded MapReport messages // For map reporting (only applies when enabled) - const uint32_t default_map_position_precision = 14; // defaults to max. offset of ~1459m - const uint32_t default_map_publish_interval_secs = 60 * 15; // defaults to 15 minutes + const uint32_t default_map_position_precision = 14; // defaults to max. offset of ~1459m uint32_t last_report_to_map = 0; uint32_t map_position_precision = default_map_position_precision; uint32_t map_publish_interval_msecs = default_map_publish_interval_secs * 1000; From 3901ae8956d34130d436182224896aa0d27e890e Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 16:44:32 -0500 Subject: [PATCH 170/238] Default --- test/test_mqtt/MQTT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 50a98001a..feb9c7e83 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -308,8 +308,8 @@ const meshtastic_MeshPacket encrypted = { // Initialize mocks and configuration before running each test. void setUp(void) { - moduleConfig.mqtt = - meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; + moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{ + .enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From b63b73ab84562887338700c47c46eb6eec45827a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 17:16:46 -0500 Subject: [PATCH 171/238] Fix --- test/test_mqtt/MQTT.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index feb9c7e83..a297dc229 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -308,8 +308,10 @@ const meshtastic_MeshPacket encrypted = { // Initialize mocks and configuration before running each test. void setUp(void) { - moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{ - .enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true, .should_report_location = true}; + moduleConfig.mqtt = + meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; + mqtt.map_report_settings = meshtastic_ModuleConfig_MQTTConfig_MapReportSettings{ + .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From ed6de5095e9cf3f89c9ce25dafeeab837173d6fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 17:54:21 -0500 Subject: [PATCH 172/238] [create-pull-request] automated change (#6815) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- .../generated/meshtastic/telemetry.pb.cpp | 3 + src/mesh/generated/meshtastic/telemetry.pb.h | 55 ++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/protobufs b/protobufs index 47ec99aa4..4eb0aebae 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 47ec99aa4c4a2e3fff71fd5170663f0848deb021 +Subproject commit 4eb0aebaef1304a5516b6fa864cb4c55daed9147 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.cpp b/src/mesh/generated/meshtastic/telemetry.pb.cpp index c79941fa5..b54cbb00e 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.cpp +++ b/src/mesh/generated/meshtastic/telemetry.pb.cpp @@ -24,6 +24,9 @@ PB_BIND(meshtastic_LocalStats, meshtastic_LocalStats, AUTO) PB_BIND(meshtastic_HealthMetrics, meshtastic_HealthMetrics, AUTO) +PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, AUTO) + + PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index be3fa0907..1c5eb4843 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -290,6 +290,28 @@ typedef struct _meshtastic_HealthMetrics { float temperature; } meshtastic_HealthMetrics; +/* Linux host metrics */ +typedef struct _meshtastic_HostMetrics { + /* Host system uptime */ + uint32_t uptime_seconds; + /* Host system free memory */ + uint64_t freemem_bytes; + /* Host system disk space free for / */ + uint64_t diskfree1_bytes; + /* Secondary system disk space free */ + bool has_diskfree2_bytes; + uint64_t diskfree2_bytes; + /* Tertiary disk space free */ + bool has_diskfree3_bytes; + uint64_t diskfree3_bytes; + /* Host system one minute load in 1/100ths */ + uint16_t load1; + /* Host system five minute load in 1/100ths */ + uint16_t load5; + /* Host system fifteen minute load in 1/100ths */ + uint16_t load15; +} meshtastic_HostMetrics; + /* Types of Measurements the telemetry module is equipped to handle */ typedef struct _meshtastic_Telemetry { /* Seconds since 1970 - or 0 for unknown/unset */ @@ -308,6 +330,8 @@ typedef struct _meshtastic_Telemetry { meshtastic_LocalStats local_stats; /* Health telemetry metrics */ meshtastic_HealthMetrics health_metrics; + /* Linux host metrics */ + meshtastic_HostMetrics host_metrics; } variant; } meshtastic_Telemetry; @@ -338,6 +362,7 @@ extern "C" { + /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} @@ -345,6 +370,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -353,6 +379,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -417,6 +444,14 @@ extern "C" { #define meshtastic_HealthMetrics_heart_bpm_tag 1 #define meshtastic_HealthMetrics_spO2_tag 2 #define meshtastic_HealthMetrics_temperature_tag 3 +#define meshtastic_HostMetrics_uptime_seconds_tag 1 +#define meshtastic_HostMetrics_freemem_bytes_tag 2 +#define meshtastic_HostMetrics_diskfree1_bytes_tag 3 +#define meshtastic_HostMetrics_diskfree2_bytes_tag 4 +#define meshtastic_HostMetrics_diskfree3_bytes_tag 5 +#define meshtastic_HostMetrics_load1_tag 6 +#define meshtastic_HostMetrics_load5_tag 7 +#define meshtastic_HostMetrics_load15_tag 8 #define meshtastic_Telemetry_time_tag 1 #define meshtastic_Telemetry_device_metrics_tag 2 #define meshtastic_Telemetry_environment_metrics_tag 3 @@ -424,6 +459,7 @@ extern "C" { #define meshtastic_Telemetry_power_metrics_tag 5 #define meshtastic_Telemetry_local_stats_tag 6 #define meshtastic_Telemetry_health_metrics_tag 7 +#define meshtastic_Telemetry_host_metrics_tag 8 #define meshtastic_Nau7802Config_zeroOffset_tag 1 #define meshtastic_Nau7802Config_calibrationFactor_tag 2 @@ -512,6 +548,18 @@ X(a, STATIC, OPTIONAL, FLOAT, temperature, 3) #define meshtastic_HealthMetrics_CALLBACK NULL #define meshtastic_HealthMetrics_DEFAULT NULL +#define meshtastic_HostMetrics_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, uptime_seconds, 1) \ +X(a, STATIC, SINGULAR, UINT64, freemem_bytes, 2) \ +X(a, STATIC, SINGULAR, UINT64, diskfree1_bytes, 3) \ +X(a, STATIC, OPTIONAL, UINT64, diskfree2_bytes, 4) \ +X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ +X(a, STATIC, SINGULAR, UINT32, load1, 6) \ +X(a, STATIC, SINGULAR, UINT32, load5, 7) \ +X(a, STATIC, SINGULAR, UINT32, load15, 8) +#define meshtastic_HostMetrics_CALLBACK NULL +#define meshtastic_HostMetrics_DEFAULT NULL + #define meshtastic_Telemetry_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, FIXED32, time, 1) \ X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \ @@ -519,7 +567,8 @@ X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environm X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4) \ X(a, STATIC, ONEOF, MESSAGE, (variant,power_metrics,variant.power_metrics), 5) \ X(a, STATIC, ONEOF, MESSAGE, (variant,local_stats,variant.local_stats), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metrics), 7) +X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metrics), 7) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,host_metrics,variant.host_metrics), 8) #define meshtastic_Telemetry_CALLBACK NULL #define meshtastic_Telemetry_DEFAULT NULL #define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics @@ -528,6 +577,7 @@ X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metric #define meshtastic_Telemetry_variant_power_metrics_MSGTYPE meshtastic_PowerMetrics #define meshtastic_Telemetry_variant_local_stats_MSGTYPE meshtastic_LocalStats #define meshtastic_Telemetry_variant_health_metrics_MSGTYPE meshtastic_HealthMetrics +#define meshtastic_Telemetry_variant_host_metrics_MSGTYPE meshtastic_HostMetrics #define meshtastic_Nau7802Config_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, zeroOffset, 1) \ @@ -541,6 +591,7 @@ extern const pb_msgdesc_t meshtastic_PowerMetrics_msg; extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg; extern const pb_msgdesc_t meshtastic_LocalStats_msg; extern const pb_msgdesc_t meshtastic_HealthMetrics_msg; +extern const pb_msgdesc_t meshtastic_HostMetrics_msg; extern const pb_msgdesc_t meshtastic_Telemetry_msg; extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; @@ -551,6 +602,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg #define meshtastic_LocalStats_fields &meshtastic_LocalStats_msg #define meshtastic_HealthMetrics_fields &meshtastic_HealthMetrics_msg +#define meshtastic_HostMetrics_fields &meshtastic_HostMetrics_msg #define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg @@ -560,6 +612,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 +#define meshtastic_HostMetrics_size 62 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 From 60d2cb35e026040013e98c102761def6498d48b9 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 18:55:27 -0500 Subject: [PATCH 173/238] Namespace --- test/test_mqtt/MQTT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index a297dc229..3cd56cfb6 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -310,7 +310,7 @@ void setUp(void) { moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; - mqtt.map_report_settings = meshtastic_ModuleConfig_MQTTConfig_MapReportSettings{ + mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, From ef9d0d7805a012cd48af90ff702ee7c082512628 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 20:22:01 -0500 Subject: [PATCH 174/238] Go --- test/test_mqtt/MQTT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 3cd56cfb6..c1f5da358 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -310,8 +310,8 @@ void setUp(void) { moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; - mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ - .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; + moduleConfig.mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ + .publish_interval_secs = 0, .position_precision = 14, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From 6bba17d463b9cf114b1db9bb420ad1ea075bd974 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Thu, 15 May 2025 19:26:41 +1000 Subject: [PATCH 175/238] Add suppport for Quectel L80 (#6803) * Add suppport for Quectel L80 Another PMTK family chip, requires only a modification to the probe code. * Update support for L80 based on testing. --- src/gps/GPS.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index e234fdb4a..142241c43 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1250,11 +1250,10 @@ GnssModel_t GPS::probe(int serialSpeed) // Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms _serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n"); delay(20); - std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, - {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D}, - {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, - {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, - {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}}; + std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D}, + {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, + {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}, {"L80-R", "_3337_", GNSS_MODEL_MTK_L76B}, + {"L80", "_3339_", GNSS_MODEL_MTK_L76B}}; PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500); From c2d586216103192995d1059809ef213f38dc4592 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 06:40:07 -0500 Subject: [PATCH 176/238] automated bumps (#6820) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ debian/changelog | 7 +++++-- version.properties | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index b98b54dd4..1a7ad284d 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8 diff --git a/debian/changelog b/debian/changelog index 8fce06c14..ae27bc3e9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -meshtasticd (2.6.8.0) UNRELEASED; urgency=medium +meshtasticd (2.6.9.0) UNRELEASED; urgency=medium [ Austin Lane ] * Initial packaging @@ -10,4 +10,7 @@ meshtasticd (2.6.8.0) UNRELEASED; urgency=medium [ ] * GitHub Actions Automatic version bump - -- Tue, 06 May 2025 01:32:49 +0000 + [ ] + * GitHub Actions Automatic version bump + + -- Thu, 15 May 2025 11:13:30 +0000 diff --git a/version.properties b/version.properties index bedba21b7..b0e960697 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 8 +build = 9 From 7d8f9c7f6df516d8c2561f3c3979581ab5209f47 Mon Sep 17 00:00:00 2001 From: Austin Date: Thu, 15 May 2025 07:40:46 -0400 Subject: [PATCH 177/238] Stop the madness! Run as a user (not root) (#6718) * Stop the madness! Run as a user (not root) * Trigger fsdir migration for < 2.6.9 --------- Co-authored-by: Ben Meadors --- .trunk/trunk.yaml | 1 - Dockerfile | 14 ++++-- alpine.Dockerfile | 11 ++++- bin/99-meshtasticd-udev.rules | 4 ++ bin/config-dist.yaml | 2 +- bin/meshtasticd.service | 7 +-- bin/native-install.sh | 2 +- debian/control | 6 ++- debian/meshtasticd.dirs | 3 +- debian/meshtasticd.install | 4 +- debian/meshtasticd.postinst | 79 ++++++++++++++++++++++++++++++ debian/meshtasticd.postrm | 41 ++++++++++++++++ debian/meshtasticd.udev | 4 ++ meshtasticd.spec.rpkg | 66 +++++++++++++++++++++++-- src/mesh/raspihttp/PiWebServer.cpp | 4 +- 15 files changed, 225 insertions(+), 23 deletions(-) create mode 100644 bin/99-meshtasticd-udev.rules create mode 100755 debian/meshtasticd.postinst create mode 100755 debian/meshtasticd.postrm create mode 100644 debian/meshtasticd.udev diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 4aa5527be..79bdf4778 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -13,7 +13,6 @@ lint: - trufflehog@3.88.29 - yamllint@1.37.1 - bandit@1.8.3 - - terrascan@1.19.9 - trivy@0.62.1 - taplo@0.9.3 - ruff@0.11.9 diff --git a/Dockerfile b/Dockerfile index 6c1b83653..e033b1bba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,3 @@ -# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue # trunk-ignore-all(trivy/DS002): We must run as root for this container # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions @@ -38,6 +37,13 @@ RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/fir ##### PRODUCTION BUILD ############# FROM debian:bookworm-slim +LABEL org.opencontainers.image.title="Meshtastic" \ + org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \ + org.opencontainers.image.url="https://meshtastic.org" \ + org.opencontainers.image.documentation="https://meshtastic.org/docs/" \ + org.opencontainers.image.authors="Meshtastic" \ + org.opencontainers.image.licenses="GPL-3.0-or-later" \ + org.opencontainers.image.source="https://github.com/meshtastic/firmware/" ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Etc/UTC @@ -54,7 +60,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \ && mkdir -p /etc/meshtasticd/ssl # Fetch compiled binary from the builder -COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/ +COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/ COPY --from=builder /tmp/web /usr/share/meshtasticd/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d @@ -65,8 +71,8 @@ VOLUME /var/lib/meshtasticd # Expose Meshtastic TCP API port from the host EXPOSE 4403 # Expose Meshtastic Web UI port from the host -EXPOSE 443 +EXPOSE 9443 -CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ] +CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ] HEALTHCHECK NONE diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 350129040..bf7cad6d4 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -28,12 +28,19 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \ # ##### PRODUCTION BUILD ############# FROM alpine:3.21 +LABEL org.opencontainers.image.title="Meshtastic" \ + org.opencontainers.image.description="Alpine Meshtastic daemon" \ + org.opencontainers.image.url="https://meshtastic.org" \ + org.opencontainers.image.documentation="https://meshtastic.org/docs/" \ + org.opencontainers.image.authors="Meshtastic" \ + org.opencontainers.image.licenses="GPL-3.0-or-later" \ + org.opencontainers.image.source="https://github.com/meshtastic/firmware/" # nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root USER root RUN apk --no-cache add \ - libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \ + shadow libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \ libx11 libinput libxkbcommon \ && rm -rf /var/cache/apk/* \ && mkdir -p /var/lib/meshtasticd \ @@ -41,7 +48,7 @@ RUN apk --no-cache add \ && mkdir -p /etc/meshtasticd/ssl # Fetch compiled binary from the builder -COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/ +COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d diff --git a/bin/99-meshtasticd-udev.rules b/bin/99-meshtasticd-udev.rules new file mode 100644 index 000000000..69a468d7a --- /dev/null +++ b/bin/99-meshtasticd-udev.rules @@ -0,0 +1,4 @@ +# Set spidev ownership to 'spi' group. +SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" +# Allow access to USB CH341 devices +SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 9238d0e56..98c7696f0 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -188,7 +188,7 @@ Logging: # AsciiLogs: true # default if not specified is !isatty() on stdout Webserver: -# Port: 443 # Port for Webserver & Webservices +# Port: 9443 # Port for Webserver & Webservices # RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer # SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present # SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present diff --git a/bin/meshtasticd.service b/bin/meshtasticd.service index 1e8ee98b8..63430bae8 100644 --- a/bin/meshtasticd.service +++ b/bin/meshtasticd.service @@ -5,10 +5,11 @@ StartLimitInterval=200 StartLimitBurst=5 [Service] -User=root -Group=root +AmbientCapabilities=CAP_NET_BIND_SERVICE +User=meshtasticd +Group=meshtasticd Type=simple -ExecStart=/usr/sbin/meshtasticd +ExecStart=/usr/bin/meshtasticd Restart=always RestartSec=3 diff --git a/bin/native-install.sh b/bin/native-install.sh index a8fcc29a6..18cd9205b 100755 --- a/bin/native-install.sh +++ b/bin/native-install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd +cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd mkdir -p /etc/meshtasticd if [[ -f "/etc/meshtasticd/config.yaml" ]]; then cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml diff --git a/debian/control b/debian/control index 9277f6f54..761383a5c 100644 --- a/debian/control +++ b/debian/control @@ -31,7 +31,9 @@ Rules-Requires-Root: no Package: meshtasticd Architecture: any -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: adduser, + ${misc:Depends}, + ${shlibs:Depends} Description: Meshtastic daemon for communicating with Meshtastic devices Meshtastic is an off-grid text communication platform that uses inexpensive - LoRa radios. \ No newline at end of file + LoRa radios. diff --git a/debian/meshtasticd.dirs b/debian/meshtasticd.dirs index 45a1ca3db..a667768b2 100644 --- a/debian/meshtasticd.dirs +++ b/debian/meshtasticd.dirs @@ -1,5 +1,6 @@ +var/lib/meshtasticd etc/meshtasticd etc/meshtasticd/config.d etc/meshtasticd/available.d usr/share/meshtasticd/web -etc/meshtasticd/ssl \ No newline at end of file +etc/meshtasticd/ssl diff --git a/debian/meshtasticd.install b/debian/meshtasticd.install index 6b6b5a361..3c68b42b1 100644 --- a/debian/meshtasticd.install +++ b/debian/meshtasticd.install @@ -1,8 +1,8 @@ -.pio/build/native-tft/meshtasticd usr/sbin +.pio/build/native-tft/meshtasticd usr/bin bin/config.yaml etc/meshtasticd bin/config.d/* etc/meshtasticd/available.d bin/meshtasticd.service lib/systemd/system -web/* usr/share/meshtasticd/web \ No newline at end of file +web/* usr/share/meshtasticd/web diff --git a/debian/meshtasticd.postinst b/debian/meshtasticd.postinst new file mode 100755 index 000000000..324865718 --- /dev/null +++ b/debian/meshtasticd.postinst @@ -0,0 +1,79 @@ +#!/bin/sh +# postinst script for meshtasticd +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure|reconfigure) + # create spi group (for udev rules) + # this group already exists on Raspberry Pi OS + getent group spi >/dev/null 2>/dev/null || addgroup --system spi + # create a meshtasticd group and user + getent passwd meshtasticd >/dev/null 2>/dev/null || adduser --system --home /var/lib/meshtasticd --no-create-home meshtasticd + getent group meshtasticd >/dev/null 2>/dev/null || addgroup --system meshtasticd + adduser meshtasticd meshtasticd >/dev/null 2>/dev/null + adduser meshtasticd spi >/dev/null 2>/dev/null + # add meshtasticd user to appropriate groups (if they exist) + getent group gpio >/dev/null 2>/dev/null && adduser meshtasticd gpio >/dev/null 2>/dev/null + getent group plugdev >/dev/null 2>/dev/null && adduser meshtasticd plugdev >/dev/null 2>/dev/null + getent group dialout >/dev/null 2>/dev/null && adduser meshtasticd dialout >/dev/null 2>/dev/null + getent group i2c >/dev/null 2>/dev/null && adduser meshtasticd i2c >/dev/null 2>/dev/null + getent group video >/dev/null 2>/dev/null && adduser meshtasticd video >/dev/null 2>/dev/null + getent group audio >/dev/null 2>/dev/null && adduser meshtasticd audio >/dev/null 2>/dev/null + getent group input >/dev/null 2>/dev/null && adduser meshtasticd input >/dev/null 2>/dev/null + + + # migrate /root/.portduino to /var/lib/meshtasticd/.portduino + # should only run once, upon upgrade from < 2.6.9 + if [ -n "$2" ] && dpkg --compare-versions "$2" lt 2.6.9; then + if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then + cp -r /root/.portduino /var/lib/meshtasticd/.portduino + echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino" + echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'." + echo "See https://github.com/meshtastic/firmware/pull/6718 for details" + fi + fi + + if [ -d /var/lib/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /var/lib/meshtasticd + fi + + if [ -d /etc/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /etc/meshtasticd + fi + + if [ -d /usr/share/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /usr/share/meshtasticd + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/meshtasticd.postrm b/debian/meshtasticd.postrm new file mode 100755 index 000000000..bb2c32a5b --- /dev/null +++ b/debian/meshtasticd.postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for meshtasticd +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + # Only remove /var/lib/meshtasticd on purge + if [ "${1}" = "purge" ] ; then + rm -rf /var/lib/meshtasticd + fi + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/meshtasticd.udev b/debian/meshtasticd.udev new file mode 100644 index 000000000..69a468d7a --- /dev/null +++ b/debian/meshtasticd.udev @@ -0,0 +1,4 @@ +# Set spidev ownership to 'spi' group. +SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" +# Allow access to USB CH341 devices +SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" diff --git a/meshtasticd.spec.rpkg b/meshtasticd.spec.rpkg index 2d777bc76..eb4ab5ae7 100644 --- a/meshtasticd.spec.rpkg +++ b/meshtasticd.spec.rpkg @@ -10,6 +10,8 @@ # - https://docs.pagure.org/rpkg-util/v3/index.html # - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/ +%global meshtasticd_user meshtasticd + Name: meshtasticd # Version Ex: 2.5.19 Version: {{{ meshtastic_version }}} @@ -47,6 +49,8 @@ BuildRequires: pkgconfig(x11) BuildRequires: pkgconfig(libinput) BuildRequires: pkgconfig(xkbcommon-x11) +Requires: systemd-udev + %description Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid text communication platform that uses inexpensive LoRa radios. @@ -63,15 +67,25 @@ gzip -dr web platformio run -e native-tft %install -mkdir -p %{buildroot}%{_sbindir} -install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd +# Install meshtasticd binary +mkdir -p %{buildroot}%{_bindir} +install -m 0755 .pio/build/native-tft/program %{buildroot}%{_bindir}/meshtasticd +# Install portduino VFS dir +install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd + +# Install udev rules +mkdir -p %{buildroot}%{_udevrulesdir} +install -m 0644 bin/99-meshtasticd-udev.rules %{buildroot}%{_udevrulesdir}/99-meshtasticd-udev.rules + +# Install config dirs mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d +# Install systemd service install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service # Install the web files under /usr/share/meshtasticd/web @@ -80,10 +94,54 @@ cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web # Install default SSL storage directory (for web) mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl +%pre +# create spi group (for udev rules) +getent group spi > /dev/null || groupadd -r spi +# create a meshtasticd group and user +getent group %{meshtasticd_user} > /dev/null || groupadd -r %{meshtasticd_user} +getent passwd %{meshtasticd_user} > /dev/null || \ + useradd -r -d %{_localstatedir}/lib/meshtasticd -g %{meshtasticd_user} -G spi \ + -s /sbin/nologin -c "Meshtastic Daemon" %{meshtasticd_user} +# add meshtasticd user to appropriate groups (if they exist) +getent group gpio > /dev/null && usermod -a -G gpio %{meshtasticd_user} > /dev/null +getent group plugdev > /dev/null && usermod -a -G plugdev %{meshtasticd_user} > /dev/null +getent group dialout > /dev/null && usermod -a -G dialout %{meshtasticd_user} > /dev/null +getent group i2c > /dev/null && usermod -a -G i2c %{meshtasticd_user} > /dev/null +getent group video > /dev/null && usermod -a -G video %{meshtasticd_user} > /dev/null +getent group audio > /dev/null && usermod -a -G audio %{meshtasticd_user} > /dev/null +getent group input > /dev/null && usermod -a -G input %{meshtasticd_user} > /dev/null +exit 0 + +%triggerin -- meshtasticd < 2.6.9 +# migrate .portduino (if it exists and hasn’t already been copied) +if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then + mkdir -p /var/lib/meshtasticd + cp -r /root/.portduino /var/lib/meshtasticd/.portduino + chown -R %{meshtasticd_user}:%{meshtasticd_user} \ + %{_localstatedir}/lib/meshtasticd || : + # Fix SELinux labels if present (no-op on non-SELinux systems) + restorecon -R /var/lib/meshtasticd/.portduino 2>/dev/null || : + echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino" + echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'." + echo "See https://github.com/meshtastic/firmware/pull/6718 for details" +fi + +%post +%systemd_post meshtasticd.service + +%preun +%systemd_preun meshtasticd.service + +%postun +%systemd_postun_with_restart meshtasticd.service + %files +%defattr(-,%{meshtasticd_user},%{meshtasticd_user}) %license LICENSE %doc README.md -%{_sbindir}/meshtasticd +%{_bindir}/meshtasticd +%dir %{_localstatedir}/lib/meshtasticd +%{_udevrulesdir}/99-meshtasticd-udev.rules %dir %{_sysconfdir}/meshtasticd %dir %{_sysconfdir}/meshtasticd/config.d %dir %{_sysconfdir}/meshtasticd/available.d @@ -96,4 +154,4 @@ mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl %dir %{_sysconfdir}/meshtasticd/ssl %changelog -%autochangelog \ No newline at end of file +%autochangelog diff --git a/src/mesh/raspihttp/PiWebServer.cpp b/src/mesh/raspihttp/PiWebServer.cpp index 4fae0bc3d..7d3542e83 100644 --- a/src/mesh/raspihttp/PiWebServer.cpp +++ b/src/mesh/raspihttp/PiWebServer.cpp @@ -462,8 +462,8 @@ PiWebServerThread::PiWebServerThread() webservport = settingsMap[webserverport]; LOG_INFO("Use webserver port from yaml config %i ", webservport); } else { - LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 443"); - webservport = 443; + LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443"); + webservport = 9443; } // Web Content Service Instance From 1ef4caea05939c23cf3dfdedbf250bc0eff8b04e Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 15 May 2025 09:23:37 -0500 Subject: [PATCH 178/238] Host metrics (#6817) * Add std::string exec() function to PortduinoGlue for future work * MVP for HostMetrics module. * Fix compilation for other targets * Remove extra debug calls * Big numbers don't do well as INTs. * Add HostMetrics to config.yaml --- bin/config-dist.yaml | 6 ++ src/modules/Modules.cpp | 4 + src/modules/Telemetry/HostMetrics.cpp | 131 +++++++++++++++++++++++ src/modules/Telemetry/HostMetrics.h | 40 +++++++ src/platform/portduino/PortduinoGlue.cpp | 19 ++++ src/platform/portduino/PortduinoGlue.h | 7 +- 6 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 src/modules/Telemetry/HostMetrics.cpp create mode 100644 src/modules/Telemetry/HostMetrics.h diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 98c7696f0..2907e4aab 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -193,6 +193,12 @@ Webserver: # SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present # SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present + +HostMetrics: +# ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled +# Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel. + + General: MaxNodes: 200 MaxMessageQueue: 100 diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 1f2b50057..fac2ca976 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -49,6 +49,7 @@ #endif #if ARCH_PORTDUINO #include "input/LinuxInputImpl.h" +#include "modules/Telemetry/HostMetrics.h" #if !MESHTASTIC_EXCLUDE_STOREFORWARD #include "modules/StoreForwardModule.h" #endif @@ -196,6 +197,9 @@ void setupModules() #if HAS_SCREEN && !MESHTASTIC_EXCLUDE_CANNEDMESSAGES cannedMessageModule = new CannedMessageModule(); #endif +#if ARCH_PORTDUINO + new HostMetricsModule(); +#endif #if HAS_TELEMETRY new DeviceTelemetryModule(); #endif diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp new file mode 100644 index 000000000..655be4b25 --- /dev/null +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -0,0 +1,131 @@ +#include "HostMetrics.h" +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "MeshService.h" +#if ARCH_PORTDUINO +#include "PortduinoGlue.h" +#include +#endif + +int32_t HostMetricsModule::runOnce() +{ +#if ARCH_PORTDUINO + if (settingsMap[hostMetrics_interval] == 0) { + return disable(); + } else { + sendMetrics(); + return 60 * 1000 * settingsMap[hostMetrics_interval]; + } +#else + return disable(); +#endif +} + +bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) +{ + // Don't worry about storing telemetry in NodeDB if we're a repeater + if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) + return false; + + if (t->which_variant == meshtastic_Telemetry_host_metrics_tag) { +#ifdef DEBUG_PORT + const char *sender = getSenderShortName(mp); + + LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", sender, + t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes, + t->variant.host_metrics.freemem_bytes, static_cast(t->variant.host_metrics.load1) / 100, + static_cast(t->variant.host_metrics.load5) / 100, + static_cast(t->variant.host_metrics.load15) / 100); +#endif + } + return false; // Let others look at this message also if they want +} + +/* +meshtastic_MeshPacket *HostMetricsModule::allocReply() +{ + if (currentRequest) { + auto req = *currentRequest; + const auto &p = req.decoded; + meshtastic_Telemetry scratch; + meshtastic_Telemetry *decoded = NULL; + memset(&scratch, 0, sizeof(scratch)); + if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_HostMetrics_msg, &scratch)) { + decoded = &scratch; + } else { + LOG_ERROR("Error decoding HostMetrics module!"); + return NULL; + } + // Check for a request for device metrics + if (decoded->which_variant == meshtastic_Telemetry_host_metrics_tag) { + LOG_INFO("Device telemetry reply to request"); + return allocDataProtobuf(getHostMetrics()); + } + } + return NULL; +} + */ + +#if ARCH_PORTDUINO +meshtastic_Telemetry HostMetricsModule::getHostMetrics() +{ + std::string file_line; + meshtastic_Telemetry t = meshtastic_HostMetrics_init_zero; + t.which_variant = meshtastic_Telemetry_host_metrics_tag; + + if (access("/proc/uptime", R_OK) == 0) { + std::ifstream proc_uptime("/proc/uptime"); + if (proc_uptime.is_open()) { + std::getline(proc_uptime, file_line, ' '); + proc_uptime.close(); + t.variant.host_metrics.uptime_seconds = stoul(file_line); + } + } + + std::filesystem::space_info root = std::filesystem::space("/"); + t.variant.host_metrics.diskfree1_bytes = root.available; + + if (access("/proc/meminfo", R_OK) == 0) { + std::ifstream proc_meminfo("/proc/meminfo"); + if (proc_meminfo.is_open()) { + do { + std::getline(proc_meminfo, file_line); + } while (file_line.find("MemAvailable") == std::string::npos); + proc_meminfo.close(); + t.variant.host_metrics.freemem_bytes = stoull(file_line.substr(file_line.find_first_of("0123456789"))) * 1024; + } + } + if (access("/proc/loadavg", R_OK) == 0) { + std::ifstream proc_loadavg("/proc/loadavg"); + if (proc_loadavg.is_open()) { + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load1 = stof(file_line) * 100; + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load5 = stof(file_line) * 100; + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load15 = stof(file_line) * 100; + proc_loadavg.close(); + } + } + + return t; +} + +bool HostMetricsModule::sendMetrics() +{ + meshtastic_Telemetry telemetry = getHostMetrics(); + LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", + telemetry.variant.host_metrics.uptime_seconds, telemetry.variant.host_metrics.diskfree1_bytes, + telemetry.variant.host_metrics.freemem_bytes, static_cast(telemetry.variant.host_metrics.load1) / 100, + static_cast(telemetry.variant.host_metrics.load5) / 100, + static_cast(telemetry.variant.host_metrics.load15) / 100); + + meshtastic_MeshPacket *p = allocDataProtobuf(telemetry); + p->to = NODENUM_BROADCAST; + p->decoded.want_response = false; + p->priority = meshtastic_MeshPacket_Priority_BACKGROUND; + p->channel = settingsMap[hostMetrics_channel]; + LOG_INFO("Send packet to mesh"); + service->sendToMesh(p, RX_SRC_LOCAL, true); + return true; +} +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/HostMetrics.h b/src/modules/Telemetry/HostMetrics.h new file mode 100644 index 000000000..99ee631c1 --- /dev/null +++ b/src/modules/Telemetry/HostMetrics.h @@ -0,0 +1,40 @@ +#pragma once +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "ProtobufModule.h" + +class HostMetricsModule : private concurrency::OSThread, public ProtobufModule +{ + CallbackObserver nodeStatusObserver = + CallbackObserver(this, &HostMetricsModule::handleStatusUpdate); + + public: + HostMetricsModule() + : concurrency::OSThread("HostMetrics"), + ProtobufModule("HostMetrics", meshtastic_PortNum_TELEMETRY_APP, &meshtastic_Telemetry_msg) + { + uptimeWrapCount = 0; + uptimeLastMs = millis(); + nodeStatusObserver.observe(&nodeStatus->onNewStatus); + setIntervalFromNow(setStartDelay()); // Wait until NodeInfo is sent + } + virtual bool wantUIFrame() { return false; } + + protected: + /** 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 + */ + virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *p) override; + // virtual meshtastic_MeshPacket *allocReply() override; + virtual int32_t runOnce() override; + /** + * Send our Telemetry into the mesh + */ + bool sendMetrics(); + + private: + meshtastic_Telemetry getHostMetrics(); + + uint32_t lastSentToMesh = 0; + uint32_t uptimeWrapCount; + uint32_t uptimeLastMs; +}; \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 4b96e662a..c6aa30629 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -600,6 +600,11 @@ bool loadConfig(const char *configPath) (yamlConfig["Webserver"]["SSLCert"]).as("/etc/meshtasticd/ssl/certificate.pem"); } + if (yamlConfig["HostMetrics"]) { + settingsMap[hostMetrics_channel] = (yamlConfig["HostMetrics"]["Channel"]).as(0); + settingsMap[hostMetrics_interval] = (yamlConfig["HostMetrics"]["ReportInterval"]).as(0); + } + if (yamlConfig["General"]) { settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); @@ -650,4 +655,18 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac) } else { return false; } +} + +std::string exec(const char *cmd) +{ // https://stackoverflow.com/a/478960 + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; } \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 6393d7294..0cf0201aa 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -100,7 +100,9 @@ enum configNames { ascii_logs, config_directory, available_directory, - mac_address + mac_address, + hostMetrics_interval, + hostMetrics_channel }; enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; @@ -114,4 +116,5 @@ int initGPIOPin(int pinNum, std::string gpioChipname, int line); 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); \ No newline at end of file +bool MAC_from_string(std::string mac_str, uint8_t *dmac); +std::string exec(const char *cmd); \ No newline at end of file From 066609a7189163f607fee5966f223526c30bd7d1 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 15 May 2025 21:29:08 -0500 Subject: [PATCH 179/238] Remove incomplete compass boot calibration (#6825) The made it in from testing unintentionally. --- src/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 452cb3526..1e46d9db1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1300,10 +1300,6 @@ void setup() LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap()); LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram()); #endif -#if !defined(ARCH_STM32WL) - if (accelerometerThread) - accelerometerThread->calibrate(30); -#endif } #endif From 3398a52a346263ff88a441e325d549242691aae7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 06:15:44 -0500 Subject: [PATCH 180/238] Update meshtastic/device-ui digest to 55f7152 (#6830) 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 b78ecdc1a..d5a954a80 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/7dee10ad31a0c6ea04880cba399e240be743d752.zip + https://github.com/meshtastic/device-ui/archive/55f71527f3137ed4eabc258498d5c6ad9f610674.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From a50a94150aba14aaba1639412c535e8f6e99a4ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 10:44:02 -0500 Subject: [PATCH 181/238] [create-pull-request] automated change (#6834) Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 27 ++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/protobufs b/protobufs index 4eb0aebae..475694e62 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 4eb0aebaef1304a5516b6fa864cb4c55daed9147 +Subproject commit 475694e62b0fdac3469abc15c6d66d05fc9ad69a diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 1c5eb4843..4cce7ca33 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -89,7 +89,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* RAKWireless RAK12035 Soil Moisture Sensor Module */ meshtastic_TelemetrySensorType_RAK12035 = 37, /* MAX17261 lipo battery gauge */ - meshtastic_TelemetrySensorType_MAX17261 = 38 + meshtastic_TelemetrySensorType_MAX17261 = 38, + /* PCT2075 Temperature Sensor */ + meshtastic_TelemetrySensorType_PCT2075 = 39 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -310,6 +312,9 @@ typedef struct _meshtastic_HostMetrics { uint16_t load5; /* Host system fifteen minute load in 1/100ths */ uint16_t load15; + /* Optional User-provided string for arbitrary host system information + that doesn't make sense as a dedicated entry. */ + pb_callback_t user_string; } meshtastic_HostMetrics; /* Types of Measurements the telemetry module is equipped to handle */ @@ -350,8 +355,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17261 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17261+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PCT2075 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PCT2075+1)) @@ -370,7 +375,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -379,7 +384,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -452,6 +457,7 @@ extern "C" { #define meshtastic_HostMetrics_load1_tag 6 #define meshtastic_HostMetrics_load5_tag 7 #define meshtastic_HostMetrics_load15_tag 8 +#define meshtastic_HostMetrics_user_string_tag 9 #define meshtastic_Telemetry_time_tag 1 #define meshtastic_Telemetry_device_metrics_tag 2 #define meshtastic_Telemetry_environment_metrics_tag 3 @@ -556,8 +562,9 @@ X(a, STATIC, OPTIONAL, UINT64, diskfree2_bytes, 4) \ X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ X(a, STATIC, SINGULAR, UINT32, load1, 6) \ X(a, STATIC, SINGULAR, UINT32, load5, 7) \ -X(a, STATIC, SINGULAR, UINT32, load15, 8) -#define meshtastic_HostMetrics_CALLBACK NULL +X(a, STATIC, SINGULAR, UINT32, load15, 8) \ +X(a, CALLBACK, OPTIONAL, STRING, user_string, 9) +#define meshtastic_HostMetrics_CALLBACK pb_default_field_callback #define meshtastic_HostMetrics_DEFAULT NULL #define meshtastic_Telemetry_FIELDLIST(X, a) \ @@ -607,16 +614,16 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg /* Maximum encoded size of messages (where known) */ -#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size +/* meshtastic_HostMetrics_size depends on runtime parameters */ +/* meshtastic_Telemetry_size depends on runtime parameters */ +#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_EnvironmentMetrics_size #define meshtastic_AirQualityMetrics_size 78 #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 -#define meshtastic_HostMetrics_size 62 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 -#define meshtastic_Telemetry_size 120 #ifdef __cplusplus } /* extern "C" */ From 5b312ab9175402d41cafe1c0a29f4c6a45f8c3a2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 12:29:18 -0500 Subject: [PATCH 182/238] [create-pull-request] automated change (#6836) Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.cpp | 4 ++-- src/mesh/generated/meshtastic/telemetry.pb.h | 17 +++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/protobufs b/protobufs index 475694e62..d8b709aa5 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 475694e62b0fdac3469abc15c6d66d05fc9ad69a +Subproject commit d8b709aa5da85959a80a06a6624761678a96f9c0 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.cpp b/src/mesh/generated/meshtastic/telemetry.pb.cpp index b54cbb00e..345d7a157 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.cpp +++ b/src/mesh/generated/meshtastic/telemetry.pb.cpp @@ -24,10 +24,10 @@ PB_BIND(meshtastic_LocalStats, meshtastic_LocalStats, AUTO) PB_BIND(meshtastic_HealthMetrics, meshtastic_HealthMetrics, AUTO) -PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, AUTO) +PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, 2) -PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) +PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, 2) PB_BIND(meshtastic_Nau7802Config, meshtastic_Nau7802Config, AUTO) diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 4cce7ca33..4071c611e 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -314,7 +314,8 @@ typedef struct _meshtastic_HostMetrics { uint16_t load15; /* Optional User-provided string for arbitrary host system information that doesn't make sense as a dedicated entry. */ - pb_callback_t user_string; + bool has_user_string; + char user_string[200]; } meshtastic_HostMetrics; /* Types of Measurements the telemetry module is equipped to handle */ @@ -375,7 +376,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -384,7 +385,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -563,8 +564,8 @@ X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ X(a, STATIC, SINGULAR, UINT32, load1, 6) \ X(a, STATIC, SINGULAR, UINT32, load5, 7) \ X(a, STATIC, SINGULAR, UINT32, load15, 8) \ -X(a, CALLBACK, OPTIONAL, STRING, user_string, 9) -#define meshtastic_HostMetrics_CALLBACK pb_default_field_callback +X(a, STATIC, OPTIONAL, STRING, user_string, 9) +#define meshtastic_HostMetrics_CALLBACK NULL #define meshtastic_HostMetrics_DEFAULT NULL #define meshtastic_Telemetry_FIELDLIST(X, a) \ @@ -614,16 +615,16 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg /* Maximum encoded size of messages (where known) */ -/* meshtastic_HostMetrics_size depends on runtime parameters */ -/* meshtastic_Telemetry_size depends on runtime parameters */ -#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_EnvironmentMetrics_size +#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 78 #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 +#define meshtastic_HostMetrics_size 264 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 +#define meshtastic_Telemetry_size 272 #ifdef __cplusplus } /* extern "C" */ From 61e4eb12e63db87d9f7839d29f5042d329b8e32f Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 17 May 2025 14:02:39 -0500 Subject: [PATCH 183/238] Use the _init_zero macro correctly for HostMetrics (#6837) --- src/modules/Telemetry/HostMetrics.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp index 655be4b25..d1e5bdd00 100644 --- a/src/modules/Telemetry/HostMetrics.cpp +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -69,8 +69,9 @@ meshtastic_MeshPacket *HostMetricsModule::allocReply() meshtastic_Telemetry HostMetricsModule::getHostMetrics() { std::string file_line; - meshtastic_Telemetry t = meshtastic_HostMetrics_init_zero; + meshtastic_Telemetry t = meshtastic_Telemetry_init_zero; t.which_variant = meshtastic_Telemetry_host_metrics_tag; + t.variant.host_metrics = meshtastic_HostMetrics_init_zero; if (access("/proc/uptime", R_OK) == 0) { std::ifstream proc_uptime("/proc/uptime"); From b2d81b740f2e5556ad2d76d0f01a60fb769d4a84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 21:11:02 +1000 Subject: [PATCH 184/238] Update dorny/test-reporter action to v2.1.0 (#6833) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/test_native.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index c3643dcbd..536d93665 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -143,7 +143,7 @@ jobs: merge-multiple: true - name: Test Report - uses: dorny/test-reporter@v2.0.0 + uses: dorny/test-reporter@v2.1.0 with: name: PlatformIO Tests path: testreport.xml From 3dd6dc0296cc06dd7e33eb25b5705f753d726054 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 14:37:54 -0500 Subject: [PATCH 185/238] Update meshtastic/device-ui digest to 48e963f (#6841) 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 d5a954a80..03206da00 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/55f71527f3137ed4eabc258498d5c6ad9f610674.zip + https://github.com/meshtastic/device-ui/archive/48e963f164238d9e83719b8ee77cfea735a6cd6e.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 16994c872540771663571bd83de1d5cbe11d3512 Mon Sep 17 00:00:00 2001 From: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com> Date: Mon, 19 May 2025 07:49:38 -0400 Subject: [PATCH 186/238] Fix for ICM-20948 not initializing (#6827) * Fix for ICM-20948 not initializing * trunk fix --- src/motion/ICM20948Sensor.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/motion/ICM20948Sensor.cpp b/src/motion/ICM20948Sensor.cpp index d03633124..ecc48d39b 100755 --- a/src/motion/ICM20948Sensor.cpp +++ b/src/motion/ICM20948Sensor.cpp @@ -189,13 +189,19 @@ bool ICM20948Singleton::init(ScanI2C::FoundDevice device) enableDebugging(); #endif -// startup -#ifdef Wire1 - ICM_20948_Status_e status = - begin(device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire, device.address.address == ICM20948_ADDR ? 1 : 0); + // startup +#if defined(WIRE_INTERFACES_COUNT) && (WIRE_INTERFACES_COUNT > 1) + TwoWire &bus = (device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire); #else - ICM_20948_Status_e status = begin(Wire, device.address.address == ICM20948_ADDR ? 1 : 0); + TwoWire &bus = Wire; // fallback if only one I2C interface #endif + + bool bAddr = (device.address.address == 0x69); + delay(100); + + LOG_DEBUG("ICM20948 begin on addr 0x%02X (port=%d, bAddr=%d)", device.address.address, device.address.port, bAddr); + + ICM_20948_Status_e status = begin(bus, bAddr); if (status != ICM_20948_Stat_Ok) { LOG_DEBUG("ICM20948 init begin - %s", statusString()); return false; From c70fa0ef13d4fea6b94b9beb618fb32e14751525 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:10:22 +0200 Subject: [PATCH 187/238] Update meshtastic/device-ui digest to c9a55f6 (#6845) 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 03206da00..adf9cb717 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/48e963f164238d9e83719b8ee77cfea735a6cd6e.zip + https://github.com/meshtastic/device-ui/archive/c9a55f661a735d1f393a02657e5183ccf39cf1a2.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From e0f878872f98b4583363094345e8cae413e3c112 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 20 May 2025 13:04:05 -0500 Subject: [PATCH 188/238] Hostmetrics user string (#6850) --- bin/config-dist.yaml | 1 + src/modules/Telemetry/HostMetrics.cpp | 18 ++++++++++++------ src/platform/portduino/PortduinoGlue.cpp | 1 + src/platform/portduino/PortduinoGlue.h | 3 ++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 2907e4aab..55e8648d9 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -197,6 +197,7 @@ Webserver: HostMetrics: # ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled # Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel. +# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString General: diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp index d1e5bdd00..dc4315efa 100644 --- a/src/modules/Telemetry/HostMetrics.cpp +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -30,11 +30,11 @@ bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, #ifdef DEBUG_PORT const char *sender = getSenderShortName(mp); - LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", sender, - t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes, + LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f, %s", + sender, t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes, t->variant.host_metrics.freemem_bytes, static_cast(t->variant.host_metrics.load1) / 100, static_cast(t->variant.host_metrics.load5) / 100, - static_cast(t->variant.host_metrics.load15) / 100); + static_cast(t->variant.host_metrics.load15) / 100, t->variant.host_metrics.user_string); #endif } return false; // Let others look at this message also if they want @@ -107,18 +107,24 @@ meshtastic_Telemetry HostMetricsModule::getHostMetrics() proc_loadavg.close(); } } - + if (settingsStrings[hostMetrics_user_command] != "") { + std::string userCommandResult = exec(settingsStrings[hostMetrics_user_command].c_str()); + if (userCommandResult.length() > 1) { + strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), 200); + t.variant.host_metrics.has_user_string = true; + } + } return t; } bool HostMetricsModule::sendMetrics() { meshtastic_Telemetry telemetry = getHostMetrics(); - LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", + LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f %s", telemetry.variant.host_metrics.uptime_seconds, telemetry.variant.host_metrics.diskfree1_bytes, telemetry.variant.host_metrics.freemem_bytes, static_cast(telemetry.variant.host_metrics.load1) / 100, static_cast(telemetry.variant.host_metrics.load5) / 100, - static_cast(telemetry.variant.host_metrics.load15) / 100); + static_cast(telemetry.variant.host_metrics.load15) / 100, telemetry.variant.host_metrics.user_string); meshtastic_MeshPacket *p = allocDataProtobuf(telemetry); p->to = NODENUM_BROADCAST; diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index c6aa30629..cc0c417d3 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -603,6 +603,7 @@ bool loadConfig(const char *configPath) if (yamlConfig["HostMetrics"]) { settingsMap[hostMetrics_channel] = (yamlConfig["HostMetrics"]["Channel"]).as(0); settingsMap[hostMetrics_interval] = (yamlConfig["HostMetrics"]["ReportInterval"]).as(0); + settingsStrings[hostMetrics_user_command] = (yamlConfig["HostMetrics"]["UserStringCommand"]).as(""); } if (yamlConfig["General"]) { diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 0cf0201aa..d324aaf47 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -102,7 +102,8 @@ enum configNames { available_directory, mac_address, hostMetrics_interval, - hostMetrics_channel + hostMetrics_channel, + hostMetrics_user_command }; enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; From cf3f35d5661fb499009a192e7ec6710c72de7691 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 19:51:03 -0500 Subject: [PATCH 189/238] [create-pull-request] automated change (#6857) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 13 +++++++++---- src/mesh/generated/meshtastic/mesh.pb.h | 14 ++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/protobufs b/protobufs index d8b709aa5..0b32ce24f 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit d8b709aa5da85959a80a06a6624761678a96f9c0 +Subproject commit 0b32ce24f029f69635026aec9428b5c8176e2ce1 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index d29fb17a7..2436098da 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -96,6 +96,9 @@ typedef struct _meshtastic_NodeInfoLite { bool is_ignored; /* Last byte of the node number of the node that should be used as the next hop to reach this node. */ uint8_t next_hop; + /* Bitfield for storing booleans. + LSB 0 is_key_manually_verified */ + uint32_t bitfield; } meshtastic_NodeInfoLite; /* This message is never sent over the wire, but it is used for serializing DB @@ -187,14 +190,14 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} -#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0} +#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 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}} #define meshtastic_NodeDatabase_init_default {0, {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_BackupPreferences_init_default {0, 0, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default, false, meshtastic_ChannelFile_init_default, false, meshtastic_User_init_default} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} -#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0} +#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 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}} #define meshtastic_NodeDatabase_init_zero {0, {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} @@ -226,6 +229,7 @@ extern "C" { #define meshtastic_NodeInfoLite_is_favorite_tag 10 #define meshtastic_NodeInfoLite_is_ignored_tag 11 #define meshtastic_NodeInfoLite_next_hop_tag 12 +#define meshtastic_NodeInfoLite_bitfield_tag 13 #define meshtastic_DeviceState_my_node_tag 2 #define meshtastic_DeviceState_owner_tag 3 #define meshtastic_DeviceState_receive_queue_tag 5 @@ -280,7 +284,8 @@ X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \ X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \ X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) \ -X(a, STATIC, SINGULAR, UINT32, next_hop, 12) +X(a, STATIC, SINGULAR, UINT32, next_hop, 12) \ +X(a, STATIC, SINGULAR, UINT32, bitfield, 13) #define meshtastic_NodeInfoLite_CALLBACK NULL #define meshtastic_NodeInfoLite_DEFAULT NULL #define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_UserLite @@ -358,7 +363,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; #define meshtastic_BackupPreferences_size 2267 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1722 -#define meshtastic_NodeInfoLite_size 190 +#define meshtastic_NodeInfoLite_size 196 #define meshtastic_PositionLite_size 28 #define meshtastic_UserLite_size 98 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 572a6f5d5..d6816eeef 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -854,6 +854,10 @@ typedef struct _meshtastic_NodeInfo { /* True if node is in our ignored list Persists between NodeDB internal clean ups */ bool is_ignored; + /* True if node public key has been verified. + Persists between NodeDB internal clean ups + LSB 0 of the bitfield */ + bool is_key_manually_verified; } meshtastic_NodeInfo; typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t; @@ -1214,7 +1218,7 @@ extern "C" { #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} -#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0} +#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0} #define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, ""} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} @@ -1239,7 +1243,7 @@ extern "C" { #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} -#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0} +#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0} #define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, ""} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} @@ -1349,6 +1353,7 @@ extern "C" { #define meshtastic_NodeInfo_hops_away_tag 9 #define meshtastic_NodeInfo_is_favorite_tag 10 #define meshtastic_NodeInfo_is_ignored_tag 11 +#define meshtastic_NodeInfo_is_key_manually_verified_tag 12 #define meshtastic_MyNodeInfo_my_node_num_tag 1 #define meshtastic_MyNodeInfo_reboot_count_tag 8 #define meshtastic_MyNodeInfo_min_app_version_tag 11 @@ -1552,7 +1557,8 @@ X(a, STATIC, SINGULAR, UINT32, channel, 7) \ X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \ X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \ -X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) +X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) \ +X(a, STATIC, SINGULAR, BOOL, is_key_manually_verified, 12) #define meshtastic_NodeInfo_CALLBACK NULL #define meshtastic_NodeInfo_DEFAULT NULL #define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User @@ -1791,7 +1797,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_MyNodeInfo_size 77 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 321 +#define meshtastic_NodeInfo_size 323 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 From 6041357cbba41f6f4e290a1dc08d2214c3636868 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 20 May 2025 20:31:01 -0500 Subject: [PATCH 190/238] Increase the debt ceiling --- src/mesh/mesh-pb-constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index f748d295e..08c03dc6b 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -20,7 +20,7 @@ /// Verify baseline assumption of node size. If it increases, we need to reevaluate /// the impact of its memory footprint, notably on MAX_NUM_NODES. -static_assert(sizeof(meshtastic_NodeInfoLite) <= 192, "NodeInfoLite size increased. Reconsider impact on MAX_NUM_NODES."); +static_assert(sizeof(meshtastic_NodeInfoLite) <= 200, "NodeInfoLite size increased. Reconsider impact on MAX_NUM_NODES."); /// max number of nodes allowed in the nodeDB #ifndef MAX_NUM_NODES From 41c1b29d70f463b4a0c33970c0f79d1358b0518a Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 20 May 2025 21:29:29 -0500 Subject: [PATCH 191/238] Add basic handling for is_manually_validated (#6856) --- src/mesh/NodeDB.cpp | 6 ++++-- src/mesh/NodeDB.h | 2 ++ src/mesh/TypeConversions.cpp | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 4b1a6d64d..12756abce 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1653,8 +1653,10 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) int oldestIndex = -1; int oldestBoringIndex = -1; for (int i = 1; i < numMeshNodes; i++) { - // Simply the oldest non-favorite node - if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && meshNodes->at(i).last_heard < oldest) { + // Simply the oldest non-favorite, non-ignored, non-verified node + if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && + !(meshNodes->at(i).bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK) && + meshNodes->at(i).last_heard < oldest) { oldest = meshNodes->at(i).last_heard; oldestIndex = i; } diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 4dbda6a9f..16159d380 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -274,6 +274,8 @@ extern meshtastic_CriticalErrorCode error_code; * A numeric error address (nonzero if available) */ extern uint32_t error_address; +#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT 0 +#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK (1 << NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT) #define Module_Config_size \ (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \ diff --git a/src/mesh/TypeConversions.cpp b/src/mesh/TypeConversions.cpp index 5fc6b8a64..c47a67e68 100644 --- a/src/mesh/TypeConversions.cpp +++ b/src/mesh/TypeConversions.cpp @@ -13,6 +13,7 @@ meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfo info.via_mqtt = lite->via_mqtt; info.is_favorite = lite->is_favorite; info.is_ignored = lite->is_ignored; + info.is_key_manually_verified = lite->bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK; if (lite->has_hops_away) { info.has_hops_away = true; From 7cd50d70443802707c2c5545f453f4fb9f5dd00a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 22 May 2025 07:40:36 -0500 Subject: [PATCH 192/238] If a contact is add from a QR, it's "verified" manually (#6858) * If a contact is add from a QR, it's "verified" manually * Update src/mesh/NodeDB.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mesh/NodeDB.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 12756abce..28af7d308 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1518,6 +1518,8 @@ void NodeDB::addFromContact(meshtastic_SharedContact contact) info->has_user = true; info->user = TypeConversions::ConvertToUserLite(contact.user); info->is_favorite = true; + // Mark the node's key as manually verified to indicate trustworthiness. + info->bitfield |= NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK; updateGUIforNode = info; powerFSM.trigger(EVENT_NODEDB_UPDATED); notifyObservers(true); // Force an update whether or not our node counts have changed From b12e9d43be00f6c496892d2567d1535d094f22be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 14:53:16 -0500 Subject: [PATCH 193/238] Update meshtastic/device-ui digest to 405ca49 (#6865) 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 adf9cb717..ae3cbd53b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/c9a55f661a735d1f393a02657e5183ccf39cf1a2.zip + https://github.com/meshtastic/device-ui/archive/405ca495322b7dc3b61f7588d28267d49b2ebc38.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From ba1ef45024b0829c887e7fa8e0f6889fd4160cdf Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 23 May 2025 11:16:53 +1200 Subject: [PATCH 194/238] InkHUD Extended ASCII (#6768) * Custom AdafruitGFX fonts with extended ASCII encodings * AppletFont handles re-encoding of UTF-8 text * Manual parsing of text which may contain non-ASCII chars * Display emoji reactions, even when unprintable Important to indicate to users that a message has been received, even if meaning is unclear. * Superstitious shrink_to_fit I don't think these help, but they're not hurting! * Use Windows-1252 fonts by default * Spelling * Tidy up nicheGraphics.h * Documentation * Fix inverted logic Slipped in during a last minute renaming while tidying up to push.. --- src/graphics/niche/Fonts/FreeSans6pt7b.h | 317 +++++---- .../niche/Fonts/FreeSans6pt8bCyrillic.h | 302 -------- .../niche/Fonts/FreeSans6pt_Win1250.h | 457 ++++++++++++ .../niche/Fonts/FreeSans6pt_Win1251.h | 457 ++++++++++++ .../niche/Fonts/FreeSans6pt_Win1252.h | 457 ++++++++++++ .../niche/Fonts/FreeSans9pt_Win1250.h | 494 +++++++++++++ .../niche/Fonts/FreeSans9pt_Win1251.h | 493 +++++++++++++ .../niche/Fonts/FreeSans9pt_Win1252.h | 494 +++++++++++++ src/graphics/niche/InkHUD/Applet.cpp | 73 +- src/graphics/niche/InkHUD/Applet.h | 15 +- src/graphics/niche/InkHUD/AppletFont.cpp | 651 ++++++++++++++---- src/graphics/niche/InkHUD/AppletFont.h | 54 +- .../InkHUD/Applets/Bases/Map/MapApplet.cpp | 8 +- .../Applets/Bases/NodeList/NodeListApplet.cpp | 12 +- .../BasicExample/BasicExampleApplet.cpp | 6 + .../NewMsgExample/NewMsgExampleApplet.h | 2 +- .../InkHUD/Applets/System/Menu/MenuApplet.cpp | 1 + .../Notification/NotificationApplet.cpp | 10 +- .../Applets/System/Pairing/PairingApplet.cpp | 4 +- .../User/AllMessage/AllMessageApplet.cpp | 12 +- .../niche/InkHUD/Applets/User/DM/DMApplet.cpp | 12 +- .../InkHUD/Applets/User/Heard/HeardApplet.cpp | 7 +- .../User/RecentsList/RecentsListApplet.cpp | 5 +- .../ThreadedMessage/ThreadedMessageApplet.cpp | 32 +- src/graphics/niche/InkHUD/Events.cpp | 5 - src/graphics/niche/InkHUD/docs/README.md | 130 +++- variants/ELECROW-ThinkNode-M1/nicheGraphics.h | 67 +- variants/heltec_mesh_pocket/nicheGraphics.h | 58 +- .../heltec_vision_master_e213/nicheGraphics.h | 51 +- .../heltec_vision_master_e290/nicheGraphics.h | 51 +- .../heltec_wireless_paper/nicheGraphics.h | 42 +- variants/t-echo/nicheGraphics.h | 78 +-- variants/tlora_t3s3_epaper/nicheGraphics.h | 34 +- 33 files changed, 3977 insertions(+), 914 deletions(-) delete mode 100644 src/graphics/niche/Fonts/FreeSans6pt8bCyrillic.h create mode 100644 src/graphics/niche/Fonts/FreeSans6pt_Win1250.h create mode 100644 src/graphics/niche/Fonts/FreeSans6pt_Win1251.h create mode 100644 src/graphics/niche/Fonts/FreeSans6pt_Win1252.h create mode 100644 src/graphics/niche/Fonts/FreeSans9pt_Win1250.h create mode 100644 src/graphics/niche/Fonts/FreeSans9pt_Win1251.h create mode 100644 src/graphics/niche/Fonts/FreeSans9pt_Win1252.h diff --git a/src/graphics/niche/Fonts/FreeSans6pt7b.h b/src/graphics/niche/Fonts/FreeSans6pt7b.h index c5bcc32c4..0b3e74b8f 100644 --- a/src/graphics/niche/Fonts/FreeSans6pt7b.h +++ b/src/graphics/niche/Fonts/FreeSans6pt7b.h @@ -1,129 +1,198 @@ #pragma once - const uint8_t FreeSans6pt7bBitmaps[] PROGMEM = { - 0xAA, 0xA8, 0xC0, 0xF6, 0xA0, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, - 0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, 0x70, 0x91, 0x23, 0x86, 0x12, 0xA2, 0x4E, 0xF4, 0xE0, - 0x5A, 0xAA, 0x94, 0x89, 0x12, 0x49, 0x29, 0x00, 0x27, 0x50, 0x21, 0x3E, 0x42, 0x00, 0xE0, 0xC0, 0x80, 0x24, 0xA4, 0xA4, 0x80, - 0x74, 0xE3, 0x18, 0xC6, 0x33, 0x70, 0x27, 0x92, 0x49, 0x20, 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, 0x79, 0x30, 0x43, 0x18, - 0x10, 0x71, 0x78, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0x7D, 0x04, 0x1E, 0x44, 0x10, 0x51, 0x78, 0x74, 0x61, 0xE8, 0xC6, - 0x31, 0x70, 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, - 0x78, 0x82, 0x87, 0x01, 0xF1, 0x83, 0x04, 0xF8, 0x3E, 0x07, 0x06, 0x36, 0x40, 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, 0x0F, 0x86, - 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, - 0x42, 0xC3, 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, 0xF9, 0x0A, 0x1C, - 0x18, 0x30, 0x61, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x61, - 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x87, - 0x29, 0x70, 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, - 0xA5, 0x99, 0x99, 0x99, 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, - 0x1E, 0x00, 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1F, 0x00, 0x00, - 0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, - 0x08, 0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, 0xC2, 0x42, 0x42, 0x64, 0x24, 0x24, 0x38, 0x18, 0x18, 0xC4, 0x28, - 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, 0x42, 0x66, 0x24, 0x18, 0x18, 0x18, 0x24, 0x46, 0x42, 0xC3, - 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24, - 0x89, 0x20, 0xE9, 0x24, 0x92, 0x49, 0x70, 0x46, 0xA9, 0x10, 0xFE, 0x40, 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, 0x84, 0x3D, 0x18, - 0xC6, 0x31, 0xF0, 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, 0x39, 0x38, 0x7F, 0x81, 0x13, - 0x80, 0x6B, 0xA4, 0x92, 0x40, 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, 0xBF, 0x80, - 0x45, 0x55, 0x57, 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, 0xFF, 0x80, 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, 0xF4, 0x63, 0x18, - 0xC6, 0x20, 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, - 0xF2, 0x49, 0x20, 0x79, 0x24, 0x1C, 0x0B, 0x27, 0x80, 0x5D, 0x24, 0x93, 0x8C, 0x63, 0x18, 0xCF, 0xA0, 0x85, 0x24, 0x92, 0x30, - 0xC3, 0x00, 0x89, 0x2C, 0x96, 0x4A, 0xA5, 0x61, 0x30, 0x98, 0x49, 0x23, 0x08, 0x31, 0x2C, 0x80, 0x89, 0x24, 0x94, 0x50, 0xC2, - 0x08, 0x21, 0x00, 0x78, 0x44, 0x46, 0x23, 0xE0, 0x6A, 0xAA, 0xA9, 0xFF, 0xE0, 0x95, 0x55, 0x56, 0x66, 0x60}; + /* ' ' 0x20 */ + /* '!' 0x21 */ 0xFE, 0x80, + /* '"' 0x22 */ 0xB6, 0x80, + /* '#' 0x23 */ 0x24, 0x49, 0xF9, 0x42, 0x9F, 0x92, 0x28, + /* '$' 0x24 */ 0x23, 0xAB, 0x5A, 0x38, 0xB5, 0xAB, 0x88, + /* '%' 0x25 */ 0x71, 0x22, 0x88, 0xA2, 0x30, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0x80, + /* '&' 0x26 */ 0x31, 0x24, 0x8C, 0x72, 0x58, 0xA3, 0x74, + /* ''' 0x27 */ 0xE0, + /* '(' 0x28 */ 0x5A, 0xAA, 0x94, + /* ')' 0x29 */ 0x89, 0x12, 0x49, 0x49, 0x00, + /* '*' 0x2A */ 0x5E, 0x80, + /* '+' 0x2B */ 0x21, 0x3E, 0x42, 0x00, + /* ',' 0x2C */ 0xE0, + /* '-' 0x2D */ 0xE0, + /* '.' 0x2E */ 0x80, + /* '/' 0x2F */ 0x25, 0x24, 0xA4, 0x80, + /* '0' 0x30 */ 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, + /* '1' 0x31 */ 0x5D, 0x55, 0x40, + /* '2' 0x32 */ 0x74, 0x42, 0x11, 0x11, 0x10, 0xF8, + /* '3' 0x33 */ 0x74, 0x42, 0x13, 0x04, 0x31, 0x70, + /* '4' 0x34 */ 0x11, 0x8C, 0xA9, 0x4B, 0xE2, 0x10, + /* '5' 0x35 */ 0x7D, 0x04, 0x1E, 0x4C, 0x10, 0x63, 0x78, + /* '6' 0x36 */ 0x72, 0x61, 0xE8, 0xC6, 0x39, 0x70, + /* '7' 0x37 */ 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, + /* '8' 0x38 */ 0x7A, 0x18, 0x61, 0x7A, 0x18, 0x61, 0x78, + /* '9' 0x39 */ 0x7B, 0x28, 0x61, 0xCD, 0xD0, 0x62, 0x70, + /* ':' 0x3A */ 0x82, + /* ';' 0x3B */ 0x87, + /* '<' 0x3C */ 0x3E, 0x30, 0x60, 0x80, + /* '=' 0x3D */ 0xF8, 0x3E, + /* '>' 0x3E */ 0xE0, 0xC6, 0xC8, 0x00, + /* '?' 0x3F */ 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, + /* '@' 0x40 */ 0x0F, 0x06, 0x19, 0x3B, 0xC4, 0x99, 0x13, 0x22, 0x64, 0x96, 0x6E, 0x40, 0x04, 0x00, 0x7C, 0x00, + /* 'A' 0x41 */ 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, + /* 'B' 0x42 */ 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xF8, + /* 'C' 0x43 */ 0x3E, 0x41, 0x80, 0x80, 0x80, 0x80, 0x81, 0x43, 0x3E, + /* 'D' 0x44 */ 0xF9, 0x0A, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xF8, + /* 'E' 0x45 */ 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0xFC, + /* 'F' 0x46 */ 0xFC, 0x21, 0x0F, 0xC2, 0x10, 0x80, + /* 'G' 0x47 */ 0x3E, 0x41, 0x80, 0x80, 0x87, 0x81, 0xC1, 0x43, 0x3D, + /* 'H' 0x48 */ 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, + /* 'I' 0x49 */ 0xFF, 0x80, + /* 'J' 0x4A */ 0x08, 0x42, 0x10, 0x86, 0x31, 0x70, + /* 'K' 0x4B */ 0x86, 0x29, 0x28, 0xD2, 0x48, 0xA1, 0x84, + /* 'L' 0x4C */ 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, + /* 'M' 0x4D */ 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, + /* 'N' 0x4E */ 0xC3, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, + /* 'O' 0x4F */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3E, 0x00, + /* 'P' 0x50 */ 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, + /* 'Q' 0x51 */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3F, 0x00, 0x40, + /* 'R' 0x52 */ 0xF9, 0x0A, 0x14, 0x2F, 0x90, 0xA1, 0x42, 0x86, + /* 'S' 0x53 */ 0x7A, 0x18, 0x30, 0x78, 0x38, 0x71, 0x78, + /* 'T' 0x54 */ 0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, + /* 'U' 0x55 */ 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE3, 0x7C, + /* 'V' 0x56 */ 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, + /* 'W' 0x57 */ 0x84, 0x38, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0xD2, 0x8C, 0x61, 0x8C, 0x31, 0x80, + /* 'X' 0x58 */ 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, + /* 'Y' 0x59 */ 0x82, 0x89, 0x11, 0x43, 0x82, 0x04, 0x08, 0x10, + /* 'Z' 0x5A */ 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, + /* '[' 0x5B */ 0xEA, 0xAA, 0xAB, + /* '\' 0x5C */ 0x92, 0x24, 0x91, 0x20, + /* ']' 0x5D */ 0xD5, 0x55, 0x57, + /* '^' 0x5E */ 0x46, 0xA9, 0x10, + /* '_' 0x5F */ 0xFE, + /* '`' 0x60 */ 0x80, + /* 'a' 0x61 */ 0x79, 0x08, 0x11, 0xEC, 0x51, 0x9D, 0x80, + /* 'b' 0x62 */ 0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF0, + /* 'c' 0x63 */ 0x7B, 0x18, 0x20, 0x83, 0x17, 0x80, + /* 'd' 0x64 */ 0x04, 0x17, 0xF3, 0x86, 0x18, 0x73, 0x74, + /* 'e' 0x65 */ 0x7B, 0x38, 0x7F, 0x83, 0x17, 0x80, + /* 'f' 0x66 */ 0x6B, 0xA4, 0x92, 0x40, + /* 'g' 0x67 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x8D, 0xE0, + /* 'h' 0x68 */ 0x84, 0x2D, 0x98, 0xC6, 0x31, 0x88, + /* 'i' 0x69 */ 0xBF, 0x80, + /* 'j' 0x6A */ 0x45, 0x55, 0x57, + /* 'k' 0x6B */ 0x84, 0x25, 0x6E, 0x72, 0x52, 0x88, + /* 'l' 0x6C */ 0xFF, 0x80, + /* 'm' 0x6D */ 0xFF, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, + /* 'n' 0x6E */ 0xB6, 0x63, 0x18, 0xC6, 0x20, + /* 'o' 0x6F */ 0x7B, 0x38, 0x61, 0x87, 0x37, 0x80, + /* 'p' 0x70 */ 0xF6, 0xE3, 0x18, 0xEF, 0xD0, 0x80, + /* 'q' 0x71 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x04, + /* 'r' 0x72 */ 0xBA, 0x49, 0x20, + /* 's' 0x73 */ 0x69, 0x8E, 0x19, 0x60, + /* 't' 0x74 */ 0x5D, 0x24, 0x93, + /* 'u' 0x75 */ 0x8C, 0x63, 0x18, 0xCD, 0xA0, + /* 'v' 0x76 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, + /* 'w' 0x77 */ 0x89, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26, + /* 'x' 0x78 */ 0x4A, 0x4C, 0x43, 0x27, 0x20, + /* 'y' 0x79 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x08, 0x21, 0x80, + /* 'z' 0x7A */ 0x78, 0x44, 0x46, 0x23, 0xE0, + /* '{' 0x7B */ 0x69, 0x25, 0xB2, 0x49, 0x30, + /* '|' 0x7C */ 0xFF, 0xE0, + /* '}' 0x7D */ 0xC9, 0x24, 0xDA, 0x49, 0x60, + /* '~' 0x7E */ 0x66, 0x70, +}; -const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = {{0, 0, 0, 3, 0, 1}, // 0x20 ' ' - {0, 2, 9, 4, 1, -8}, // 0x21 '!' - {3, 4, 3, 4, 0, -8}, // 0x22 '"' - {5, 7, 8, 7, 0, -7}, // 0x23 '#' - {12, 6, 11, 7, 0, -9}, // 0x24 '$' - {21, 10, 9, 11, 0, -8}, // 0x25 '%' - {33, 7, 9, 8, 1, -8}, // 0x26 '&' - {41, 1, 3, 2, 1, -8}, // 0x27 ''' - {42, 2, 11, 4, 1, -8}, // 0x28 '(' - {45, 3, 11, 4, 0, -8}, // 0x29 ')' - {50, 4, 3, 5, 0, -8}, // 0x2A '*' - {52, 5, 5, 7, 1, -4}, // 0x2B '+' - {56, 1, 3, 3, 1, 0}, // 0x2C ',' - {57, 2, 1, 4, 1, -3}, // 0x2D '-' - {58, 1, 1, 3, 1, 0}, // 0x2E '.' - {59, 3, 9, 3, 0, -8}, // 0x2F '/' - {63, 5, 9, 7, 1, -8}, // 0x30 '0' - {69, 3, 9, 7, 1, -8}, // 0x31 '1' - {73, 6, 9, 7, 0, -8}, // 0x32 '2' - {80, 6, 9, 7, 0, -8}, // 0x33 '3' - {87, 6, 9, 7, 0, -8}, // 0x34 '4' - {94, 6, 9, 7, 0, -8}, // 0x35 '5' - {101, 5, 9, 7, 1, -8}, // 0x36 '6' - {107, 5, 9, 7, 1, -8}, // 0x37 '7' - {113, 6, 9, 7, 0, -8}, // 0x38 '8' - {120, 6, 9, 7, 0, -8}, // 0x39 '9' - {127, 1, 7, 3, 1, -6}, // 0x3A ':' - {128, 1, 8, 3, 1, -5}, // 0x3B ';' - {129, 5, 6, 7, 1, -5}, // 0x3C '<' - {133, 5, 3, 7, 1, -3}, // 0x3D '=' - {135, 5, 6, 7, 1, -5}, // 0x3E '>' - {139, 5, 9, 7, 1, -8}, // 0x3F '?' - {145, 11, 11, 12, 0, -8}, // 0x40 '@' - {161, 8, 9, 8, 0, -8}, // 0x41 'A' - {170, 6, 9, 8, 1, -8}, // 0x42 'B' - {177, 8, 9, 9, 0, -8}, // 0x43 'C' - {186, 7, 9, 8, 1, -8}, // 0x44 'D' - {194, 6, 9, 8, 1, -8}, // 0x45 'E' - {201, 6, 9, 7, 1, -8}, // 0x46 'F' - {208, 8, 9, 9, 0, -8}, // 0x47 'G' - {217, 7, 9, 9, 1, -8}, // 0x48 'H' - {225, 1, 9, 3, 1, -8}, // 0x49 'I' - {227, 5, 9, 6, 0, -8}, // 0x4A 'J' - {233, 7, 9, 8, 1, -8}, // 0x4B 'K' - {241, 5, 9, 7, 1, -8}, // 0x4C 'L' - {247, 8, 9, 10, 1, -8}, // 0x4D 'M' - {256, 7, 9, 9, 1, -8}, // 0x4E 'N' - {264, 9, 9, 9, 0, -8}, // 0x4F 'O' - {275, 6, 9, 8, 1, -8}, // 0x50 'P' - {282, 9, 10, 9, 0, -8}, // 0x51 'Q' - {294, 7, 9, 9, 1, -8}, // 0x52 'R' - {302, 6, 9, 8, 1, -8}, // 0x53 'S' - {309, 7, 9, 8, 0, -8}, // 0x54 'T' - {317, 7, 9, 9, 1, -8}, // 0x55 'U' - {325, 8, 9, 8, 0, -8}, // 0x56 'V' - {334, 11, 9, 11, 0, -8}, // 0x57 'W' - {347, 8, 9, 8, 0, -8}, // 0x58 'X' - {356, 8, 9, 8, 0, -8}, // 0x59 'Y' - {365, 7, 9, 7, 0, -8}, // 0x5A 'Z' - {373, 2, 12, 3, 1, -8}, // 0x5B '[' - {376, 3, 9, 3, 0, -8}, // 0x5C '\' - {380, 3, 12, 3, 0, -8}, // 0x5D ']' - {385, 4, 5, 6, 1, -8}, // 0x5E '^' - {388, 7, 1, 7, 0, 2}, // 0x5F '_' - {389, 3, 1, 3, 0, -8}, // 0x60 '`' - {390, 6, 7, 7, 0, -6}, // 0x61 'a' - {396, 5, 9, 7, 1, -8}, // 0x62 'b' - {402, 6, 7, 6, 0, -6}, // 0x63 'c' - {408, 6, 9, 7, 0, -8}, // 0x64 'd' - {415, 6, 7, 6, 0, -6}, // 0x65 'e' - {421, 3, 9, 3, 0, -8}, // 0x66 'f' - {425, 6, 10, 7, 0, -6}, // 0x67 'g' - {433, 5, 9, 6, 1, -8}, // 0x68 'h' - {439, 1, 9, 3, 1, -8}, // 0x69 'i' - {441, 2, 12, 3, 0, -8}, // 0x6A 'j' - {444, 5, 9, 6, 1, -8}, // 0x6B 'k' - {450, 1, 9, 3, 1, -8}, // 0x6C 'l' - {452, 8, 7, 10, 1, -6}, // 0x6D 'm' - {459, 5, 7, 6, 1, -6}, // 0x6E 'n' - {464, 6, 7, 6, 0, -6}, // 0x6F 'o' - {470, 5, 9, 7, 1, -6}, // 0x70 'p' - {476, 6, 9, 7, 0, -6}, // 0x71 'q' - {483, 3, 7, 4, 1, -6}, // 0x72 'r' - {486, 6, 7, 6, 0, -6}, // 0x73 's' - {492, 3, 8, 3, 0, -7}, // 0x74 't' - {495, 5, 7, 6, 1, -6}, // 0x75 'u' - {500, 6, 7, 6, 0, -6}, // 0x76 'v' - {506, 9, 7, 9, 0, -6}, // 0x77 'w' - {514, 6, 7, 6, 0, -6}, // 0x78 'x' - {520, 6, 10, 6, 0, -6}, // 0x79 'y' - {528, 5, 7, 6, 0, -6}, // 0x7A 'z' - {533, 2, 12, 4, 1, -8}, // 0x7B '{' - {536, 1, 11, 3, 1, -8}, // 0x7C '|' - {538, 2, 12, 4, 1, -8}, // 0x7D '}' - {541, 6, 2, 6, 0, -4}}; // 0x7E '~' +const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 3, 0, 0}, + /* '!' 0x21 */ {0, 1, 9, 4, 2, -8}, + /* '"' 0x22 */ {2, 3, 3, 4, 0, -8}, + /* '#' 0x23 */ {4, 7, 8, 7, 0, -7}, + /* '$' 0x24 */ {11, 5, 11, 7, 1, -9}, + /* '%' 0x25 */ {18, 10, 9, 11, 0, -8}, + /* '&' 0x26 */ {30, 6, 9, 8, 1, -8}, + /* ''' 0x27 */ {37, 1, 3, 2, 1, -8}, + /* '(' 0x28 */ {38, 2, 11, 4, 1, -8}, + /* ')' 0x29 */ {41, 3, 11, 4, 0, -8}, + /* '*' 0x2A */ {46, 3, 3, 5, 1, -8}, + /* '+' 0x2B */ {48, 5, 5, 7, 1, -4}, + /* ',' 0x2C */ {52, 1, 3, 3, 1, 0}, + /* '-' 0x2D */ {53, 3, 1, 4, 1, -3}, + /* '.' 0x2E */ {54, 1, 1, 3, 1, 0}, + /* '/' 0x2F */ {55, 3, 9, 3, 0, -8}, + /* '0' 0x30 */ {59, 5, 9, 7, 1, -8}, + /* '1' 0x31 */ {65, 2, 9, 7, 2, -8}, + /* '2' 0x32 */ {68, 5, 9, 7, 1, -8}, + /* '3' 0x33 */ {74, 5, 9, 7, 1, -8}, + /* '4' 0x34 */ {80, 5, 9, 7, 1, -8}, + /* '5' 0x35 */ {86, 6, 9, 7, 0, -8}, + /* '6' 0x36 */ {93, 5, 9, 7, 1, -8}, + /* '7' 0x37 */ {99, 5, 9, 7, 1, -8}, + /* '8' 0x38 */ {105, 6, 9, 7, 0, -8}, + /* '9' 0x39 */ {112, 6, 9, 7, 0, -8}, + /* ':' 0x3A */ {119, 1, 7, 3, 1, -6}, + /* ';' 0x3B */ {120, 1, 8, 3, 1, -5}, + /* '<' 0x3C */ {121, 5, 5, 7, 1, -4}, + /* '=' 0x3D */ {125, 5, 3, 7, 1, -3}, + /* '>' 0x3E */ {127, 5, 5, 7, 1, -4}, + /* '?' 0x3F */ {131, 5, 9, 7, 1, -8}, + /* '@' 0x40 */ {137, 11, 11, 12, 0, -8}, + /* 'A' 0x41 */ {153, 8, 9, 8, 0, -8}, + /* 'B' 0x42 */ {162, 6, 9, 8, 1, -8}, + /* 'C' 0x43 */ {169, 8, 9, 9, 0, -8}, + /* 'D' 0x44 */ {178, 7, 9, 8, 1, -8}, + /* 'E' 0x45 */ {186, 6, 9, 8, 1, -8}, + /* 'F' 0x46 */ {193, 5, 9, 7, 1, -8}, + /* 'G' 0x47 */ {199, 8, 9, 9, 0, -8}, + /* 'H' 0x48 */ {208, 7, 9, 9, 1, -8}, + /* 'I' 0x49 */ {216, 1, 9, 3, 1, -8}, + /* 'J' 0x4A */ {218, 5, 9, 6, 0, -8}, + /* 'K' 0x4B */ {224, 6, 9, 8, 1, -8}, + /* 'L' 0x4C */ {231, 5, 9, 7, 1, -8}, + /* 'M' 0x4D */ {237, 8, 9, 10, 1, -8}, + /* 'N' 0x4E */ {246, 7, 9, 9, 1, -8}, + /* 'O' 0x4F */ {254, 9, 9, 9, 0, -8}, + /* 'P' 0x50 */ {265, 6, 9, 8, 1, -8}, + /* 'Q' 0x51 */ {272, 9, 10, 9, 0, -8}, + /* 'R' 0x52 */ {284, 7, 9, 9, 1, -8}, + /* 'S' 0x53 */ {292, 6, 9, 8, 1, -8}, + /* 'T' 0x54 */ {299, 6, 9, 8, 0, -8}, + /* 'U' 0x55 */ {306, 7, 9, 9, 1, -8}, + /* 'V' 0x56 */ {314, 7, 9, 8, 0, -8}, + /* 'W' 0x57 */ {322, 11, 9, 11, 0, -8}, + /* 'X' 0x58 */ {335, 6, 9, 8, 1, -8}, + /* 'Y' 0x59 */ {342, 7, 9, 8, 1, -8}, + /* 'Z' 0x5A */ {350, 7, 9, 7, 0, -8}, + /* '[' 0x5B */ {358, 2, 12, 3, 1, -8}, + /* '\' 0x5C */ {361, 3, 9, 3, 0, -8}, + /* ']' 0x5D */ {365, 2, 12, 3, 0, -8}, + /* '^' 0x5E */ {368, 4, 5, 6, 1, -8}, + /* '_' 0x5F */ {371, 7, 1, 7, 0, 2}, + /* '`' 0x60 */ {372, 1, 1, 3, 1, -8}, + /* 'a' 0x61 */ {373, 7, 7, 7, 0, -6}, + /* 'b' 0x62 */ {380, 5, 9, 7, 1, -8}, + /* 'c' 0x63 */ {386, 6, 7, 6, 0, -6}, + /* 'd' 0x64 */ {392, 6, 9, 7, 0, -8}, + /* 'e' 0x65 */ {399, 6, 7, 6, 0, -6}, + /* 'f' 0x66 */ {405, 3, 9, 3, 0, -8}, + /* 'g' 0x67 */ {409, 6, 10, 7, 0, -6}, + /* 'h' 0x68 */ {417, 5, 9, 6, 1, -8}, + /* 'i' 0x69 */ {423, 1, 9, 3, 1, -8}, + /* 'j' 0x6A */ {425, 2, 12, 3, 0, -8}, + /* 'k' 0x6B */ {428, 5, 9, 6, 1, -8}, + /* 'l' 0x6C */ {434, 1, 9, 3, 1, -8}, + /* 'm' 0x6D */ {436, 8, 7, 10, 1, -6}, + /* 'n' 0x6E */ {443, 5, 7, 6, 1, -6}, + /* 'o' 0x6F */ {448, 6, 7, 6, 0, -6}, + /* 'p' 0x70 */ {454, 5, 9, 7, 1, -6}, + /* 'q' 0x71 */ {460, 6, 9, 7, 0, -6}, + /* 'r' 0x72 */ {467, 3, 7, 4, 1, -6}, + /* 's' 0x73 */ {470, 4, 7, 6, 1, -6}, + /* 't' 0x74 */ {474, 3, 8, 3, 0, -7}, + /* 'u' 0x75 */ {477, 5, 7, 6, 1, -6}, + /* 'v' 0x76 */ {482, 6, 7, 6, 0, -6}, + /* 'w' 0x77 */ {488, 8, 7, 9, 0, -6}, + /* 'x' 0x78 */ {495, 5, 7, 6, 0, -6}, + /* 'y' 0x79 */ {500, 6, 10, 6, 0, -6}, + /* 'z' 0x7A */ {508, 5, 7, 6, 0, -6}, + /* '{' 0x7B */ {513, 3, 12, 4, 0, -8}, + /* '|' 0x7C */ {518, 1, 11, 3, 1, -8}, + /* '}' 0x7D */ {520, 3, 12, 4, 1, -8}, + /* '~' 0x7E */ {525, 6, 2, 6, 0, -4}, +}; const GFXfont FreeSans6pt7b PROGMEM = {(uint8_t *)FreeSans6pt7bBitmaps, (GFXglyph *)FreeSans6pt7bGlyphs, 0x20, 0x7E, 14}; - -// Approx. 1215 bytes diff --git a/src/graphics/niche/Fonts/FreeSans6pt8bCyrillic.h b/src/graphics/niche/Fonts/FreeSans6pt8bCyrillic.h deleted file mode 100644 index d222cd1c3..000000000 --- a/src/graphics/niche/Fonts/FreeSans6pt8bCyrillic.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - -Uses Windows-1251 encoding to map translingual Cyrillic characters to range between (uint8_t)127 and (uint8_t)255 -https://en.wikipedia.org/wiki/Windows-1251 - -Cyrillic characters present to the firmware as UTF8. -A NicheGraphics implementation needs to identify these, and substitute the appropriate Windows-1251 char value. - -*/ - -#pragma once - -const uint8_t FreeSans6pt8bCyrillicBitmaps[] PROGMEM = { - 0xFF, 0xA0, 0xC0, 0xFF, 0xA0, 0xC0, 0xB6, 0x80, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x31, 0x75, 0x54, 0x78, 0x79, 0x75, - 0x7C, 0x41, 0x00, 0x01, 0x1C, 0x49, 0x22, 0x50, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0xC0, 0x21, 0x44, 0x94, 0x62, 0x59, 0xE2, - 0xF4, 0xE0, 0x6A, 0xAA, 0x90, 0x48, 0x92, 0x49, 0x4A, 0x00, 0x5D, 0x40, 0x21, 0x09, 0xF2, 0x10, 0xE0, 0xC0, 0x80, 0x25, 0x25, - 0x24, 0x26, 0xA3, 0x18, 0xC6, 0x31, 0xF0, 0x27, 0x92, 0x49, 0x20, 0x11, 0xB4, 0x41, 0x0C, 0xC6, 0x10, 0xFC, 0x26, 0xA2, 0x13, - 0x04, 0x31, 0xF0, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0xFF, 0xE1, 0x4D, 0x84, 0x31, 0xF0, 0x26, 0xE3, 0x0F, 0x46, 0x31, - 0xF0, 0xFF, 0xC4, 0x22, 0x11, 0x08, 0x40, 0x11, 0xA4, 0x51, 0x39, 0x1C, 0x51, 0x78, 0x11, 0xA4, 0x71, 0x45, 0xF0, 0x51, 0x78, - 0xC0, 0x30, 0xC0, 0x36, 0x1F, 0x20, 0xE0, 0x80, 0xF8, 0x3E, 0xC1, 0xC2, 0xE8, 0x00, 0x74, 0x62, 0x11, 0x10, 0x80, 0x20, 0x0F, - 0x06, 0x18, 0x81, 0xA7, 0xD4, 0x93, 0x22, 0x64, 0x4A, 0x7E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x1C, 0x24, 0x24, 0x7E, - 0x42, 0x42, 0xC3, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xF9, 0x1A, 0x1C, - 0x18, 0x30, 0x60, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x3C, 0x46, - 0x82, 0x80, 0x8F, 0x81, 0x83, 0xC3, 0x7D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x86, - 0x31, 0x78, 0x87, 0x1A, 0x65, 0x8F, 0x1A, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, - 0xA5, 0x99, 0x99, 0x99, 0x83, 0x87, 0x8D, 0x19, 0x32, 0x62, 0xC3, 0x86, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC2, - 0x3E, 0x00, 0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x3F, 0x00, 0xFD, - 0x0E, 0x0C, 0x1F, 0xD0, 0xA0, 0xC1, 0x82, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, - 0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC3, 0x7C, 0xC3, 0x42, 0x42, 0x26, 0x24, 0x24, 0x14, 0x18, 0x18, 0xC4, 0x28, 0xC5, - 0x39, 0xA5, 0x24, 0xA4, 0x52, 0x8C, 0x71, 0x8C, 0x30, 0x80, 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, 0xC3, 0x42, 0x26, 0x24, - 0x18, 0x18, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x10, 0x41, 0x06, 0x08, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24, 0x89, 0x20, 0xED, - 0xB6, 0xDB, 0x6D, 0xF0, 0x46, 0xAA, 0x90, 0xFC, 0x90, 0xFC, 0x4F, 0x98, 0xFC, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0xF0, 0x79, 0x18, - 0x20, 0x45, 0xE0, 0x04, 0x10, 0x5F, 0xC6, 0x18, 0x51, 0x7C, 0xFC, 0x7F, 0x08, 0xF8, 0x29, 0x74, 0x92, 0x40, 0x7D, 0x18, 0x61, - 0x45, 0xF0, 0x52, 0x30, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0x88, 0xDF, 0x80, 0x51, 0x55, 0x56, 0x84, 0x21, 0x2A, 0x72, 0x92, 0x98, - 0xFF, 0x80, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFC, 0x63, 0x18, 0xC4, 0x79, 0x18, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xFA, - 0x10, 0x80, 0x7D, 0x18, 0x61, 0x45, 0xF0, 0x41, 0x04, 0xF2, 0x49, 0x00, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0x4B, 0xA4, 0x93, 0x8C, - 0x63, 0x18, 0xFC, 0xCD, 0x24, 0x94, 0x30, 0xC0, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26, 0x96, 0x66, 0x99, 0xCA, 0x52, 0x63, 0x18, - 0x84, 0x40, 0x78, 0xC4, 0x44, 0x7C, 0x6A, 0xAA, 0xA9, 0xFF, 0xF0, 0xC9, 0x24, 0x4A, 0x49, 0x40, 0xE8, 0xC0, 0xFE, 0x18, 0x61, - 0x86, 0x18, 0x61, 0xFC, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, 0x10, 0x8F, 0xE0, 0x82, - 0x08, 0x20, 0x82, 0x08, 0x00, 0x64, 0x0F, 0x88, 0x88, 0x80, 0x3D, 0x0C, 0x2E, 0xF9, 0x04, 0x0F, 0x7C, 0x08, 0x81, 0x10, 0x22, - 0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, 0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0, - 0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0x83, - 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, 0x78, 0x24, 0x13, - 0xC9, 0x14, 0x8E, 0x7C, 0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, 0x60, 0x9A, 0xCC, 0xA9, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, - 0x44, 0x8C, 0x63, 0x18, 0xFC, 0x80, 0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, 0x70, 0x22, 0x95, 0xA8, 0xC4, - 0x23, 0x10, 0x08, 0x42, 0x10, 0x86, 0x31, 0x78, 0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, 0x28, 0x0F, 0xE0, 0x82, 0x0F, - 0xE0, 0x82, 0x0F, 0xC0, 0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, 0x51, 0x55, 0x56, 0xA1, 0x24, 0x92, 0x49, 0x00, 0xFF, - 0x80, 0xDF, 0x80, 0x27, 0xC9, 0x24, 0x8A, 0x28, 0xA2, 0x8B, 0xF8, 0x20, 0x80, 0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, 0x88, - 0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x89, 0x80, 0x79, 0x1F, 0x30, 0x45, 0xE0, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, - 0x7C, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0xB4, 0x24, 0x92, 0x40, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, 0xFE, 0x08, - 0x20, 0xFE, 0x18, 0x61, 0xFC, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, 0x1F, 0x08, - 0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0x88, 0xA4, 0x9A, - 0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, 0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, 0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68, - 0xE1, 0xC2, 0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, 0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, 0x3E, 0x44, - 0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, - 0xC1, 0x82, 0x3C, 0x46, 0x83, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, 0xFA, 0x18, - 0x61, 0xFE, 0x08, 0x20, 0x80, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, - 0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, 0x08, 0x1E, 0x32, 0xD1, 0x38, 0x8C, 0x4F, 0x2C, 0xFC, 0x08, 0x00, 0x87, 0x34, - 0x8C, 0x30, 0xC4, 0xB3, 0x84, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, 0x8E, 0x38, 0xE3, 0x8D, 0xF0, - 0xC3, 0x0C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, 0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF, - 0x80, 0x40, 0x20, 0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC, - 0x2E, 0x17, 0x0B, 0xF9, 0x80, 0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, 0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, 0x87, - 0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, 0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, 0x79, 0x11, 0xD9, - 0xCD, 0xD0, 0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, 0xF4, 0xBD, 0x29, 0xF8, 0xF8, 0x88, 0x88, 0x3C, 0x48, 0x91, 0x22, 0x5F, - 0xE0, 0x80, 0x79, 0x1F, 0xF0, 0x45, 0xE0, 0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, 0x78, 0x23, 0x82, 0xCD, 0xE0, 0x9C, 0xEB, 0x5C, - 0xC4, 0x70, 0x27, 0x3A, 0xD7, 0x31, 0x9A, 0xCC, 0xA9, 0x7A, 0x52, 0x94, 0xE4, 0x8F, 0x3D, 0x6D, 0xA6, 0x90, 0x8C, 0x7F, 0x18, - 0xC4, 0x79, 0x1C, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xC4, 0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, 0x79, 0x1C, 0x30, 0x45, 0xE0, - 0xF9, 0x08, 0x42, 0x10, 0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, 0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04, - 0x01, 0x00, 0x40, 0x4B, 0x8C, 0x65, 0xE4, 0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, 0x99, 0x97, 0x11, 0x96, 0x59, 0x65, 0x97, 0xF0, - 0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, 0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, 0x86, 0x1F, 0x63, 0x8F, 0xD0, 0x84, 0x3D, 0x18, - 0xF8, 0xF4, 0xDE, 0x19, 0xF8, 0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, 0xFC, 0x7E, 0xD4, 0xC4, -}; - -const GFXglyph FreeSans6pt8bCyrillicGlyphs[] PROGMEM = { - {0, 0, 0, 3, 0, 0}, // 0x20 ' ' - {3, 2, 9, 3, 1, -8}, // 0x21 '!' - {6, 3, 3, 4, 1, -8}, // 0x22 '"' - {8, 7, 8, 7, 0, -7}, // 0x23 '#' - {15, 6, 11, 7, 0, -8}, // 0x24 '$' - {24, 10, 9, 11, 0, -8}, // 0x25 '%' - {36, 6, 9, 8, 1, -8}, // 0x26 '&' - {43, 1, 3, 2, 1, -8}, // 0x27 ''' - {44, 2, 10, 4, 1, -7}, // 0x28 '(' - {47, 3, 11, 4, 0, -7}, // 0x29 ')' - {52, 3, 4, 5, 1, -8}, // 0x2A '*' - {54, 5, 6, 7, 1, -5}, // 0x2B '+' - {58, 1, 3, 3, 1, 0}, // 0x2C ',' - {59, 2, 1, 4, 1, -3}, // 0x2D '-' - {60, 1, 1, 3, 1, 0}, // 0x2E '.' - {61, 3, 8, 3, 0, -7}, // 0x2F '/' - {64, 5, 9, 7, 1, -8}, // 0x30 '0' - {70, 3, 9, 7, 1, -8}, // 0x31 '1' - {74, 6, 9, 7, 0, -8}, // 0x32 '2' - {81, 5, 9, 7, 1, -8}, // 0x33 '3' - {87, 6, 9, 7, 0, -8}, // 0x34 '4' - {94, 5, 9, 7, 1, -8}, // 0x35 '5' - {100, 5, 9, 7, 1, -8}, // 0x36 '6' - {106, 5, 9, 7, 1, -8}, // 0x37 '7' - {112, 6, 9, 7, 0, -8}, // 0x38 '8' - {119, 6, 9, 7, 0, -8}, // 0x39 '9' - {126, 2, 6, 3, 1, -5}, // 0x3A ':' - {128, 2, 8, 3, 1, -5}, // 0x3B ';' - {130, 5, 5, 7, 1, -4}, // 0x3C '<' - {134, 5, 3, 7, 1, -3}, // 0x3D '=' - {136, 5, 5, 7, 1, -4}, // 0x3E '>' - {140, 5, 9, 7, 1, -8}, // 0x3F '?' - {146, 11, 11, 12, 0, -8}, // 0x40 '@' - {162, 8, 9, 8, 0, -8}, // 0x41 'A' - {171, 6, 9, 8, 1, -8}, // 0x42 'B' - {178, 7, 9, 9, 1, -8}, // 0x43 'C' - {186, 7, 9, 9, 1, -8}, // 0x44 'D' - {194, 6, 9, 8, 1, -8}, // 0x45 'E' - {201, 6, 9, 7, 1, -8}, // 0x46 'F' - {208, 8, 9, 9, 1, -8}, // 0x47 'G' - {217, 7, 9, 9, 1, -8}, // 0x48 'H' - {225, 1, 9, 3, 1, -8}, // 0x49 'I' - {227, 5, 9, 6, 0, -8}, // 0x4A 'J' - {233, 7, 9, 8, 1, -8}, // 0x4B 'K' - {241, 5, 9, 7, 1, -8}, // 0x4C 'L' - {247, 8, 9, 10, 1, -8}, // 0x4D 'M' - {256, 7, 9, 9, 1, -8}, // 0x4E 'N' - {264, 9, 9, 9, 0, -8}, // 0x4F 'O' - {275, 6, 9, 8, 1, -8}, // 0x50 'P' - {282, 9, 9, 9, 0, -8}, // 0x51 'Q' - {293, 7, 9, 9, 1, -8}, // 0x52 'R' - {301, 6, 9, 8, 1, -8}, // 0x53 'S' - {308, 7, 9, 7, 0, -8}, // 0x54 'T' - {316, 7, 9, 9, 1, -8}, // 0x55 'U' - {324, 8, 9, 8, 0, -8}, // 0x56 'V' - {333, 11, 9, 11, 0, -8}, // 0x57 'W' - {346, 6, 9, 8, 1, -8}, // 0x58 'X' - {353, 8, 9, 8, 0, -8}, // 0x59 'Y' - {362, 7, 9, 7, 0, -8}, // 0x5A 'Z' - {370, 2, 12, 3, 1, -8}, // 0x5B '[' - {373, 3, 9, 3, 0, -8}, // 0x5C '\' - {377, 3, 12, 3, 0, -8}, // 0x5D ']' - {382, 4, 5, 6, 1, -8}, // 0x5E '^' - {385, 6, 1, 7, 0, 2}, // 0x5F '_' - {386, 2, 2, 4, 1, -8}, // 0x60 '`' - {387, 5, 6, 7, 1, -5}, // 0x61 'a' - {391, 5, 9, 7, 1, -8}, // 0x62 'b' - {397, 6, 6, 6, 0, -5}, // 0x63 'c' - {402, 6, 9, 7, 0, -8}, // 0x64 'd' - {409, 5, 6, 7, 1, -5}, // 0x65 'e' - {413, 3, 9, 3, 0, -8}, // 0x66 'f' - {417, 6, 9, 7, 0, -5}, // 0x67 'g' - {424, 5, 9, 7, 1, -8}, // 0x68 'h' - {430, 1, 9, 3, 1, -8}, // 0x69 'i' - {432, 2, 12, 3, 0, -8}, // 0x6A 'j' - {435, 5, 9, 6, 1, -8}, // 0x6B 'k' - {441, 1, 9, 3, 1, -8}, // 0x6C 'l' - {443, 8, 6, 10, 1, -5}, // 0x6D 'm' - {449, 5, 6, 7, 1, -5}, // 0x6E 'n' - {453, 6, 6, 7, 0, -5}, // 0x6F 'o' - {458, 5, 9, 7, 1, -5}, // 0x70 'p' - {464, 6, 9, 7, 0, -5}, // 0x71 'q' - {471, 3, 6, 4, 1, -5}, // 0x72 'r' - {474, 6, 6, 6, 0, -5}, // 0x73 's' - {479, 3, 8, 3, 0, -7}, // 0x74 't' - {482, 5, 6, 7, 1, -5}, // 0x75 'u' - {486, 6, 6, 6, 0, -5}, // 0x76 'v' - {491, 8, 6, 9, 0, -5}, // 0x77 'w' - {497, 4, 6, 6, 1, -5}, // 0x78 'x' - {500, 5, 9, 6, 0, -5}, // 0x79 'y' - {506, 5, 6, 6, 0, -5}, // 0x7A 'z' - {510, 2, 12, 4, 1, -8}, // 0x7B '{' - {513, 1, 12, 3, 1, -8}, // 0x7C '|' - {515, 3, 12, 4, 0, -8}, // 0x7D '}' - {520, 5, 2, 7, 1, -4}, // 0x7E '~' - {522, 6, 9, 8, 1, -8}, // - {529, 9, 11, 9, 0, -8}, // - {542, 6, 11, 7, 1, -10}, // - {551, 0, 0, 8, 0, 0}, // - {551, 4, 9, 5, 1, -8}, // - {556, 0, 0, 8, 0, 0}, // - {556, 0, 0, 8, 0, 0}, // - {556, 0, 0, 8, 0, 0}, // - {556, 0, 0, 8, 0, 0}, // - {556, 6, 8, 8, 1, -7}, // - {562, 0, 0, 8, 0, 0}, // - {562, 11, 9, 13, 1, -8}, // - {575, 0, 0, 8, 0, 0}, // - {575, 11, 9, 12, 1, -8}, // - {588, 6, 11, 8, 1, -10}, // - {597, 9, 9, 9, 0, -8}, // - {608, 7, 11, 9, 1, -8}, // - {618, 6, 11, 7, 0, -8}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 0, 0, 8, 0, 0}, // - {627, 9, 6, 10, 0, -5}, // - {634, 0, 0, 8, 0, 0}, // - {634, 9, 6, 10, 1, -5}, // - {641, 4, 8, 6, 1, -7}, // - {645, 6, 9, 7, 0, -8}, // - {652, 5, 7, 7, 1, -5}, // - {657, 0, 0, 8, 0, 0}, // - {657, 7, 11, 7, 0, -10}, // - {667, 5, 11, 6, 0, -7}, // - {674, 5, 9, 6, 0, -8}, // - {680, 0, 0, 8, 0, 0}, // - {680, 6, 10, 7, 1, -9}, // - {688, 0, 0, 8, 0, 0}, // - {688, 0, 0, 8, 0, 0}, // - {688, 6, 11, 8, 1, -10}, // - {697, 7, 9, 9, 1, -8}, // - {705, 0, 0, 8, 0, 0}, // - {705, 0, 0, 8, 0, 0}, // - {705, 2, 12, 3, 0, -8}, // - {708, 0, 0, 8, 0, 0}, // - {708, 0, 0, 8, 0, 0}, // - {708, 3, 11, 3, 0, -10}, // - {713, 0, 0, 8, 0, 0}, // - {713, 0, 0, 8, 0, 0}, // - {713, 1, 9, 3, 1, -8}, // - {715, 1, 9, 3, 1, -8}, // - {717, 3, 8, 5, 1, -7}, // - {720, 6, 9, 7, 1, -5}, // - {727, 0, 0, 8, 0, 0}, // - {727, 0, 0, 8, 0, 0}, // - {727, 6, 9, 7, 0, -8}, // - {734, 9, 9, 11, 1, -8}, // - {745, 6, 6, 6, 0, -5}, // - {750, 0, 0, 8, 0, 0}, // - {750, 0, 0, 8, 0, 0}, // - {750, 6, 9, 8, 1, -8}, // - {757, 6, 6, 6, 0, -5}, // - {762, 3, 9, 3, 0, -8}, // - {766, 8, 9, 8, 0, -8}, // - {775, 6, 9, 8, 1, -8}, // - {782, 6, 9, 8, 1, -8}, // - {789, 6, 9, 7, 1, -8}, // - {796, 9, 11, 10, 0, -8}, // - {809, 6, 9, 8, 1, -8}, // - {816, 9, 9, 11, 1, -8}, // - {827, 6, 9, 8, 1, -8}, // - {834, 7, 9, 9, 1, -8}, // - {842, 7, 11, 9, 1, -10}, // - {852, 6, 9, 8, 1, -8}, // - {859, 7, 9, 8, 0, -8}, // - {867, 8, 9, 10, 1, -8}, // - {876, 7, 9, 9, 1, -8}, // - {884, 8, 9, 10, 1, -8}, // - {893, 7, 9, 9, 1, -8}, // - {901, 6, 9, 8, 1, -8}, // - {908, 7, 9, 9, 1, -8}, // - {916, 7, 9, 7, 0, -8}, // - {924, 7, 9, 7, 0, -8}, // - {932, 9, 9, 10, 1, -8}, // - {943, 6, 9, 8, 1, -8}, // - {950, 8, 11, 9, 1, -8}, // - {961, 6, 9, 8, 1, -8}, // - {968, 8, 9, 10, 1, -8}, // - {977, 9, 11, 10, 1, -8}, // - {990, 10, 9, 10, 0, -8}, // - {1002, 9, 9, 10, 1, -8}, // - {1013, 6, 9, 8, 1, -8}, // - {1020, 7, 9, 9, 1, -8}, // - {1028, 10, 9, 12, 1, -8}, // - {1040, 6, 9, 8, 1, -8}, // - {1047, 6, 6, 7, 0, -5}, // - {1052, 6, 9, 7, 0, -8}, // - {1059, 5, 6, 6, 1, -5}, // - {1063, 4, 6, 5, 1, -5}, // - {1066, 7, 7, 7, 0, -5}, // - {1073, 6, 6, 7, 0, -5}, // - {1078, 8, 6, 9, 1, -5}, // - {1084, 6, 6, 6, 0, -5}, // - {1089, 5, 6, 7, 1, -5}, // - {1093, 5, 8, 7, 1, -7}, // - {1098, 4, 6, 6, 1, -5}, // - {1101, 5, 6, 6, 0, -5}, // - {1105, 6, 6, 7, 1, -5}, // - {1110, 5, 6, 7, 1, -5}, // - {1114, 6, 6, 7, 0, -5}, // - {1119, 5, 6, 7, 1, -5}, // - {1123, 5, 9, 7, 1, -5}, // - {1129, 6, 6, 6, 0, -5}, // - {1134, 5, 6, 5, 0, -5}, // - {1138, 5, 9, 6, 0, -5}, // - {1144, 10, 11, 10, 0, -7}, // - {1158, 5, 6, 6, 0, -5}, // - {1162, 6, 7, 7, 1, -5}, // - {1168, 4, 6, 6, 1, -5}, // - {1171, 6, 6, 8, 1, -5}, // - {1176, 7, 7, 9, 1, -5}, // - {1183, 7, 6, 8, 0, -5}, // - {1189, 6, 6, 8, 1, -5}, // - {1194, 5, 6, 6, 1, -5}, // - {1198, 5, 6, 6, 1, -5}, // - {1202, 8, 6, 9, 1, -5}, // - {1208, 5, 6, 7, 1, -5} // -}; - -const GFXfont FreeSans6pt8bCyrillic PROGMEM = {(uint8_t *)FreeSans6pt8bCyrillicBitmaps, (GFXglyph *)FreeSans6pt8bCyrillicGlyphs, - 0x20, 0xFF, 16}; diff --git a/src/graphics/niche/Fonts/FreeSans6pt_Win1250.h b/src/graphics/niche/Fonts/FreeSans6pt_Win1250.h new file mode 100644 index 000000000..aee777783 --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans6pt_Win1250.h @@ -0,0 +1,457 @@ +#pragma once +const uint8_t FreeSans6pt_Win1250Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFC, 0x80, /* '!' 0x21 */ + 0xB6, 0x80, /* '"' 0x22 */ + 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */ + 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */ + 0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */ + 0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */ + 0xE0, /* ''' 0x27 */ + 0x5A, 0xAA, 0x94, /* '(' 0x28 */ + 0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */ + 0x5E, 0x80, /* '*' 0x2A */ + 0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */ + 0xE0, /* ',' 0x2C */ + 0xC0, /* '-' 0x2D */ + 0x80, /* '.' 0x2E */ + 0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */ + 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */ + 0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */ + 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */ + 0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */ + 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */ + 0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */ + 0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */ + 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */ + 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */ + 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */ + 0x82, /* ':' 0x3A */ + 0x87, /* ';' 0x3B */ + 0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */ + 0xF8, 0x3E, /* '=' 0x3D */ + 0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */ + 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */ + 0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */ + 0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */ + 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */ + 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */ + 0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */ + 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */ + 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */ + 0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */ + 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */ + 0xFF, 0x80, /* 'I' 0x49 */ + 0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */ + 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */ + 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */ + 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */ + 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */ + 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */ + 0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */ + 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */ + 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */ + 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */ + 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */ + 0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */ + 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */ + 0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */ + 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */ + 0xEA, 0xAA, 0xAB, /* '[' 0x5B */ + 0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */ + 0xD5, 0x55, 0x57, /* ']' 0x5D */ + 0x46, 0xA9, /* '^' 0x5E */ + 0xFE, /* '_' 0x5F */ + 0x80, /* '`' 0x60 */ + 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */ + 0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */ + 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */ + 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */ + 0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */ + 0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */ + 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */ + 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */ + 0xBF, 0x80, /* 'i' 0x69 */ + 0x45, 0x55, 0x57, /* 'j' 0x6A */ + 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */ + 0xFF, 0x80, /* 'l' 0x6C */ + 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */ + 0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */ + 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */ + 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */ + 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */ + 0xF2, 0x49, 0x20, /* 'r' 0x72 */ + 0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */ + 0x5D, 0x24, 0x93, /* 't' 0x74 */ + 0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */ + 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */ + 0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */ + 0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */ + 0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */ + 0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */ + 0x6A, 0xAA, 0xA9, /* '{' 0x7B */ + 0xFF, 0xE0, /* '|' 0x7C */ + 0x95, 0x55, 0x56, /* '}' 0x7D */ + 0x66, 0x60, /* '~' 0x7E */ + 0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */ + 0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */ + /* 0x81 */ + 0xE0, /* 0x82 */ + /* 0x83 */ + 0xB6, 0x80, /* 0x84 */ + 0xA8, /* 0x85 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */ + /* 0x88 */ + 0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */ + 0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */ + 0x64, /* 0x8B */ + 0x10, 0x87, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8C */ + 0x28, 0x4F, 0xC4, 0x10, 0x41, 0x04, 0x10, 0x40, /* 0x8D */ + 0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */ + 0x08, 0x21, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8F */ + /* 0x90 */ + 0xE0, /* 0x91 */ + 0xE0, /* 0x92 */ + 0xB6, 0x80, /* 0x93 */ + 0xB6, 0x80, /* 0x94 */ + 0xFF, 0x80, /* 0x95 */ + 0xFC, /* 0x96 */ + 0xFF, 0xF0, /* 0x97 */ + /* 0x98 */ + 0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */ + 0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */ + 0x98, /* 0x9B */ + 0x24, 0x06, 0x98, 0xE1, 0x96, /* 0x9C */ + 0x15, 0xE4, 0x44, 0x44, 0x60, /* 0x9D */ + 0x51, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9E */ + 0x11, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9F */ + /* 0xA0 */ + 0xA8, /* 0xA1 */ + 0x96, /* 0xA2 */ + 0x41, 0x05, 0x18, 0x43, 0x04, 0x10, 0x7C, /* 0xA3 */ + 0xFC, 0x63, 0xF0, /* 0xA4 */ + 0x30, 0x38, 0x28, 0x48, 0x4C, 0x7C, 0x84, 0x86, 0x82, 0x04, 0x07, /* 0xA5 */ + 0xF9, 0xF0, /* 0xA6 */ + 0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */ + 0xA0, /* 0xA8 */ + 0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */ + 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xC1, 0x0C, /* 0xAA */ + 0x5A, 0xA5, /* 0xAB */ + 0xFC, 0x10, 0x40, /* 0xAC */ + /* 0xAD */ + 0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */ + 0x18, 0x31, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0xAF */ + 0x69, 0x96, /* 0xB0 */ + 0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */ + 0x9C, /* 0xB2 */ + 0x49, 0x35, 0x92, 0x40, /* 0xB3 */ + 0x80, /* 0xB4 */ + 0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */ + 0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */ + 0x80, /* 0xB7 */ + 0x67, 0x80, /* 0xB8 */ + 0x78, 0x84, 0x04, 0x3C, 0xC4, 0x8C, 0x76, 0x04, 0x07, /* 0xB9 */ + 0x69, 0x8E, 0x19, 0x66, 0x26, /* 0xBA */ + 0xA5, 0x5A, /* 0xBB */ + 0xA5, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 0xBC */ + 0xA0, /* 0xBD */ + 0xBA, 0x49, 0x24, 0x90, /* 0xBE */ + 0x31, 0x9E, 0x11, 0x11, 0x88, 0xF8, /* 0xBF */ + 0x10, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xC0 */ + 0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */ + 0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */ + 0x24, 0x18, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */ + 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */ + 0x11, 0x21, 0x08, 0x42, 0x10, 0x87, 0xC0, /* 0xC5 */ + 0x08, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC6 */ + 0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */ + 0x28, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC8 */ + 0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */ + 0xFD, 0x02, 0x04, 0x0F, 0xD0, 0x20, 0x40, 0xFC, 0x10, 0x38, /* 0xCA */ + 0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */ + 0x28, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x82, 0x0F, 0xC0, /* 0xCC */ + 0x62, 0xAA, 0xA0, /* 0xCD */ + 0x54, 0x24, 0x92, 0x48, /* 0xCE */ + 0x50, 0x43, 0xE4, 0x28, 0x30, 0x60, 0xC1, 0x85, 0xF0, /* 0xCF */ + 0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */ + 0x08, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */ + 0x28, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD2 */ + 0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */ + 0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */ + 0x0A, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */ + 0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */ + 0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */ + 0x50, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xD8 */ + 0x10, 0x52, 0x4C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */ + 0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */ + 0x14, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */ + 0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */ + 0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */ + 0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, 0x60, 0x8E, /* 0xDE */ + 0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */ + 0x42, 0xE9, 0x24, 0x80, /* 0xE0 */ + 0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */ + 0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */ + 0x48, 0x60, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */ + 0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */ + 0x62, 0xAA, 0xA0, /* 0xE5 */ + 0x10, 0x80, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE6 */ + 0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */ + 0x28, 0x40, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE8 */ + 0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */ + 0x7B, 0x38, 0x7F, 0x83, 0x37, 0x84, 0x1C, /* 0xEA */ + 0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */ + 0x28, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEC */ + 0x62, 0xAA, 0xA0, /* 0xED */ + 0x54, 0x24, 0x92, 0x48, /* 0xEE */ + 0x02, 0x0C, 0x13, 0xEC, 0xD0, 0xA1, 0x42, 0xCC, 0xE8, /* 0xEF */ + 0x04, 0x1D, 0xD6, 0x68, 0x50, 0xA1, 0x66, 0x74, /* 0xF0 */ + 0x11, 0x01, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */ + 0x20, 0x81, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF2 */ + 0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */ + 0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */ + 0x29, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */ + 0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */ + 0x20, 0x3E, 0x02, 0x00, /* 0xF7 */ + 0xA8, 0x5D, 0x24, 0x90, /* 0xF8 */ + 0x22, 0x89, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xF9 */ + 0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */ + 0x2A, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */ + 0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */ + 0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */ + 0x4E, 0x44, 0x44, 0x46, 0x31, 0x70, /* 0xFE */ + 0x80, /* 0xFF */ +}; + +const GFXglyph FreeSans6pt_Win1250Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 3, 0, 0}, + /* '!' 0x21 */ {0, 1, 9, 4, 2, -8}, + /* '"' 0x22 */ {2, 3, 3, 4, 0, -8}, + /* '#' 0x23 */ {4, 7, 8, 7, 0, -7}, + /* '$' 0x24 */ {11, 6, 11, 7, 0, -9}, + /* '%' 0x25 */ {20, 10, 9, 11, 0, -8}, + /* '&' 0x26 */ {32, 6, 9, 8, 1, -8}, + /* ''' 0x27 */ {39, 1, 3, 2, 1, -8}, + /* '(' 0x28 */ {40, 2, 11, 4, 1, -8}, + /* ')' 0x29 */ {43, 3, 11, 4, 0, -8}, + /* '*' 0x2A */ {48, 3, 3, 5, 1, -8}, + /* '+' 0x2B */ {50, 5, 5, 7, 1, -4}, + /* ',' 0x2C */ {54, 1, 3, 3, 1, 0}, + /* '-' 0x2D */ {55, 2, 1, 4, 1, -3}, + /* '.' 0x2E */ {56, 1, 1, 3, 1, 0}, + /* '/' 0x2F */ {57, 3, 9, 3, 0, -8}, + /* '0' 0x30 */ {61, 5, 9, 7, 1, -8}, + /* '1' 0x31 */ {67, 3, 9, 7, 1, -8}, + /* '2' 0x32 */ {71, 6, 9, 7, 0, -8}, + /* '3' 0x33 */ {78, 6, 9, 7, 0, -8}, + /* '4' 0x34 */ {85, 6, 9, 7, 0, -8}, + /* '5' 0x35 */ {92, 5, 9, 7, 1, -8}, + /* '6' 0x36 */ {98, 5, 9, 7, 1, -8}, + /* '7' 0x37 */ {104, 5, 9, 7, 1, -8}, + /* '8' 0x38 */ {110, 6, 9, 7, 0, -8}, + /* '9' 0x39 */ {117, 6, 9, 7, 0, -8}, + /* ':' 0x3A */ {124, 1, 7, 3, 1, -6}, + /* ';' 0x3B */ {125, 1, 8, 3, 1, -5}, + /* '<' 0x3C */ {126, 5, 5, 7, 1, -4}, + /* '=' 0x3D */ {130, 5, 3, 7, 1, -3}, + /* '>' 0x3E */ {132, 5, 5, 7, 1, -4}, + /* '?' 0x3F */ {136, 5, 9, 7, 1, -8}, + /* '@' 0x40 */ {142, 11, 11, 12, 0, -8}, + /* 'A' 0x41 */ {158, 8, 9, 8, 0, -8}, + /* 'B' 0x42 */ {167, 6, 9, 8, 1, -8}, + /* 'C' 0x43 */ {174, 8, 9, 9, 0, -8}, + /* 'D' 0x44 */ {183, 7, 9, 8, 1, -8}, + /* 'E' 0x45 */ {191, 6, 9, 8, 1, -8}, + /* 'F' 0x46 */ {198, 6, 9, 7, 1, -8}, + /* 'G' 0x47 */ {205, 8, 9, 9, 0, -8}, + /* 'H' 0x48 */ {214, 7, 9, 9, 1, -8}, + /* 'I' 0x49 */ {222, 1, 9, 3, 1, -8}, + /* 'J' 0x4A */ {224, 5, 9, 6, 0, -8}, + /* 'K' 0x4B */ {230, 7, 9, 8, 1, -8}, + /* 'L' 0x4C */ {238, 5, 9, 7, 1, -8}, + /* 'M' 0x4D */ {244, 8, 9, 10, 1, -8}, + /* 'N' 0x4E */ {253, 7, 9, 9, 1, -8}, + /* 'O' 0x4F */ {261, 9, 9, 9, 0, -8}, + /* 'P' 0x50 */ {272, 6, 9, 8, 1, -8}, + /* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8}, + /* 'R' 0x52 */ {291, 7, 9, 9, 1, -8}, + /* 'S' 0x53 */ {299, 6, 9, 8, 1, -8}, + /* 'T' 0x54 */ {306, 7, 9, 8, 0, -8}, + /* 'U' 0x55 */ {314, 7, 9, 9, 1, -8}, + /* 'V' 0x56 */ {322, 7, 9, 8, 0, -8}, + /* 'W' 0x57 */ {330, 11, 9, 11, 0, -8}, + /* 'X' 0x58 */ {343, 6, 9, 8, 1, -8}, + /* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8}, + /* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8}, + /* '[' 0x5B */ {367, 2, 12, 3, 1, -8}, + /* '\' 0x5C */ {370, 3, 9, 3, 0, -8}, + /* ']' 0x5D */ {374, 2, 12, 3, 0, -8}, + /* '^' 0x5E */ {377, 4, 4, 6, 1, -8}, + /* '_' 0x5F */ {379, 7, 1, 7, 0, 2}, + /* '`' 0x60 */ {380, 1, 1, 3, 1, -8}, + /* 'a' 0x61 */ {381, 6, 7, 7, 0, -6}, + /* 'b' 0x62 */ {387, 5, 9, 7, 1, -8}, + /* 'c' 0x63 */ {393, 6, 7, 6, 0, -6}, + /* 'd' 0x64 */ {399, 6, 9, 7, 0, -8}, + /* 'e' 0x65 */ {406, 6, 7, 6, 0, -6}, + /* 'f' 0x66 */ {412, 3, 9, 3, 0, -8}, + /* 'g' 0x67 */ {416, 6, 10, 7, 0, -6}, + /* 'h' 0x68 */ {424, 5, 9, 6, 1, -8}, + /* 'i' 0x69 */ {430, 1, 9, 3, 1, -8}, + /* 'j' 0x6A */ {432, 2, 12, 3, 0, -8}, + /* 'k' 0x6B */ {435, 5, 9, 6, 1, -8}, + /* 'l' 0x6C */ {441, 1, 9, 3, 1, -8}, + /* 'm' 0x6D */ {443, 8, 7, 10, 1, -6}, + /* 'n' 0x6E */ {450, 5, 7, 6, 1, -6}, + /* 'o' 0x6F */ {455, 6, 7, 6, 0, -6}, + /* 'p' 0x70 */ {461, 5, 9, 7, 1, -6}, + /* 'q' 0x71 */ {467, 6, 9, 7, 0, -6}, + /* 'r' 0x72 */ {474, 3, 7, 4, 1, -6}, + /* 's' 0x73 */ {477, 5, 7, 6, 0, -6}, + /* 't' 0x74 */ {482, 3, 8, 3, 0, -7}, + /* 'u' 0x75 */ {485, 5, 7, 6, 1, -6}, + /* 'v' 0x76 */ {490, 6, 7, 6, 0, -6}, + /* 'w' 0x77 */ {496, 8, 7, 9, 0, -6}, + /* 'x' 0x78 */ {503, 5, 7, 6, 0, -6}, + /* 'y' 0x79 */ {508, 5, 10, 6, 0, -6}, + /* 'z' 0x7A */ {515, 5, 7, 6, 0, -6}, + /* '{' 0x7B */ {520, 2, 12, 4, 1, -8}, + /* '|' 0x7C */ {523, 1, 11, 3, 1, -8}, + /* '}' 0x7D */ {525, 2, 12, 4, 1, -8}, + /* '~' 0x7E */ {528, 6, 2, 6, 0, -4}, + /* 0x7F */ {530, 9, 10, 11, 1, -8}, + /* 0x80 */ {542, 7, 9, 8, 0, -8}, + /* 0x81 */ {550, 0, 0, 8, 0, 0}, + /* 0x82 */ {550, 1, 3, 3, 1, 0}, + /* 0x83 */ {551, 0, 0, 8, 0, 0}, + /* 0x84 */ {551, 3, 3, 5, 1, 0}, + /* 0x85 */ {553, 5, 1, 7, 1, 0}, + /* 0x86 */ {554, 5, 11, 7, 1, -8}, + /* 0x87 */ {561, 5, 11, 7, 1, -8}, + /* 0x88 */ {568, 0, 0, 8, 0, 0}, + /* 0x89 */ {568, 12, 9, 12, 0, -8}, + /* 0x8A */ {582, 6, 11, 8, 1, -9}, + /* 0x8B */ {591, 2, 3, 4, 1, -4}, + /* 0x8C */ {592, 6, 11, 8, 1, -10}, + /* 0x8D */ {601, 6, 10, 8, 0, -9}, + /* 0x8E */ {609, 7, 10, 7, 0, -9}, + /* 0x8F */ {618, 7, 10, 7, 0, -9}, + /* 0x90 */ {627, 0, 0, 8, 0, 0}, + /* 0x91 */ {627, 1, 3, 3, 1, -8}, + /* 0x92 */ {628, 1, 3, 2, 1, -8}, + /* 0x93 */ {629, 3, 3, 5, 1, -8}, + /* 0x94 */ {631, 3, 3, 5, 1, -8}, + /* 0x95 */ {633, 3, 3, 5, 1, -5}, + /* 0x96 */ {635, 6, 1, 6, 0, -3}, + /* 0x97 */ {636, 12, 1, 12, 0, -3}, + /* 0x98 */ {638, 0, 0, 8, 0, 0}, + /* 0x99 */ {638, 11, 7, 12, 1, -8}, + /* 0x9A */ {648, 4, 9, 6, 1, -8}, + /* 0x9B */ {653, 2, 3, 3, 1, -4}, + /* 0x9C */ {654, 4, 10, 6, 1, -9}, + /* 0x9D */ {659, 4, 9, 5, 0, -8}, + /* 0x9E */ {664, 5, 10, 6, 0, -9}, + /* 0x9F */ {671, 5, 10, 6, 0, -9}, + /* 0xA0 */ {678, 0, 0, 3, 0, 0}, + /* 0xA1 */ {678, 3, 2, 4, 0, -8}, + /* 0xA2 */ {679, 4, 2, 4, 0, -8}, + /* 0xA3 */ {680, 6, 9, 7, 0, -8}, + /* 0xA4 */ {687, 5, 4, 7, 1, -5}, + /* 0xA5 */ {690, 8, 11, 8, 1, -8}, + /* 0xA6 */ {701, 1, 12, 3, 1, -8}, + /* 0xA7 */ {703, 5, 12, 7, 1, -8}, + /* 0xA8 */ {711, 3, 1, 4, 0, -7}, + /* 0xA9 */ {712, 9, 9, 10, 0, -8}, + /* 0xAA */ {723, 6, 12, 8, 1, -8}, + /* 0xAB */ {732, 4, 4, 6, 1, -4}, + /* 0xAC */ {734, 6, 3, 7, 1, -4}, + /* 0xAD */ {737, 0, 0, 0, 0, 0}, + /* 0xAE */ {737, 9, 9, 10, 0, -8}, + /* 0xAF */ {748, 7, 10, 7, 0, -9}, + /* 0xB0 */ {757, 4, 4, 7, 2, -8}, + /* 0xB1 */ {759, 5, 7, 7, 1, -6}, + /* 0xB2 */ {764, 3, 2, 4, 1, 1}, + /* 0xB3 */ {765, 3, 9, 3, 0, -8}, + /* 0xB4 */ {769, 1, 1, 4, 1, -8}, + /* 0xB5 */ {770, 6, 9, 7, 1, -6}, + /* 0xB6 */ {777, 6, 10, 6, 1, -8}, + /* 0xB7 */ {785, 1, 1, 3, 1, -2}, + /* 0xB8 */ {786, 3, 3, 4, 1, 1}, + /* 0xB9 */ {788, 8, 9, 7, 0, -6}, + /* 0xBA */ {797, 4, 10, 6, 1, -6}, + /* 0xBB */ {802, 4, 4, 6, 1, -5}, + /* 0xBC */ {804, 5, 9, 7, 1, -8}, + /* 0xBD */ {810, 3, 1, 4, 0, -8}, + /* 0xBE */ {811, 3, 10, 3, 1, -9}, + /* 0xBF */ {815, 5, 9, 6, 0, -8}, + /* 0xC0 */ {821, 7, 10, 9, 1, -9}, + /* 0xC1 */ {830, 8, 10, 8, 0, -9}, + /* 0xC2 */ {840, 8, 10, 8, 0, -9}, + /* 0xC3 */ {850, 8, 10, 8, 0, -9}, + /* 0xC4 */ {860, 8, 10, 8, 0, -9}, + /* 0xC5 */ {870, 5, 10, 7, 1, -9}, + /* 0xC6 */ {877, 7, 11, 9, 0, -10}, + /* 0xC7 */ {887, 8, 12, 9, 0, -8}, + /* 0xC8 */ {899, 7, 11, 9, 0, -10}, + /* 0xC9 */ {909, 6, 10, 8, 1, -9}, + /* 0xCA */ {917, 7, 11, 8, 1, -8}, + /* 0xCB */ {927, 6, 10, 8, 1, -9}, + /* 0xCC */ {935, 6, 11, 8, 1, -10}, + /* 0xCD */ {944, 2, 10, 3, 1, -9}, + /* 0xCE */ {947, 3, 10, 4, 0, -9}, + /* 0xCF */ {951, 7, 10, 8, 1, -9}, + /* 0xD0 */ {960, 8, 9, 8, 0, -8}, + /* 0xD1 */ {969, 7, 10, 9, 1, -9}, + /* 0xD2 */ {978, 7, 10, 9, 1, -9}, + /* 0xD3 */ {987, 9, 10, 9, 0, -9}, + /* 0xD4 */ {999, 9, 11, 9, 0, -10}, + /* 0xD5 */ {1012, 9, 11, 9, 0, -10}, + /* 0xD6 */ {1025, 9, 11, 9, 0, -10}, + /* 0xD7 */ {1038, 5, 5, 7, 1, -5}, + /* 0xD8 */ {1042, 7, 10, 9, 1, -9}, + /* 0xD9 */ {1051, 7, 10, 9, 1, -9}, + /* 0xDA */ {1060, 7, 10, 9, 1, -9}, + /* 0xDB */ {1069, 7, 10, 9, 1, -9}, + /* 0xDC */ {1078, 7, 10, 9, 1, -9}, + /* 0xDD */ {1087, 7, 10, 8, 1, -9}, + /* 0xDE */ {1096, 6, 12, 7, 0, -8}, + /* 0xDF */ {1105, 6, 9, 7, 1, -8}, + /* 0xE0 */ {1112, 3, 9, 4, 1, -8}, + /* 0xE1 */ {1116, 7, 10, 7, 0, -9}, + /* 0xE2 */ {1125, 7, 10, 7, 0, -9}, + /* 0xE3 */ {1134, 7, 10, 7, 0, -9}, + /* 0xE4 */ {1143, 7, 9, 7, 0, -8}, + /* 0xE5 */ {1151, 2, 10, 3, 1, -9}, + /* 0xE6 */ {1154, 6, 10, 6, 0, -9}, + /* 0xE7 */ {1162, 6, 10, 6, 0, -6}, + /* 0xE8 */ {1170, 6, 10, 6, 0, -9}, + /* 0xE9 */ {1178, 6, 10, 6, 0, -9}, + /* 0xEA */ {1186, 6, 9, 6, 0, -6}, + /* 0xEB */ {1193, 6, 9, 6, 0, -8}, + /* 0xEC */ {1200, 6, 10, 6, 0, -9}, + /* 0xED */ {1208, 2, 10, 3, 1, -9}, + /* 0xEE */ {1211, 3, 10, 3, 0, -9}, + /* 0xEF */ {1215, 7, 10, 7, 0, -9}, + /* 0xF0 */ {1224, 7, 9, 7, 0, -8}, + /* 0xF1 */ {1232, 5, 10, 6, 1, -9}, + /* 0xF2 */ {1239, 5, 10, 6, 1, -9}, + /* 0xF3 */ {1246, 6, 10, 6, 0, -9}, + /* 0xF4 */ {1254, 6, 10, 6, 0, -9}, + /* 0xF5 */ {1262, 6, 10, 6, 0, -9}, + /* 0xF6 */ {1270, 6, 9, 6, 0, -8}, + /* 0xF7 */ {1277, 5, 5, 7, 1, -5}, + /* 0xF8 */ {1281, 3, 10, 4, 1, -9}, + /* 0xF9 */ {1285, 5, 10, 6, 1, -9}, + /* 0xFA */ {1292, 5, 9, 6, 1, -8}, + /* 0xFB */ {1298, 5, 10, 6, 1, -9}, + /* 0xFC */ {1305, 5, 9, 6, 1, -8}, + /* 0xFD */ {1311, 6, 12, 6, 0, -8}, + /* 0xFE */ {1320, 4, 11, 3, 0, -7}, + /* 0xFF */ {1326, 1, 1, 4, 1, -7}, +}; + +const GFXfont FreeSans6pt_Win1250 PROGMEM = {(uint8_t *)FreeSans6pt_Win1250Bitmaps, (GFXglyph *)FreeSans6pt_Win1250Glyphs, 0x20, + 0xFF, 14}; diff --git a/src/graphics/niche/Fonts/FreeSans6pt_Win1251.h b/src/graphics/niche/Fonts/FreeSans6pt_Win1251.h new file mode 100644 index 000000000..4d3ad1705 --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans6pt_Win1251.h @@ -0,0 +1,457 @@ +#pragma once +const uint8_t FreeSans6pt_Win1251Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFC, 0x80, /* '!' 0x21 */ + 0xB6, 0x80, /* '"' 0x22 */ + 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */ + 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */ + 0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */ + 0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */ + 0xE0, /* ''' 0x27 */ + 0x5A, 0xAA, 0x94, /* '(' 0x28 */ + 0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */ + 0x5E, 0x80, /* '*' 0x2A */ + 0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */ + 0xE0, /* ',' 0x2C */ + 0xC0, /* '-' 0x2D */ + 0x80, /* '.' 0x2E */ + 0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */ + 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */ + 0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */ + 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */ + 0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */ + 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */ + 0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */ + 0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */ + 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */ + 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */ + 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */ + 0x82, /* ':' 0x3A */ + 0x87, /* ';' 0x3B */ + 0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */ + 0xF8, 0x3E, /* '=' 0x3D */ + 0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */ + 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */ + 0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */ + 0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */ + 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */ + 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */ + 0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */ + 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */ + 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */ + 0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */ + 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */ + 0xFF, 0x80, /* 'I' 0x49 */ + 0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */ + 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */ + 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */ + 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */ + 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */ + 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */ + 0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */ + 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */ + 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */ + 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */ + 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */ + 0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */ + 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */ + 0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */ + 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */ + 0xEA, 0xAA, 0xAB, /* '[' 0x5B */ + 0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */ + 0xD5, 0x55, 0x57, /* ']' 0x5D */ + 0x46, 0xA9, /* '^' 0x5E */ + 0xFE, /* '_' 0x5F */ + 0x80, /* '`' 0x60 */ + 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */ + 0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */ + 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */ + 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */ + 0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */ + 0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */ + 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */ + 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */ + 0xBF, 0x80, /* 'i' 0x69 */ + 0x45, 0x55, 0x57, /* 'j' 0x6A */ + 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */ + 0xFF, 0x80, /* 'l' 0x6C */ + 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */ + 0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */ + 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */ + 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */ + 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */ + 0xF2, 0x49, 0x20, /* 'r' 0x72 */ + 0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */ + 0x5D, 0x24, 0x93, /* 't' 0x74 */ + 0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */ + 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */ + 0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */ + 0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */ + 0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */ + 0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */ + 0x6A, 0xAA, 0xA9, /* '{' 0x7B */ + 0xFF, 0xE0, /* '|' 0x7C */ + 0x95, 0x55, 0x56, /* '}' 0x7D */ + 0x66, 0x60, /* '~' 0x7E */ + 0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */ + 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, /* 0x80 */ + 0x10, 0x8F, 0xE0, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0x81 */ + 0xE0, /* 0x82 */ + 0x24, 0x0F, 0x88, 0x88, 0x80, /* 0x83 */ + 0xB6, 0x80, /* 0x84 */ + 0xA8, /* 0x85 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */ + 0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x88 */ + 0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */ + 0x7C, 0x08, 0x81, 0x10, 0x22, 0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, /* 0x8A */ + 0x64, /* 0x8B */ + 0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0, /* 0x8C */ + 0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, /* 0x8D */ + 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, /* 0x8E */ + 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, /* 0x8F */ + 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, /* 0x90 */ + 0xE0, /* 0x91 */ + 0xE0, /* 0x92 */ + 0xB6, 0x80, /* 0x93 */ + 0xB6, 0x80, /* 0x94 */ + 0xFF, 0x80, /* 0x95 */ + 0xFC, /* 0x96 */ + 0xFF, 0xF0, /* 0x97 */ + /* 0x98 */ + 0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */ + 0x78, 0x24, 0x13, 0xC9, 0x14, 0x8E, 0x7C, /* 0x9A */ + 0x98, /* 0x9B */ + 0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, /* 0x9C */ + 0x24, 0x09, 0xAC, 0xCA, 0x90, /* 0x9D */ + 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, /* 0x9E */ + 0x8C, 0x63, 0x18, 0xFC, 0x80, /* 0x9F */ + /* 0xA0 */ + 0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, /* 0xA1 */ + 0x51, 0x22, 0x95, 0xA8, 0xC4, 0x23, 0x10, /* 0xA2 */ + 0x08, 0x42, 0x10, 0x86, 0x31, 0x78, /* 0xA3 */ + 0xFC, 0x63, 0xF0, /* 0xA4 */ + 0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0xA5 */ + 0xF9, 0xF0, /* 0xA6 */ + 0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */ + 0x28, 0x0F, 0xE0, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, /* 0xA8 */ + 0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */ + 0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, /* 0xAA */ + 0x5A, 0xA5, /* 0xAB */ + 0x51, 0x55, 0x56, /* 0xAC */ + /* 0xAD */ + 0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */ + 0xA1, 0x24, 0x92, 0x49, 0x00, /* 0xAF */ + 0x69, 0x96, /* 0xB0 */ + 0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */ + 0xFF, 0x80, /* 0xB2 */ + 0xDF, 0x80, /* 0xB3 */ + 0x27, 0xC9, 0x24, /* 0xB4 */ + 0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */ + 0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */ + 0x80, /* 0xB7 */ + 0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, /* 0xB8 */ + 0x88, 0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x8B, 0x80, /* 0xB9 */ + 0x79, 0x1F, 0x30, 0x45, 0xE0, /* 0xBA */ + 0xA5, 0x5A, /* 0xBB */ + 0x45, 0x55, 0x57, /* 0xBC */ + 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, /* 0xBD */ + 0x7A, 0x1C, 0x1C, 0xBC, /* 0xBE */ + 0xB4, 0x24, 0x92, 0x40, /* 0xBF */ + 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC0 */ + 0xFE, 0x08, 0x20, 0xFA, 0x18, 0x61, 0xF8, /* 0xC1 */ + 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 0xC2 */ + 0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, /* 0xC3 */ + 0x1F, 0x08, 0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, /* 0xC4 */ + 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 0xC5 */ + 0x88, 0xA4, 0x9A, 0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, /* 0xC6 */ + 0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, /* 0xC7 */ + 0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68, 0xE1, 0xC2, /* 0xC8 */ + 0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, /* 0xC9 */ + 0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, /* 0xCA */ + 0x3E, 0x44, 0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, /* 0xCB */ + 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 0xCC */ + 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 0xCD */ + 0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, /* 0xCE */ + 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, /* 0xCF */ + 0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, /* 0xD0 */ + 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, /* 0xD1 */ + 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 0xD2 */ + 0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, /* 0xD3 */ + 0x08, 0x1F, 0x32, 0x71, 0x18, 0x8C, 0x47, 0x26, 0xFE, 0x08, 0x00, /* 0xD4 */ + 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, /* 0xD5 */ + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, /* 0xD6 */ + 0x8E, 0x38, 0xE3, 0x8D, 0xF0, 0xC3, 0x0C, /* 0xD7 */ + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, /* 0xD8 */ + 0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF, 0x80, 0x40, 0x20, /* 0xD9 */ + 0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, /* 0xDA */ + 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC, 0x2E, 0x17, 0x0B, 0xF9, 0x80, /* 0xDB */ + 0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, /* 0xDC */ + 0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, /* 0xDD */ + 0x87, 0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, /* 0xDE */ + 0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, /* 0xDF */ + 0x79, 0x11, 0xD9, 0xCD, 0xD0, /* 0xE0 */ + 0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, /* 0xE1 */ + 0xF4, 0xBD, 0x29, 0xF8, /* 0xE2 */ + 0xF8, 0x88, 0x88, /* 0xE3 */ + 0x3C, 0x48, 0x91, 0x22, 0x5F, 0xE0, 0x80, /* 0xE4 */ + 0x79, 0x1F, 0xF0, 0x45, 0xE0, /* 0xE5 */ + 0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, /* 0xE6 */ + 0x78, 0x23, 0x82, 0xCD, 0xE0, /* 0xE7 */ + 0x9C, 0xEB, 0x5C, 0xC4, /* 0xE8 */ + 0x70, 0x27, 0x3A, 0xD7, 0x31, /* 0xE9 */ + 0x9A, 0xCC, 0xA9, /* 0xEA */ + 0x7A, 0x52, 0x94, 0xE4, /* 0xEB */ + 0x8F, 0x3D, 0x6D, 0xA6, 0x90, /* 0xEC */ + 0x8C, 0x7F, 0x18, 0xC4, /* 0xED */ + 0x79, 0x1C, 0x71, 0x45, 0xE0, /* 0xEE */ + 0xFC, 0x63, 0x18, 0xC4, /* 0xEF */ + 0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, /* 0xF0 */ + 0x79, 0x1C, 0x30, 0x45, 0xE0, /* 0xF1 */ + 0xF9, 0x08, 0x42, 0x10, /* 0xF2 */ + 0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, /* 0xF3 */ + 0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04, 0x01, 0x00, 0x40, /* 0xF4 */ + 0x4B, 0x8C, 0x65, 0xE4, /* 0xF5 */ + 0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, /* 0xF6 */ + 0x99, 0x97, 0x11, /* 0xF7 */ + 0x96, 0x59, 0x65, 0x97, 0xF0, /* 0xF8 */ + 0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, /* 0xF9 */ + 0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, /* 0xFA */ + 0x86, 0x1F, 0x63, 0x8F, 0xD0, /* 0xFB */ + 0x84, 0x3D, 0x18, 0xF8, /* 0xFC */ + 0xF4, 0xDE, 0x19, 0xF8, /* 0xFD */ + 0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, /* 0xFE */ + 0xFC, 0x7E, 0xD4, 0xC4, /* 0xFF */ +}; + +const GFXglyph FreeSans6pt_Win1251Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 3, 0, 0}, + /* '!' 0x21 */ {0, 1, 9, 4, 2, -8}, + /* '"' 0x22 */ {2, 3, 3, 4, 0, -8}, + /* '#' 0x23 */ {4, 7, 8, 7, 0, -7}, + /* '$' 0x24 */ {11, 6, 11, 7, 0, -9}, + /* '%' 0x25 */ {20, 10, 9, 11, 0, -8}, + /* '&' 0x26 */ {32, 6, 9, 8, 1, -8}, + /* ''' 0x27 */ {39, 1, 3, 2, 1, -8}, + /* '(' 0x28 */ {40, 2, 11, 4, 1, -8}, + /* ')' 0x29 */ {43, 3, 11, 4, 0, -8}, + /* '*' 0x2A */ {48, 3, 3, 5, 1, -8}, + /* '+' 0x2B */ {50, 5, 5, 7, 1, -4}, + /* ',' 0x2C */ {54, 1, 3, 3, 1, 0}, + /* '-' 0x2D */ {55, 2, 1, 4, 1, -3}, + /* '.' 0x2E */ {56, 1, 1, 3, 1, 0}, + /* '/' 0x2F */ {57, 3, 9, 3, 0, -8}, + /* '0' 0x30 */ {61, 5, 9, 7, 1, -8}, + /* '1' 0x31 */ {67, 3, 9, 7, 1, -8}, + /* '2' 0x32 */ {71, 6, 9, 7, 0, -8}, + /* '3' 0x33 */ {78, 6, 9, 7, 0, -8}, + /* '4' 0x34 */ {85, 6, 9, 7, 0, -8}, + /* '5' 0x35 */ {92, 5, 9, 7, 1, -8}, + /* '6' 0x36 */ {98, 5, 9, 7, 1, -8}, + /* '7' 0x37 */ {104, 5, 9, 7, 1, -8}, + /* '8' 0x38 */ {110, 6, 9, 7, 0, -8}, + /* '9' 0x39 */ {117, 6, 9, 7, 0, -8}, + /* ':' 0x3A */ {124, 1, 7, 3, 1, -6}, + /* ';' 0x3B */ {125, 1, 8, 3, 1, -5}, + /* '<' 0x3C */ {126, 5, 5, 7, 1, -4}, + /* '=' 0x3D */ {130, 5, 3, 7, 1, -3}, + /* '>' 0x3E */ {132, 5, 5, 7, 1, -4}, + /* '?' 0x3F */ {136, 5, 9, 7, 1, -8}, + /* '@' 0x40 */ {142, 11, 11, 12, 0, -8}, + /* 'A' 0x41 */ {158, 8, 9, 8, 0, -8}, + /* 'B' 0x42 */ {167, 6, 9, 8, 1, -8}, + /* 'C' 0x43 */ {174, 8, 9, 9, 0, -8}, + /* 'D' 0x44 */ {183, 7, 9, 8, 1, -8}, + /* 'E' 0x45 */ {191, 6, 9, 8, 1, -8}, + /* 'F' 0x46 */ {198, 6, 9, 7, 1, -8}, + /* 'G' 0x47 */ {205, 8, 9, 9, 0, -8}, + /* 'H' 0x48 */ {214, 7, 9, 9, 1, -8}, + /* 'I' 0x49 */ {222, 1, 9, 3, 1, -8}, + /* 'J' 0x4A */ {224, 5, 9, 6, 0, -8}, + /* 'K' 0x4B */ {230, 7, 9, 8, 1, -8}, + /* 'L' 0x4C */ {238, 5, 9, 7, 1, -8}, + /* 'M' 0x4D */ {244, 8, 9, 10, 1, -8}, + /* 'N' 0x4E */ {253, 7, 9, 9, 1, -8}, + /* 'O' 0x4F */ {261, 9, 9, 9, 0, -8}, + /* 'P' 0x50 */ {272, 6, 9, 8, 1, -8}, + /* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8}, + /* 'R' 0x52 */ {291, 7, 9, 9, 1, -8}, + /* 'S' 0x53 */ {299, 6, 9, 8, 1, -8}, + /* 'T' 0x54 */ {306, 7, 9, 8, 0, -8}, + /* 'U' 0x55 */ {314, 7, 9, 9, 1, -8}, + /* 'V' 0x56 */ {322, 7, 9, 8, 0, -8}, + /* 'W' 0x57 */ {330, 11, 9, 11, 0, -8}, + /* 'X' 0x58 */ {343, 6, 9, 8, 1, -8}, + /* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8}, + /* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8}, + /* '[' 0x5B */ {367, 2, 12, 3, 1, -8}, + /* '\' 0x5C */ {370, 3, 9, 3, 0, -8}, + /* ']' 0x5D */ {374, 2, 12, 3, 0, -8}, + /* '^' 0x5E */ {377, 4, 4, 6, 1, -8}, + /* '_' 0x5F */ {379, 7, 1, 7, 0, 2}, + /* '`' 0x60 */ {380, 1, 1, 3, 1, -8}, + /* 'a' 0x61 */ {381, 6, 7, 7, 0, -6}, + /* 'b' 0x62 */ {387, 5, 9, 7, 1, -8}, + /* 'c' 0x63 */ {393, 6, 7, 6, 0, -6}, + /* 'd' 0x64 */ {399, 6, 9, 7, 0, -8}, + /* 'e' 0x65 */ {406, 6, 7, 6, 0, -6}, + /* 'f' 0x66 */ {412, 3, 9, 3, 0, -8}, + /* 'g' 0x67 */ {416, 6, 10, 7, 0, -6}, + /* 'h' 0x68 */ {424, 5, 9, 6, 1, -8}, + /* 'i' 0x69 */ {430, 1, 9, 3, 1, -8}, + /* 'j' 0x6A */ {432, 2, 12, 3, 0, -8}, + /* 'k' 0x6B */ {435, 5, 9, 6, 1, -8}, + /* 'l' 0x6C */ {441, 1, 9, 3, 1, -8}, + /* 'm' 0x6D */ {443, 8, 7, 10, 1, -6}, + /* 'n' 0x6E */ {450, 5, 7, 6, 1, -6}, + /* 'o' 0x6F */ {455, 6, 7, 6, 0, -6}, + /* 'p' 0x70 */ {461, 5, 9, 7, 1, -6}, + /* 'q' 0x71 */ {467, 6, 9, 7, 0, -6}, + /* 'r' 0x72 */ {474, 3, 7, 4, 1, -6}, + /* 's' 0x73 */ {477, 5, 7, 6, 0, -6}, + /* 't' 0x74 */ {482, 3, 8, 3, 0, -7}, + /* 'u' 0x75 */ {485, 5, 7, 6, 1, -6}, + /* 'v' 0x76 */ {490, 6, 7, 6, 0, -6}, + /* 'w' 0x77 */ {496, 8, 7, 9, 0, -6}, + /* 'x' 0x78 */ {503, 5, 7, 6, 0, -6}, + /* 'y' 0x79 */ {508, 5, 10, 6, 0, -6}, + /* 'z' 0x7A */ {515, 5, 7, 6, 0, -6}, + /* '{' 0x7B */ {520, 2, 12, 4, 1, -8}, + /* '|' 0x7C */ {523, 1, 11, 3, 1, -8}, + /* '}' 0x7D */ {525, 2, 12, 4, 1, -8}, + /* '~' 0x7E */ {528, 6, 2, 6, 0, -4}, + /* 0x7F */ {530, 9, 10, 11, 1, -8}, + /* 0x80 */ {542, 9, 11, 9, 0, -8}, + /* 0x81 */ {555, 6, 10, 7, 1, -9}, + /* 0x82 */ {563, 1, 3, 3, 1, 0}, + /* 0x83 */ {564, 4, 9, 5, 1, -8}, + /* 0x84 */ {569, 3, 3, 5, 1, 0}, + /* 0x85 */ {571, 5, 1, 7, 1, 0}, + /* 0x86 */ {572, 5, 11, 7, 1, -8}, + /* 0x87 */ {579, 5, 11, 7, 1, -8}, + /* 0x88 */ {586, 7, 9, 8, 0, -8}, + /* 0x89 */ {594, 12, 9, 12, 0, -8}, + /* 0x8A */ {608, 11, 9, 13, 1, -8}, + /* 0x8B */ {621, 2, 3, 4, 1, -4}, + /* 0x8C */ {622, 11, 9, 12, 1, -8}, + /* 0x8D */ {635, 6, 11, 8, 1, -10}, + /* 0x8E */ {644, 9, 9, 9, 0, -8}, + /* 0x8F */ {655, 7, 11, 9, 1, -8}, + /* 0x90 */ {665, 6, 11, 7, 0, -8}, + /* 0x91 */ {674, 1, 3, 3, 1, -8}, + /* 0x92 */ {675, 1, 3, 2, 1, -8}, + /* 0x93 */ {676, 3, 3, 5, 1, -8}, + /* 0x94 */ {678, 3, 3, 5, 1, -8}, + /* 0x95 */ {680, 3, 3, 5, 1, -5}, + /* 0x96 */ {682, 6, 1, 6, 0, -3}, + /* 0x97 */ {683, 12, 1, 12, 0, -3}, + /* 0x98 */ {685, 0, 0, 8, 0, 0}, + /* 0x99 */ {685, 11, 7, 12, 1, -8}, + /* 0x9A */ {695, 9, 6, 10, 0, -5}, + /* 0x9B */ {702, 2, 3, 3, 1, -4}, + /* 0x9C */ {703, 9, 6, 10, 1, -5}, + /* 0x9D */ {710, 4, 9, 6, 1, -8}, + /* 0x9E */ {715, 6, 9, 7, 0, -8}, + /* 0x9F */ {722, 5, 7, 7, 1, -5}, + /* 0xA0 */ {727, 0, 0, 3, 0, 0}, + /* 0xA1 */ {727, 7, 11, 7, 0, -10}, + /* 0xA2 */ {737, 5, 11, 6, 0, -7}, + /* 0xA3 */ {744, 5, 9, 6, 0, -8}, + /* 0xA4 */ {750, 5, 4, 7, 1, -5}, + /* 0xA5 */ {753, 6, 10, 7, 1, -9}, + /* 0xA6 */ {761, 1, 12, 3, 1, -8}, + /* 0xA7 */ {763, 5, 12, 7, 1, -8}, + /* 0xA8 */ {771, 6, 11, 8, 1, -10}, + /* 0xA9 */ {780, 9, 9, 10, 0, -8}, + /* 0xAA */ {791, 7, 9, 9, 1, -8}, + /* 0xAB */ {799, 4, 4, 6, 1, -4}, + /* 0xAC */ {801, 2, 12, 3, 0, -8}, + /* 0xAD */ {804, 0, 0, 0, 0, 0}, + /* 0xAE */ {804, 9, 9, 10, 0, -8}, + /* 0xAF */ {815, 3, 11, 3, 0, -10}, + /* 0xB0 */ {820, 4, 4, 7, 2, -8}, + /* 0xB1 */ {822, 5, 7, 7, 1, -6}, + /* 0xB2 */ {827, 1, 9, 3, 1, -8}, + /* 0xB3 */ {829, 1, 9, 3, 1, -8}, + /* 0xB4 */ {831, 3, 8, 5, 1, -7}, + /* 0xB5 */ {834, 6, 9, 7, 1, -6}, + /* 0xB6 */ {841, 6, 10, 6, 1, -8}, + /* 0xB7 */ {849, 1, 1, 3, 1, -2}, + /* 0xB8 */ {850, 6, 9, 7, 0, -8}, + /* 0xB9 */ {857, 9, 9, 11, 1, -8}, + /* 0xBA */ {868, 6, 6, 6, 0, -5}, + /* 0xBB */ {873, 4, 4, 6, 1, -5}, + /* 0xBC */ {875, 2, 12, 3, 0, -8}, + /* 0xBD */ {878, 6, 9, 8, 1, -8}, + /* 0xBE */ {885, 5, 6, 6, 0, -5}, + /* 0xBF */ {889, 3, 9, 3, 0, -8}, + /* 0xC0 */ {893, 8, 9, 8, 0, -8}, + /* 0xC1 */ {902, 6, 9, 8, 1, -8}, + /* 0xC2 */ {909, 6, 9, 8, 1, -8}, + /* 0xC3 */ {916, 6, 9, 7, 1, -8}, + /* 0xC4 */ {923, 9, 11, 10, 0, -8}, + /* 0xC5 */ {936, 6, 9, 8, 1, -8}, + /* 0xC6 */ {943, 9, 9, 11, 1, -8}, + /* 0xC7 */ {954, 6, 9, 8, 1, -8}, + /* 0xC8 */ {961, 7, 9, 9, 1, -8}, + /* 0xC9 */ {969, 7, 11, 9, 1, -10}, + /* 0xCA */ {979, 6, 9, 8, 1, -8}, + /* 0xCB */ {986, 7, 9, 8, 0, -8}, + /* 0xCC */ {994, 8, 9, 10, 1, -8}, + /* 0xCD */ {1003, 7, 9, 9, 1, -8}, + /* 0xCE */ {1011, 8, 9, 10, 1, -8}, + /* 0xCF */ {1020, 7, 9, 9, 1, -8}, + /* 0xD0 */ {1028, 6, 9, 8, 1, -8}, + /* 0xD1 */ {1035, 7, 9, 9, 1, -8}, + /* 0xD2 */ {1043, 7, 9, 7, 0, -8}, + /* 0xD3 */ {1051, 7, 9, 7, 0, -8}, + /* 0xD4 */ {1059, 9, 9, 10, 1, -8}, + /* 0xD5 */ {1070, 6, 9, 8, 1, -8}, + /* 0xD6 */ {1077, 8, 11, 9, 1, -8}, + /* 0xD7 */ {1088, 6, 9, 8, 1, -8}, + /* 0xD8 */ {1095, 8, 9, 10, 1, -8}, + /* 0xD9 */ {1104, 9, 11, 10, 1, -8}, + /* 0xDA */ {1117, 10, 9, 10, 0, -8}, + /* 0xDB */ {1129, 9, 9, 10, 1, -8}, + /* 0xDC */ {1140, 6, 9, 8, 1, -8}, + /* 0xDD */ {1147, 7, 9, 9, 1, -8}, + /* 0xDE */ {1155, 10, 9, 12, 1, -8}, + /* 0xDF */ {1167, 6, 9, 8, 1, -8}, + /* 0xE0 */ {1174, 6, 6, 7, 0, -5}, + /* 0xE1 */ {1179, 6, 9, 7, 0, -8}, + /* 0xE2 */ {1186, 5, 6, 6, 1, -5}, + /* 0xE3 */ {1190, 4, 6, 5, 1, -5}, + /* 0xE4 */ {1193, 7, 7, 7, 0, -5}, + /* 0xE5 */ {1200, 6, 6, 7, 0, -5}, + /* 0xE6 */ {1205, 8, 6, 9, 1, -5}, + /* 0xE7 */ {1211, 6, 6, 6, 0, -5}, + /* 0xE8 */ {1216, 5, 6, 7, 1, -5}, + /* 0xE9 */ {1220, 5, 8, 7, 1, -7}, + /* 0xEA */ {1225, 4, 6, 6, 1, -5}, + /* 0xEB */ {1228, 5, 6, 6, 0, -5}, + /* 0xEC */ {1232, 6, 6, 7, 1, -5}, + /* 0xED */ {1237, 5, 6, 7, 1, -5}, + /* 0xEE */ {1241, 6, 6, 7, 0, -5}, + /* 0xEF */ {1246, 5, 6, 7, 1, -5}, + /* 0xF0 */ {1250, 5, 9, 7, 1, -5}, + /* 0xF1 */ {1256, 6, 6, 6, 0, -5}, + /* 0xF2 */ {1261, 5, 6, 5, 0, -5}, + /* 0xF3 */ {1265, 5, 9, 6, 0, -5}, + /* 0xF4 */ {1271, 10, 11, 10, 0, -7}, + /* 0xF5 */ {1285, 5, 6, 6, 0, -5}, + /* 0xF6 */ {1289, 6, 7, 7, 1, -5}, + /* 0xF7 */ {1295, 4, 6, 6, 1, -5}, + /* 0xF8 */ {1298, 6, 6, 8, 1, -5}, + /* 0xF9 */ {1303, 7, 7, 9, 1, -5}, + /* 0xFA */ {1310, 7, 6, 8, 0, -5}, + /* 0xFB */ {1316, 6, 6, 8, 1, -5}, + /* 0xFC */ {1321, 5, 6, 6, 1, -5}, + /* 0xFD */ {1325, 5, 6, 6, 1, -5}, + /* 0xFE */ {1329, 8, 6, 9, 1, -5}, + /* 0xFF */ {1335, 5, 6, 7, 1, -5}, +}; + +const GFXfont FreeSans6pt_Win1251 PROGMEM = {(uint8_t *)FreeSans6pt_Win1251Bitmaps, (GFXglyph *)FreeSans6pt_Win1251Glyphs, 0x20, + 0xFF, 14}; diff --git a/src/graphics/niche/Fonts/FreeSans6pt_Win1252.h b/src/graphics/niche/Fonts/FreeSans6pt_Win1252.h new file mode 100644 index 000000000..32f995270 --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans6pt_Win1252.h @@ -0,0 +1,457 @@ +#pragma once +const uint8_t FreeSans6pt_Win1252Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFC, 0x80, /* '!' 0x21 */ + 0xB6, 0x80, /* '"' 0x22 */ + 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */ + 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */ + 0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */ + 0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */ + 0xE0, /* ''' 0x27 */ + 0x5A, 0xAA, 0x94, /* '(' 0x28 */ + 0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */ + 0x5E, 0x80, /* '*' 0x2A */ + 0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */ + 0xE0, /* ',' 0x2C */ + 0xC0, /* '-' 0x2D */ + 0x80, /* '.' 0x2E */ + 0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */ + 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */ + 0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */ + 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */ + 0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */ + 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */ + 0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */ + 0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */ + 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */ + 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */ + 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */ + 0x82, /* ':' 0x3A */ + 0x87, /* ';' 0x3B */ + 0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */ + 0xF8, 0x3E, /* '=' 0x3D */ + 0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */ + 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */ + 0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */ + 0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */ + 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */ + 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */ + 0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */ + 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */ + 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */ + 0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */ + 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */ + 0xFF, 0x80, /* 'I' 0x49 */ + 0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */ + 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */ + 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */ + 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */ + 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */ + 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */ + 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */ + 0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */ + 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */ + 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */ + 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */ + 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */ + 0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */ + 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */ + 0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */ + 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */ + 0xEA, 0xAA, 0xAB, /* '[' 0x5B */ + 0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */ + 0xD5, 0x55, 0x57, /* ']' 0x5D */ + 0x46, 0xA9, /* '^' 0x5E */ + 0xFE, /* '_' 0x5F */ + 0x80, /* '`' 0x60 */ + 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */ + 0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */ + 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */ + 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */ + 0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */ + 0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */ + 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */ + 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */ + 0xBF, 0x80, /* 'i' 0x69 */ + 0x45, 0x55, 0x57, /* 'j' 0x6A */ + 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */ + 0xFF, 0x80, /* 'l' 0x6C */ + 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */ + 0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */ + 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */ + 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */ + 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */ + 0xF2, 0x49, 0x20, /* 'r' 0x72 */ + 0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */ + 0x5D, 0x24, 0x93, /* 't' 0x74 */ + 0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */ + 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */ + 0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */ + 0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */ + 0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */ + 0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */ + 0x6A, 0xAA, 0xA9, /* '{' 0x7B */ + 0xFF, 0xE0, /* '|' 0x7C */ + 0x95, 0x55, 0x56, /* '}' 0x7D */ + 0x66, 0x60, /* '~' 0x7E */ + 0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */ + 0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */ + /* 0x81 */ + 0xE0, /* 0x82 */ + 0x6B, 0xA4, 0x92, 0x49, 0x60, /* 0x83 */ + 0xB6, 0x80, /* 0x84 */ + 0xA8, /* 0x85 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */ + 0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */ + 0x54, /* 0x88 */ + 0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */ + 0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */ + 0x64, /* 0x8B */ + 0x3B, 0xE8, 0xC2, 0x08, 0x41, 0x08, 0x3F, 0x04, 0x20, 0x82, 0x30, 0x3B, 0xE0, /* 0x8C */ + /* 0x8D */ + 0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */ + /* 0x8F */ + /* 0x90 */ + 0xE0, /* 0x91 */ + 0xE0, /* 0x92 */ + 0xB6, 0x80, /* 0x93 */ + 0xB6, 0x80, /* 0x94 */ + 0xFF, 0x80, /* 0x95 */ + 0xFC, /* 0x96 */ + 0xFF, 0xF0, /* 0x97 */ + 0xDB, /* 0x98 */ + 0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */ + 0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */ + 0x98, /* 0x9B */ + 0x7B, 0xD9, 0xCE, 0x10, 0xC3, 0xF8, 0x41, 0x9C, 0x5E, 0xF0, /* 0x9C */ + /* 0x9D */ + 0x51, 0x1E, 0x11, 0x11, 0x88, 0xF8, /* 0x9E */ + 0x29, 0x05, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0x9F */ + /* 0xA0 */ + 0xBF, 0x80, /* 0xA1 */ + 0x23, 0xAB, 0x4A, 0x52, 0xAE, 0x20, /* 0xA2 */ + 0x39, 0x14, 0x10, 0xF0, 0x82, 0x1C, 0x4C, /* 0xA3 */ + 0xFC, 0x63, 0xF0, /* 0xA4 */ + 0x8C, 0x54, 0xAF, 0x93, 0xE4, 0x20, /* 0xA5 */ + 0xF9, 0xF0, /* 0xA6 */ + 0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */ + 0xA0, /* 0xA8 */ + 0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */ + 0x61, 0x79, 0x60, /* 0xAA */ + 0x5A, 0xA5, /* 0xAB */ + 0xFC, 0x10, 0x40, /* 0xAC */ + /* 0xAD */ + 0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */ + 0xE0, /* 0xAF */ + 0x69, 0x96, /* 0xB0 */ + 0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */ + 0x69, 0x3C, 0xF0, /* 0xB2 */ + 0x79, 0x29, 0x70, /* 0xB3 */ + 0x80, /* 0xB4 */ + 0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */ + 0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */ + 0x80, /* 0xB7 */ + 0x67, 0x80, /* 0xB8 */ + 0x75, 0x50, /* 0xB9 */ + 0x69, 0x96, 0xF0, /* 0xBA */ + 0xA5, 0x5A, /* 0xBB */ + 0x42, 0x30, 0x84, 0x41, 0x10, 0x48, 0x82, 0x61, 0x28, 0x8F, 0x20, 0x80, /* 0xBC */ + 0x40, 0x63, 0x11, 0x09, 0x74, 0xA8, 0x84, 0x44, 0x44, 0x43, 0x80, /* 0xBD */ + 0x71, 0x24, 0x82, 0x20, 0x50, 0x98, 0x9A, 0x61, 0x28, 0x4F, 0x20, 0x80, /* 0xBE */ + 0x20, 0x08, 0x44, 0x42, 0x11, 0x70, /* 0xBF */ + 0x10, 0x08, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC0 */ + 0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */ + 0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */ + 0x34, 0x2C, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */ + 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */ + 0x18, 0x24, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC5 */ + 0x1F, 0xC5, 0x02, 0x40, 0x90, 0x47, 0xDF, 0x04, 0x42, 0x10, 0x87, 0xC0, /* 0xC6 */ + 0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */ + 0x20, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC8 */ + 0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */ + 0x10, 0xA0, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xCA */ + 0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */ + 0x91, 0x55, 0x50, /* 0xCC */ + 0x62, 0xAA, 0xA0, /* 0xCD */ + 0x54, 0x24, 0x92, 0x48, /* 0xCE */ + 0xA1, 0x24, 0x92, 0x48, /* 0xCF */ + 0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */ + 0x14, 0x53, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */ + 0x10, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD2 */ + 0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */ + 0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */ + 0x1A, 0x0B, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */ + 0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */ + 0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */ + 0x3E, 0xB1, 0xB0, 0xF0, 0x98, 0x8C, 0x87, 0x86, 0xC6, 0xBE, 0x00, /* 0xD8 */ + 0x20, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */ + 0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */ + 0x10, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */ + 0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */ + 0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */ + 0x83, 0xE8, 0x61, 0x87, 0xE8, 0x20, 0x80, /* 0xDE */ + 0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */ + 0x20, 0x20, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE0 */ + 0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */ + 0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */ + 0x68, 0xB0, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */ + 0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */ + 0x10, 0x50, 0x43, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE5 */ + 0x7B, 0xA1, 0x90, 0x45, 0xFF, 0x84, 0x23, 0x17, 0x38, /* 0xE6 */ + 0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */ + 0x20, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE8 */ + 0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */ + 0x10, 0xA0, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEA */ + 0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */ + 0x91, 0x55, 0x50, /* 0xEC */ + 0x62, 0xAA, 0xA0, /* 0xED */ + 0x54, 0x24, 0x92, 0x48, /* 0xEE */ + 0xA1, 0x24, 0x92, 0x40, /* 0xEF */ + 0x28, 0x42, 0x8F, 0x46, 0x18, 0x52, 0x30, /* 0xF0 */ + 0x6A, 0xC1, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */ + 0x20, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF2 */ + 0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */ + 0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */ + 0x69, 0x60, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */ + 0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */ + 0x20, 0x3E, 0x02, 0x00, /* 0xF7 */ + 0x7F, 0x39, 0x69, 0xC7, 0x3F, 0x80, /* 0xF8 */ + 0x41, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xF9 */ + 0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */ + 0x22, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */ + 0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */ + 0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */ + 0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF4, 0x20, /* 0xFE */ + 0x28, 0x08, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFF */ +}; + +const GFXglyph FreeSans6pt_Win1252Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 3, 0, 0}, + /* '!' 0x21 */ {0, 1, 9, 4, 2, -8}, + /* '"' 0x22 */ {2, 3, 3, 4, 0, -8}, + /* '#' 0x23 */ {4, 7, 8, 7, 0, -7}, + /* '$' 0x24 */ {11, 6, 11, 7, 0, -9}, + /* '%' 0x25 */ {20, 10, 9, 11, 0, -8}, + /* '&' 0x26 */ {32, 6, 9, 8, 1, -8}, + /* ''' 0x27 */ {39, 1, 3, 2, 1, -8}, + /* '(' 0x28 */ {40, 2, 11, 4, 1, -8}, + /* ')' 0x29 */ {43, 3, 11, 4, 0, -8}, + /* '*' 0x2A */ {48, 3, 3, 5, 1, -8}, + /* '+' 0x2B */ {50, 5, 5, 7, 1, -4}, + /* ',' 0x2C */ {54, 1, 3, 3, 1, 0}, + /* '-' 0x2D */ {55, 2, 1, 4, 1, -3}, + /* '.' 0x2E */ {56, 1, 1, 3, 1, 0}, + /* '/' 0x2F */ {57, 3, 9, 3, 0, -8}, + /* '0' 0x30 */ {61, 5, 9, 7, 1, -8}, + /* '1' 0x31 */ {67, 3, 9, 7, 1, -8}, + /* '2' 0x32 */ {71, 6, 9, 7, 0, -8}, + /* '3' 0x33 */ {78, 6, 9, 7, 0, -8}, + /* '4' 0x34 */ {85, 6, 9, 7, 0, -8}, + /* '5' 0x35 */ {92, 5, 9, 7, 1, -8}, + /* '6' 0x36 */ {98, 5, 9, 7, 1, -8}, + /* '7' 0x37 */ {104, 5, 9, 7, 1, -8}, + /* '8' 0x38 */ {110, 6, 9, 7, 0, -8}, + /* '9' 0x39 */ {117, 6, 9, 7, 0, -8}, + /* ':' 0x3A */ {124, 1, 7, 3, 1, -6}, + /* ';' 0x3B */ {125, 1, 8, 3, 1, -5}, + /* '<' 0x3C */ {126, 5, 5, 7, 1, -4}, + /* '=' 0x3D */ {130, 5, 3, 7, 1, -3}, + /* '>' 0x3E */ {132, 5, 5, 7, 1, -4}, + /* '?' 0x3F */ {136, 5, 9, 7, 1, -8}, + /* '@' 0x40 */ {142, 11, 11, 12, 0, -8}, + /* 'A' 0x41 */ {158, 8, 9, 8, 0, -8}, + /* 'B' 0x42 */ {167, 6, 9, 8, 1, -8}, + /* 'C' 0x43 */ {174, 8, 9, 9, 0, -8}, + /* 'D' 0x44 */ {183, 7, 9, 8, 1, -8}, + /* 'E' 0x45 */ {191, 6, 9, 8, 1, -8}, + /* 'F' 0x46 */ {198, 6, 9, 7, 1, -8}, + /* 'G' 0x47 */ {205, 8, 9, 9, 0, -8}, + /* 'H' 0x48 */ {214, 7, 9, 9, 1, -8}, + /* 'I' 0x49 */ {222, 1, 9, 3, 1, -8}, + /* 'J' 0x4A */ {224, 5, 9, 6, 0, -8}, + /* 'K' 0x4B */ {230, 7, 9, 8, 1, -8}, + /* 'L' 0x4C */ {238, 5, 9, 7, 1, -8}, + /* 'M' 0x4D */ {244, 8, 9, 10, 1, -8}, + /* 'N' 0x4E */ {253, 7, 9, 9, 1, -8}, + /* 'O' 0x4F */ {261, 9, 9, 9, 0, -8}, + /* 'P' 0x50 */ {272, 6, 9, 8, 1, -8}, + /* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8}, + /* 'R' 0x52 */ {291, 7, 9, 9, 1, -8}, + /* 'S' 0x53 */ {299, 6, 9, 8, 1, -8}, + /* 'T' 0x54 */ {306, 7, 9, 8, 0, -8}, + /* 'U' 0x55 */ {314, 7, 9, 9, 1, -8}, + /* 'V' 0x56 */ {322, 7, 9, 8, 0, -8}, + /* 'W' 0x57 */ {330, 11, 9, 11, 0, -8}, + /* 'X' 0x58 */ {343, 6, 9, 8, 1, -8}, + /* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8}, + /* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8}, + /* '[' 0x5B */ {367, 2, 12, 3, 1, -8}, + /* '\' 0x5C */ {370, 3, 9, 3, 0, -8}, + /* ']' 0x5D */ {374, 2, 12, 3, 0, -8}, + /* '^' 0x5E */ {377, 4, 4, 6, 1, -8}, + /* '_' 0x5F */ {379, 7, 1, 7, 0, 2}, + /* '`' 0x60 */ {380, 1, 1, 3, 1, -8}, + /* 'a' 0x61 */ {381, 6, 7, 7, 0, -6}, + /* 'b' 0x62 */ {387, 5, 9, 7, 1, -8}, + /* 'c' 0x63 */ {393, 6, 7, 6, 0, -6}, + /* 'd' 0x64 */ {399, 6, 9, 7, 0, -8}, + /* 'e' 0x65 */ {406, 6, 7, 6, 0, -6}, + /* 'f' 0x66 */ {412, 3, 9, 3, 0, -8}, + /* 'g' 0x67 */ {416, 6, 10, 7, 0, -6}, + /* 'h' 0x68 */ {424, 5, 9, 6, 1, -8}, + /* 'i' 0x69 */ {430, 1, 9, 3, 1, -8}, + /* 'j' 0x6A */ {432, 2, 12, 3, 0, -8}, + /* 'k' 0x6B */ {435, 5, 9, 6, 1, -8}, + /* 'l' 0x6C */ {441, 1, 9, 3, 1, -8}, + /* 'm' 0x6D */ {443, 8, 7, 10, 1, -6}, + /* 'n' 0x6E */ {450, 5, 7, 6, 1, -6}, + /* 'o' 0x6F */ {455, 6, 7, 6, 0, -6}, + /* 'p' 0x70 */ {461, 5, 9, 7, 1, -6}, + /* 'q' 0x71 */ {467, 6, 9, 7, 0, -6}, + /* 'r' 0x72 */ {474, 3, 7, 4, 1, -6}, + /* 's' 0x73 */ {477, 5, 7, 6, 0, -6}, + /* 't' 0x74 */ {482, 3, 8, 3, 0, -7}, + /* 'u' 0x75 */ {485, 5, 7, 6, 1, -6}, + /* 'v' 0x76 */ {490, 6, 7, 6, 0, -6}, + /* 'w' 0x77 */ {496, 8, 7, 9, 0, -6}, + /* 'x' 0x78 */ {503, 5, 7, 6, 0, -6}, + /* 'y' 0x79 */ {508, 5, 10, 6, 0, -6}, + /* 'z' 0x7A */ {515, 5, 7, 6, 0, -6}, + /* '{' 0x7B */ {520, 2, 12, 4, 1, -8}, + /* '|' 0x7C */ {523, 1, 11, 3, 1, -8}, + /* '}' 0x7D */ {525, 2, 12, 4, 1, -8}, + /* '~' 0x7E */ {528, 6, 2, 6, 0, -4}, + /* 0x7F */ {530, 9, 10, 11, 1, -8}, + /* 0x80 */ {542, 7, 9, 8, 0, -8}, + /* 0x81 */ {550, 0, 0, 8, 0, 0}, + /* 0x82 */ {550, 1, 3, 3, 1, 0}, + /* 0x83 */ {551, 3, 12, 3, 0, -8}, + /* 0x84 */ {556, 3, 3, 5, 1, 0}, + /* 0x85 */ {558, 5, 1, 7, 1, 0}, + /* 0x86 */ {559, 5, 11, 7, 1, -8}, + /* 0x87 */ {566, 5, 11, 7, 1, -8}, + /* 0x88 */ {573, 3, 2, 4, 0, -9}, + /* 0x89 */ {574, 12, 9, 12, 0, -8}, + /* 0x8A */ {588, 6, 11, 8, 1, -9}, + /* 0x8B */ {597, 2, 3, 4, 1, -4}, + /* 0x8C */ {598, 11, 9, 12, 0, -8}, + /* 0x8D */ {611, 0, 0, 8, 0, 0}, + /* 0x8E */ {611, 7, 10, 7, 0, -9}, + /* 0x8F */ {620, 0, 0, 8, 0, 0}, + /* 0x90 */ {620, 0, 0, 8, 0, 0}, + /* 0x91 */ {620, 1, 3, 3, 1, -8}, + /* 0x92 */ {621, 1, 3, 2, 1, -8}, + /* 0x93 */ {622, 3, 3, 5, 1, -8}, + /* 0x94 */ {624, 3, 3, 5, 1, -8}, + /* 0x95 */ {626, 3, 3, 5, 1, -5}, + /* 0x96 */ {628, 6, 1, 6, 0, -3}, + /* 0x97 */ {629, 12, 1, 12, 0, -3}, + /* 0x98 */ {631, 4, 2, 4, 0, -8}, + /* 0x99 */ {632, 11, 7, 12, 1, -8}, + /* 0x9A */ {642, 4, 9, 6, 1, -8}, + /* 0x9B */ {647, 2, 3, 3, 1, -4}, + /* 0x9C */ {648, 11, 7, 11, 0, -6}, + /* 0x9D */ {658, 0, 0, 8, 0, 0}, + /* 0x9E */ {658, 5, 9, 6, 0, -8}, + /* 0x9F */ {664, 7, 10, 8, 1, -9}, + /* 0xA0 */ {673, 0, 0, 3, 0, 0}, + /* 0xA1 */ {673, 1, 9, 4, 1, -5}, + /* 0xA2 */ {675, 5, 9, 7, 1, -7}, + /* 0xA3 */ {681, 6, 9, 7, 0, -8}, + /* 0xA4 */ {688, 5, 4, 7, 1, -5}, + /* 0xA5 */ {691, 5, 9, 7, 1, -8}, + /* 0xA6 */ {697, 1, 12, 3, 1, -8}, + /* 0xA7 */ {699, 5, 12, 7, 1, -8}, + /* 0xA8 */ {707, 3, 1, 4, 0, -7}, + /* 0xA9 */ {708, 9, 9, 10, 0, -8}, + /* 0xAA */ {719, 4, 5, 4, 0, -8}, + /* 0xAB */ {722, 4, 4, 6, 1, -4}, + /* 0xAC */ {724, 6, 3, 7, 1, -4}, + /* 0xAD */ {727, 0, 0, 0, 0, 0}, + /* 0xAE */ {727, 9, 9, 10, 0, -8}, + /* 0xAF */ {738, 3, 1, 4, 0, -8}, + /* 0xB0 */ {739, 4, 4, 7, 2, -8}, + /* 0xB1 */ {741, 5, 7, 7, 1, -6}, + /* 0xB2 */ {746, 4, 5, 4, 0, -9}, + /* 0xB3 */ {749, 4, 5, 4, 0, -9}, + /* 0xB4 */ {752, 1, 1, 4, 1, -8}, + /* 0xB5 */ {753, 6, 9, 7, 1, -6}, + /* 0xB6 */ {760, 6, 10, 6, 1, -8}, + /* 0xB7 */ {768, 1, 1, 3, 1, -2}, + /* 0xB8 */ {769, 3, 3, 4, 1, 1}, + /* 0xB9 */ {771, 2, 6, 4, 1, -9}, + /* 0xBA */ {773, 4, 5, 4, 0, -8}, + /* 0xBB */ {776, 4, 4, 6, 1, -5}, + /* 0xBC */ {778, 10, 9, 10, 1, -8}, + /* 0xBD */ {790, 9, 9, 10, 1, -8}, + /* 0xBE */ {801, 10, 9, 11, 0, -8}, + /* 0xBF */ {813, 5, 9, 7, 1, -5}, + /* 0xC0 */ {819, 8, 10, 8, 0, -9}, + /* 0xC1 */ {829, 8, 10, 8, 0, -9}, + /* 0xC2 */ {839, 8, 10, 8, 0, -9}, + /* 0xC3 */ {849, 8, 10, 8, 0, -9}, + /* 0xC4 */ {859, 8, 10, 8, 0, -9}, + /* 0xC5 */ {869, 8, 10, 8, 0, -9}, + /* 0xC6 */ {879, 10, 9, 12, 1, -8}, + /* 0xC7 */ {891, 8, 12, 9, 0, -8}, + /* 0xC8 */ {903, 6, 10, 8, 1, -9}, + /* 0xC9 */ {911, 6, 10, 8, 1, -9}, + /* 0xCA */ {919, 6, 10, 8, 1, -9}, + /* 0xCB */ {927, 6, 10, 8, 1, -9}, + /* 0xCC */ {935, 2, 10, 3, 0, -9}, + /* 0xCD */ {938, 2, 10, 3, 1, -9}, + /* 0xCE */ {941, 3, 10, 4, 0, -9}, + /* 0xCF */ {945, 3, 10, 4, 0, -9}, + /* 0xD0 */ {949, 8, 9, 8, 0, -8}, + /* 0xD1 */ {958, 7, 10, 9, 1, -9}, + /* 0xD2 */ {967, 9, 10, 9, 0, -9}, + /* 0xD3 */ {979, 9, 10, 9, 0, -9}, + /* 0xD4 */ {991, 9, 11, 9, 0, -10}, + /* 0xD5 */ {1004, 9, 11, 9, 0, -10}, + /* 0xD6 */ {1017, 9, 11, 9, 0, -10}, + /* 0xD7 */ {1030, 5, 5, 7, 1, -5}, + /* 0xD8 */ {1034, 9, 9, 9, 0, -8}, + /* 0xD9 */ {1045, 7, 10, 9, 1, -9}, + /* 0xDA */ {1054, 7, 10, 9, 1, -9}, + /* 0xDB */ {1063, 7, 10, 9, 1, -9}, + /* 0xDC */ {1072, 7, 10, 9, 1, -9}, + /* 0xDD */ {1081, 7, 10, 8, 1, -9}, + /* 0xDE */ {1090, 6, 9, 8, 1, -8}, + /* 0xDF */ {1097, 6, 9, 7, 1, -8}, + /* 0xE0 */ {1104, 7, 10, 7, 0, -9}, + /* 0xE1 */ {1113, 7, 10, 7, 0, -9}, + /* 0xE2 */ {1122, 7, 10, 7, 0, -9}, + /* 0xE3 */ {1131, 7, 10, 7, 0, -9}, + /* 0xE4 */ {1140, 7, 9, 7, 0, -8}, + /* 0xE5 */ {1148, 7, 10, 7, 0, -9}, + /* 0xE6 */ {1157, 10, 7, 10, 0, -6}, + /* 0xE7 */ {1166, 6, 10, 6, 0, -6}, + /* 0xE8 */ {1174, 6, 10, 6, 0, -9}, + /* 0xE9 */ {1182, 6, 10, 6, 0, -9}, + /* 0xEA */ {1190, 6, 10, 6, 0, -9}, + /* 0xEB */ {1198, 6, 9, 6, 0, -8}, + /* 0xEC */ {1205, 2, 10, 3, 0, -9}, + /* 0xED */ {1208, 2, 10, 3, 1, -9}, + /* 0xEE */ {1211, 3, 10, 3, 0, -9}, + /* 0xEF */ {1215, 3, 9, 3, 0, -8}, + /* 0xF0 */ {1219, 6, 9, 6, 0, -8}, + /* 0xF1 */ {1226, 5, 10, 6, 1, -9}, + /* 0xF2 */ {1233, 6, 10, 6, 0, -9}, + /* 0xF3 */ {1241, 6, 10, 6, 0, -9}, + /* 0xF4 */ {1249, 6, 10, 6, 0, -9}, + /* 0xF5 */ {1257, 6, 10, 6, 0, -9}, + /* 0xF6 */ {1265, 6, 9, 6, 0, -8}, + /* 0xF7 */ {1272, 5, 5, 7, 1, -5}, + /* 0xF8 */ {1276, 6, 7, 6, 0, -6}, + /* 0xF9 */ {1282, 5, 9, 6, 1, -8}, + /* 0xFA */ {1288, 5, 9, 6, 1, -8}, + /* 0xFB */ {1294, 5, 10, 6, 1, -9}, + /* 0xFC */ {1301, 5, 9, 6, 1, -8}, + /* 0xFD */ {1307, 6, 12, 6, 0, -8}, + /* 0xFE */ {1316, 5, 11, 7, 1, -8}, + /* 0xFF */ {1323, 6, 12, 6, 0, -8}, +}; + +const GFXfont FreeSans6pt_Win1252 PROGMEM = {(uint8_t *)FreeSans6pt_Win1252Bitmaps, (GFXglyph *)FreeSans6pt_Win1252Glyphs, 0x20, + 0xFF, 14}; diff --git a/src/graphics/niche/Fonts/FreeSans9pt_Win1250.h b/src/graphics/niche/Fonts/FreeSans9pt_Win1250.h new file mode 100644 index 000000000..7022939a0 --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans9pt_Win1250.h @@ -0,0 +1,494 @@ +#pragma once +const uint8_t FreeSans9pt_Win1250Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */ + 0xDE, 0xF7, 0x20, /* '"' 0x22 */ + 0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */ + 0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */ + 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04, + 0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */ + 0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */ + 0xFE, /* ''' 0x27 */ + 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */ + 0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */ + 0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */ + 0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */ + 0xD6, /* ',' 0x2C */ + 0xF0, /* '-' 0x2D */ + 0xC0, /* '.' 0x2E */ + 0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */ + 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */ + 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */ + 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */ + 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */ + 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */ + 0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */ + 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */ + 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */ + 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */ + 0xC0, 0x00, 0x30, /* ':' 0x3A */ + 0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */ + 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */ + 0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */ + 0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */ + 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11, + 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */ + 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, + 0x30, /* 'A' 0x41 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */ + 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */ + 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */ + 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */ + 0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F, + 0x10, /* 'G' 0x47 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */ + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */ + 0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */ + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */ + 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, + 0x80, /* 'M' 0x4D */ + 0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, + 0x00, /* 'O' 0x4F */ + 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB, + 0x00, 0x08, /* 'Q' 0x51 */ + 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, + 0x70, /* 'R' 0x52 */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */ + 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */ + 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */ + 0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C, + 0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */ + 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */ + 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, + 0x00, /* 'Y' 0x59 */ + 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */ + 0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */ + 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */ + 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */ + 0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */ + 0xFF, 0xC0, /* '_' 0x5F */ + 0xC6, 0x30, /* '`' 0x60 */ + 0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */ + 0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */ + 0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */ + 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */ + 0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */ + 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */ + 0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */ + 0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */ + 0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */ + 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */ + 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */ + 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */ + 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */ + 0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */ + 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */ + 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */ + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */ + 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */ + 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */ + 0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */ + 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */ + 0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */ + 0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */ + 0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */ + 0x61, 0x24, 0x38, /* '~' 0x7E */ + 0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00, + 0xFF, 0xFC, /* 0x7F */ + 0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x80 */ + /* 0x81 */ + 0xDC, /* 0x82 */ + /* 0x83 */ + 0xDA, 0x76, /* 0x84 */ + 0xCC, 0xC0, /* 0x85 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */ + /* 0x88 */ + 0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84, + 0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */ + 0x1B, 0x03, 0x83, 0xF1, 0x86, 0xC0, 0xF0, 0x3C, 0x01, 0xE0, 0x1F, 0x00, 0xE0, 0x0F, 0x03, 0xC0, 0xD8, 0x63, 0xF0, /* 0x8A */ + 0x69, /* 0x8B */ + 0x06, 0x03, 0x03, 0xF1, 0x86, 0xC0, 0xF0, 0x3C, 0x01, 0xE0, 0x1F, 0x00, 0xE0, 0x0F, 0x03, 0xC0, 0xD8, 0x63, 0xF0, /* 0x8C */ + 0x33, 0x0F, 0x3F, 0xE1, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, /* 0x8D */ + 0x1B, 0x03, 0x8F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0x8E */ + 0x0C, 0x06, 0x0F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0x8F */ + /* 0x90 */ + 0x6B, /* 0x91 */ + 0xD6, /* 0x92 */ + 0x4C, 0xA5, 0xB0, /* 0x93 */ + 0xDA, 0x53, 0x20, /* 0x94 */ + 0x6F, 0xFF, 0x60, /* 0x95 */ + 0xFE, /* 0x96 */ + 0xFF, 0xFF, /* 0x97 */ + /* 0x98 */ + 0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC, + 0x33, 0x30, /* 0x99 */ + 0x24, 0x3C, 0x18, 0x7E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9A */ + 0x96, /* 0x9B */ + 0x0C, 0x18, 0x10, 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9C */ + 0x0D, 0xA7, 0x3C, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x70, /* 0x9D */ + 0x48, 0xF0, 0xC7, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9E */ + 0x0C, 0x10, 0x47, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9F */ + /* 0xA0 */ + 0x8A, 0x9C, /* 0xA1 */ + 0x85, 0xE0, /* 0xA2 */ + 0x60, 0x30, 0x18, 0x0C, 0x86, 0xC3, 0xC1, 0xC1, 0xC0, 0xE0, 0x30, 0x18, 0x0C, 0x07, 0xF8, /* 0xA3 */ + 0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */ + 0x06, 0x00, 0xF0, 0x0F, 0x01, 0x30, 0x13, 0x81, 0x38, 0x21, 0x82, 0x1C, 0x3F, 0xC6, 0x04, 0x60, 0x66, 0x06, 0xC0, 0x30, 0x06, + 0x00, 0xC0, 0x0C, 0x00, 0x70, /* 0xA5 */ + 0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */ + 0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E, + 0x00, /* 0xA7 */ + 0xCC, /* 0xA8 */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18, + 0x0F, 0xC0, /* 0xA9 */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x02, 0x00, 0xE0, 0x18, 0x1C, + 0x00, /* 0xAA */ + 0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */ + 0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */ + /* 0xAD */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18, + 0x0F, 0xC0, /* 0xAE */ + 0x0C, 0x00, 0x0F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0xAF */ + 0x74, 0x63, 0x17, 0x00, /* 0xB0 */ + 0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */ + 0x6C, 0xC7, /* 0xB2 */ + 0x66, 0x66, 0x67, 0x6E, 0x66, 0x66, 0x60, /* 0xB3 */ + 0x36, 0xC0, /* 0xB4 */ + 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */ + 0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */ + 0xE0, /* 0xB7 */ + 0x21, 0xC7, 0xE0, /* 0xB8 */ + 0x7E, 0x38, 0xCC, 0x30, 0x0C, 0x0F, 0x1E, 0xCC, 0x33, 0x0C, 0xC7, 0x1E, 0xE0, 0x10, 0x0C, 0x03, 0x00, 0x70, /* 0xB9 */ + 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xC3, 0x7E, 0x10, 0x1C, 0x0C, 0x38, /* 0xBA */ + 0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */ + 0xC6, 0xC4, 0xC8, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xBC */ + 0x6F, 0x69, 0x00, /* 0xBD */ + 0xDE, 0xB9, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xBE */ + 0x30, 0x03, 0xF8, 0x30, 0xC3, 0x06, 0x18, 0x60, 0x83, 0x07, 0xF0, /* 0xBF */ + 0x06, 0x00, 0xC0, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, + 0xC0, 0x70, /* 0xC0 */ + 0x06, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC1 */ + 0x0C, 0x04, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC2 */ + 0x21, 0x07, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC3 */ + 0x33, 0x00, 0x00, 0xC0, 0x78, 0x1E, 0x04, 0x83, 0x30, 0xCC, 0x33, 0x1F, 0xE6, 0x19, 0x02, 0xC0, 0xF0, 0x30, /* 0xC4 */ + 0x30, 0x60, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xC5 */ + 0x06, 0x01, 0x80, 0x00, 0x0F, 0xC3, 0x0C, 0xC0, 0xD0, 0x1E, 0x00, 0xC0, 0x18, 0x03, 0x01, 0xA0, 0x36, 0x0C, 0x61, 0x87, + 0xC0, /* 0xC6 */ + 0x1F, 0x06, 0x19, 0x83, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0xE1, 0xF0, 0x08, 0x01, 0xC0, + 0x18, 0x0E, 0x00, /* 0xC7 */ + 0x19, 0x81, 0xE0, 0x00, 0x0F, 0xC3, 0x0C, 0xC0, 0xF0, 0x1E, 0x00, 0xC0, 0x18, 0x03, 0x01, 0xA0, 0x36, 0x0C, 0x61, 0x87, + 0xC0, /* 0xC8 */ + 0x0C, 0x0C, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC9 */ + 0xFF, 0xD8, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0F, 0xFC, 0x01, 0x80, 0x60, + 0x0C, 0x00, 0xE0, /* 0xCA */ + 0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCB */ + 0x33, 0x0F, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFE, /* 0xCC */ + 0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xC0, /* 0xCD */ + 0x76, 0xC0, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, /* 0xCE */ + 0x66, 0x0F, 0x00, 0x03, 0xF8, 0xC3, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC1, 0xB0, 0xEF, 0xE0, /* 0xCF */ + 0x7F, 0x0C, 0x31, 0x83, 0x30, 0x36, 0x06, 0xC0, 0xFE, 0x1B, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x30, 0xE7, 0xF0, /* 0xD0 */ + 0x03, 0x01, 0x83, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81, + 0xC0, /* 0xD1 */ + 0x19, 0x81, 0xE3, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81, + 0xC0, /* 0xD2 */ + 0x03, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD3 */ + 0x0F, 0x01, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD4 */ + 0x0D, 0x81, 0xB0, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD5 */ + 0x19, 0x81, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD6 */ + 0x83, 0x89, 0xA1, 0x83, 0x89, 0xA1, 0x80, /* 0xD7 */ + 0x33, 0x01, 0xE0, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, + 0xC0, 0x70, /* 0xD8 */ + 0x04, 0x01, 0x43, 0x11, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xD9 */ + 0x06, 0x01, 0x83, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDA */ + 0x0D, 0x83, 0x63, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDB */ + 0x1B, 0x00, 0x03, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDC */ + 0x03, 0x0C, 0x63, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x1D, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, + 0x60, /* 0xDD */ + 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x40, 0x3C, 0x06, 0x1E, + 0x00, /* 0xDE */ + 0x3C, 0x33, 0x30, 0xD8, 0x6C, 0x36, 0x33, 0x39, 0x86, 0xC1, 0xE0, 0xF0, 0x78, 0x6D, 0xE0, /* 0xDF */ + 0x19, 0x89, 0xBE, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xE0 */ + 0x0C, 0x04, 0x04, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE1 */ + 0x10, 0x14, 0x1B, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE2 */ + 0x66, 0x1E, 0x00, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE3 */ + 0x66, 0x00, 0x1F, 0x9C, 0x6C, 0x30, 0x18, 0x3C, 0xF6, 0xC3, 0x61, 0xB1, 0xCF, 0x70, /* 0xE4 */ + 0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xD8, /* 0xE5 */ + 0x0C, 0x08, 0x10, 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE6 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x10, 0x1C, 0x0C, 0x38, /* 0xE7 */ + 0x44, 0x28, 0x38, 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE8 */ + 0x0C, 0x08, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE9 */ + 0x3C, 0x62, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3E, 0x04, 0x0C, 0x0C, 0x06, /* 0xEA */ + 0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEB */ + 0x64, 0x2C, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEC */ + 0x7A, 0x6D, 0xB6, 0xDB, 0x6C, /* 0xED */ + 0x69, 0x06, 0x66, 0x66, 0x66, 0x66, 0x60, /* 0xEE */ + 0x03, 0x30, 0x32, 0x03, 0x43, 0xB0, 0x67, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x06, 0x70, 0x3B, + 0x00, /* 0xEF */ + 0x03, 0x07, 0xC0, 0xC7, 0x66, 0x76, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xCC, 0xE3, 0xB0, /* 0xF0 */ + 0x0C, 0x18, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF1 */ + 0x66, 0x3C, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF2 */ + 0x0C, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF3 */ + 0x18, 0x24, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF4 */ + 0x36, 0x6C, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF5 */ + 0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF6 */ + 0x18, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x30, /* 0xF7 */ + 0xDB, 0x81, 0xBE, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xF8 */ + 0x10, 0x28, 0x10, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xF9 */ + 0x06, 0x0C, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFA */ + 0x36, 0x6C, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFB */ + 0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFC */ + 0x06, 0x04, 0x08, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFD */ + 0x63, 0x3C, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xE2, 0x1C, 0x6F, /* 0xFE */ + 0xC0, /* 0xFF */ +}; + +const GFXglyph FreeSans9pt_Win1250Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 5, 0, 0}, + /* '!' 0x21 */ {0, 2, 13, 6, 2, -12}, + /* '"' 0x22 */ {4, 5, 4, 6, 1, -12}, + /* '#' 0x23 */ {7, 10, 12, 10, 0, -11}, + /* '$' 0x24 */ {22, 9, 16, 10, 1, -13}, + /* '%' 0x25 */ {40, 16, 13, 16, 1, -12}, + /* '&' 0x26 */ {66, 10, 13, 12, 1, -12}, + /* ''' 0x27 */ {83, 2, 4, 4, 1, -12}, + /* '(' 0x28 */ {84, 4, 17, 6, 1, -12}, + /* ')' 0x29 */ {93, 4, 17, 6, 1, -12}, + /* '*' 0x2A */ {102, 5, 5, 7, 1, -12}, + /* '+' 0x2B */ {106, 6, 8, 11, 3, -7}, + /* ',' 0x2C */ {112, 2, 4, 5, 2, 0}, + /* '-' 0x2D */ {113, 4, 1, 6, 1, -4}, + /* '.' 0x2E */ {114, 2, 1, 5, 1, 0}, + /* '/' 0x2F */ {115, 5, 13, 5, 0, -12}, + /* '0' 0x30 */ {124, 8, 13, 10, 1, -12}, + /* '1' 0x31 */ {137, 4, 13, 10, 3, -12}, + /* '2' 0x32 */ {144, 9, 13, 10, 1, -12}, + /* '3' 0x33 */ {159, 8, 13, 10, 1, -12}, + /* '4' 0x34 */ {172, 7, 13, 10, 2, -12}, + /* '5' 0x35 */ {184, 9, 13, 10, 1, -12}, + /* '6' 0x36 */ {199, 9, 13, 10, 1, -12}, + /* '7' 0x37 */ {214, 8, 13, 10, 0, -12}, + /* '8' 0x38 */ {227, 9, 13, 10, 1, -12}, + /* '9' 0x39 */ {242, 8, 13, 10, 1, -12}, + /* ':' 0x3A */ {255, 2, 10, 5, 1, -9}, + /* ';' 0x3B */ {258, 3, 12, 5, 1, -8}, + /* '<' 0x3C */ {263, 9, 9, 11, 1, -8}, + /* '=' 0x3D */ {274, 9, 4, 11, 1, -5}, + /* '>' 0x3E */ {279, 9, 8, 11, 1, -7}, + /* '?' 0x3F */ {288, 9, 13, 10, 1, -12}, + /* '@' 0x40 */ {303, 17, 16, 18, 1, -12}, + /* 'A' 0x41 */ {337, 12, 13, 12, 0, -12}, + /* 'B' 0x42 */ {357, 11, 13, 12, 1, -12}, + /* 'C' 0x43 */ {375, 11, 13, 13, 1, -12}, + /* 'D' 0x44 */ {393, 11, 13, 13, 1, -12}, + /* 'E' 0x45 */ {411, 9, 13, 11, 1, -12}, + /* 'F' 0x46 */ {426, 8, 13, 11, 1, -12}, + /* 'G' 0x47 */ {439, 12, 13, 14, 1, -12}, + /* 'H' 0x48 */ {459, 11, 13, 13, 1, -12}, + /* 'I' 0x49 */ {477, 2, 13, 5, 2, -12}, + /* 'J' 0x4A */ {481, 7, 13, 10, 1, -12}, + /* 'K' 0x4B */ {493, 10, 13, 12, 1, -12}, + /* 'L' 0x4C */ {510, 8, 13, 10, 1, -12}, + /* 'M' 0x4D */ {523, 13, 13, 15, 1, -12}, + /* 'N' 0x4E */ {545, 11, 13, 13, 1, -12}, + /* 'O' 0x4F */ {563, 13, 13, 14, 1, -12}, + /* 'P' 0x50 */ {585, 10, 13, 12, 1, -12}, + /* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12}, + /* 'R' 0x52 */ {625, 12, 13, 13, 1, -12}, + /* 'S' 0x53 */ {645, 10, 13, 12, 1, -12}, + /* 'T' 0x54 */ {662, 9, 13, 11, 1, -12}, + /* 'U' 0x55 */ {677, 11, 13, 13, 1, -12}, + /* 'V' 0x56 */ {695, 11, 13, 11, 0, -12}, + /* 'W' 0x57 */ {713, 16, 13, 17, 0, -12}, + /* 'X' 0x58 */ {739, 10, 13, 12, 1, -12}, + /* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12}, + /* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12}, + /* '[' 0x5B */ {793, 3, 17, 5, 1, -12}, + /* '\' 0x5C */ {800, 5, 13, 5, 0, -12}, + /* ']' 0x5D */ {809, 3, 17, 5, 0, -12}, + /* '^' 0x5E */ {816, 7, 7, 8, 1, -12}, + /* '_' 0x5F */ {823, 10, 1, 10, 0, 3}, + /* '`' 0x60 */ {825, 4, 3, 5, 0, -12}, + /* 'a' 0x61 */ {827, 9, 10, 10, 1, -9}, + /* 'b' 0x62 */ {839, 9, 13, 10, 1, -12}, + /* 'c' 0x63 */ {854, 8, 10, 9, 1, -9}, + /* 'd' 0x64 */ {864, 8, 13, 10, 1, -12}, + /* 'e' 0x65 */ {877, 8, 10, 10, 1, -9}, + /* 'f' 0x66 */ {887, 4, 13, 5, 1, -12}, + /* 'g' 0x67 */ {894, 8, 14, 10, 1, -9}, + /* 'h' 0x68 */ {908, 8, 13, 10, 1, -12}, + /* 'i' 0x69 */ {921, 2, 13, 4, 1, -12}, + /* 'j' 0x6A */ {925, 4, 17, 4, 0, -12}, + /* 'k' 0x6B */ {934, 8, 13, 9, 1, -12}, + /* 'l' 0x6C */ {947, 2, 13, 4, 1, -12}, + /* 'm' 0x6D */ {951, 13, 10, 15, 1, -9}, + /* 'n' 0x6E */ {968, 8, 10, 10, 1, -9}, + /* 'o' 0x6F */ {978, 8, 10, 10, 1, -9}, + /* 'p' 0x70 */ {988, 9, 13, 10, 1, -9}, + /* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9}, + /* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9}, + /* 's' 0x73 */ {1023, 8, 10, 9, 1, -9}, + /* 't' 0x74 */ {1033, 4, 12, 5, 1, -11}, + /* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9}, + /* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9}, + /* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9}, + /* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9}, + /* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9}, + /* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9}, + /* '{' 0x7B */ {1110, 4, 17, 6, 1, -12}, + /* '|' 0x7C */ {1119, 2, 17, 4, 2, -12}, + /* '}' 0x7D */ {1124, 4, 17, 6, 1, -12}, + /* '~' 0x7E */ {1133, 7, 3, 9, 1, -7}, + /* 0x7F */ {1136, 13, 14, 15, 1, -12}, + /* 0x80 */ {1159, 10, 13, 12, 1, -12}, + /* 0x81 */ {1176, 0, 0, 0, 0, 0}, + /* 0x82 */ {1176, 2, 3, 5, 1, 0}, + /* 0x83 */ {1177, 0, 0, 0, 0, 0}, + /* 0x84 */ {1177, 5, 3, 7, 1, 0}, + /* 0x85 */ {1179, 10, 1, 12, 1, 0}, + /* 0x86 */ {1181, 8, 16, 10, 1, -12}, + /* 0x87 */ {1197, 8, 16, 10, 1, -12}, + /* 0x88 */ {1213, 0, 0, 0, 0, 0}, + /* 0x89 */ {1213, 18, 13, 18, 0, -12}, + /* 0x8A */ {1243, 10, 15, 12, 1, -14}, + /* 0x8B */ {1262, 2, 4, 4, 1, -6}, + /* 0x8C */ {1263, 10, 15, 12, 1, -14}, + /* 0x8D */ {1282, 9, 15, 11, 1, -14}, + /* 0x8E */ {1299, 10, 15, 11, 1, -14}, + /* 0x8F */ {1318, 10, 15, 11, 1, -14}, + /* 0x90 */ {1337, 0, 0, 0, 0, 0}, + /* 0x91 */ {1337, 2, 4, 4, 2, -12}, + /* 0x92 */ {1338, 2, 4, 4, 1, -12}, + /* 0x93 */ {1339, 5, 4, 7, 2, -12}, + /* 0x94 */ {1342, 5, 4, 7, 1, -12}, + /* 0x95 */ {1345, 4, 5, 7, 1, -8}, + /* 0x96 */ {1348, 7, 1, 9, 1, -4}, + /* 0x97 */ {1349, 16, 1, 18, 1, -4}, + /* 0x98 */ {1351, 0, 0, 0, 0, 0}, + /* 0x99 */ {1351, 18, 10, 18, 1, -13}, + /* 0x9A */ {1374, 8, 13, 9, 1, -12}, + /* 0x9B */ {1387, 2, 4, 5, 2, -6}, + /* 0x9C */ {1388, 8, 13, 9, 1, -12}, + /* 0x9D */ {1401, 6, 13, 8, 1, -12}, + /* 0x9E */ {1411, 7, 13, 9, 1, -12}, + /* 0x9F */ {1423, 7, 13, 9, 1, -12}, + /* 0xA0 */ {1435, 0, 0, 5, 0, 0}, + /* 0xA1 */ {1435, 5, 3, 6, 0, -12}, + /* 0xA2 */ {1437, 6, 2, 6, 0, -12}, + /* 0xA3 */ {1439, 9, 13, 11, 1, -12}, + /* 0xA4 */ {1454, 7, 6, 10, 2, -8}, + /* 0xA5 */ {1460, 12, 17, 12, 1, -12}, + /* 0xA6 */ {1486, 2, 17, 5, 2, -12}, + /* 0xA7 */ {1491, 9, 17, 10, 1, -12}, + /* 0xA8 */ {1511, 6, 1, 6, 0, -11}, + /* 0xA9 */ {1512, 14, 13, 14, 1, -12}, + /* 0xAA */ {1535, 10, 17, 12, 1, -12}, + /* 0xAB */ {1557, 7, 6, 9, 1, -7}, + /* 0xAC */ {1563, 9, 5, 11, 2, -5}, + /* 0xAD */ {1569, 0, 0, 0, 0, 0}, + /* 0xAE */ {1569, 14, 13, 14, 1, -12}, + /* 0xAF */ {1592, 10, 15, 11, 1, -14}, + /* 0xB0 */ {1611, 5, 5, 11, 3, -11}, + /* 0xB1 */ {1615, 9, 11, 11, 1, -10}, + /* 0xB2 */ {1628, 4, 4, 6, 1, 1}, + /* 0xB3 */ {1630, 4, 13, 5, 1, -12}, + /* 0xB4 */ {1637, 4, 3, 6, 2, -12}, + /* 0xB5 */ {1639, 9, 13, 10, 1, -9}, + /* 0xB6 */ {1654, 8, 16, 10, 2, -12}, + /* 0xB7 */ {1670, 3, 1, 5, 1, -4}, + /* 0xB8 */ {1671, 5, 4, 6, 1, 1}, + /* 0xB9 */ {1674, 10, 14, 10, 1, -9}, + /* 0xBA */ {1692, 8, 14, 9, 1, -9}, + /* 0xBB */ {1706, 7, 6, 9, 1, -7}, + /* 0xBC */ {1712, 8, 13, 10, 1, -12}, + /* 0xBD */ {1725, 6, 3, 6, 0, -12}, + /* 0xBE */ {1728, 5, 13, 7, 1, -12}, + /* 0xBF */ {1737, 7, 12, 9, 1, -11}, + /* 0xC0 */ {1748, 12, 15, 13, 1, -14}, + /* 0xC1 */ {1771, 10, 14, 12, 1, -13}, + /* 0xC2 */ {1789, 10, 14, 12, 1, -13}, + /* 0xC3 */ {1807, 10, 14, 12, 1, -13}, + /* 0xC4 */ {1825, 10, 14, 12, 1, -13}, + /* 0xC5 */ {1843, 8, 14, 10, 1, -13}, + /* 0xC6 */ {1857, 11, 15, 13, 1, -14}, + /* 0xC7 */ {1878, 11, 17, 13, 1, -12}, + /* 0xC8 */ {1902, 11, 15, 13, 1, -14}, + /* 0xC9 */ {1923, 9, 14, 11, 1, -13}, + /* 0xCA */ {1939, 11, 17, 12, 1, -12}, + /* 0xCB */ {1963, 9, 14, 11, 1, -13}, + /* 0xCC */ {1979, 9, 15, 11, 1, -14}, + /* 0xCD */ {1996, 3, 14, 5, 1, -13}, + /* 0xCE */ {2002, 5, 14, 5, 0, -13}, + /* 0xCF */ {2011, 10, 15, 13, 2, -14}, + /* 0xD0 */ {2030, 11, 13, 13, 1, -12}, + /* 0xD1 */ {2048, 11, 14, 13, 1, -13}, + /* 0xD2 */ {2068, 11, 14, 13, 1, -13}, + /* 0xD3 */ {2088, 12, 15, 13, 1, -14}, + /* 0xD4 */ {2111, 12, 15, 13, 1, -14}, + /* 0xD5 */ {2134, 12, 15, 13, 1, -14}, + /* 0xD6 */ {2157, 12, 15, 13, 1, -14}, + /* 0xD7 */ {2180, 7, 7, 11, 2, -7}, + /* 0xD8 */ {2187, 12, 15, 13, 1, -14}, + /* 0xD9 */ {2210, 11, 14, 13, 1, -13}, + /* 0xDA */ {2230, 11, 14, 13, 1, -13}, + /* 0xDB */ {2250, 11, 14, 13, 1, -13}, + /* 0xDC */ {2270, 11, 14, 13, 1, -13}, + /* 0xDD */ {2290, 12, 14, 12, 0, -13}, + /* 0xDE */ {2311, 9, 17, 11, 1, -12}, + /* 0xDF */ {2331, 9, 13, 11, 1, -12}, + /* 0xE0 */ {2346, 5, 13, 6, 1, -12}, + /* 0xE1 */ {2355, 9, 13, 10, 1, -12}, + /* 0xE2 */ {2370, 9, 13, 10, 1, -12}, + /* 0xE3 */ {2385, 9, 13, 10, 1, -12}, + /* 0xE4 */ {2400, 9, 12, 10, 1, -11}, + /* 0xE5 */ {2414, 3, 15, 4, 0, -14}, + /* 0xE6 */ {2420, 8, 13, 9, 1, -12}, + /* 0xE7 */ {2433, 8, 14, 9, 1, -9}, + /* 0xE8 */ {2447, 8, 13, 9, 1, -12}, + /* 0xE9 */ {2460, 8, 13, 10, 1, -12}, + /* 0xEA */ {2473, 8, 14, 10, 1, -9}, + /* 0xEB */ {2487, 8, 12, 10, 1, -11}, + /* 0xEC */ {2499, 8, 13, 10, 1, -12}, + /* 0xED */ {2512, 3, 13, 4, 1, -12}, + /* 0xEE */ {2517, 4, 13, 5, 0, -12}, + /* 0xEF */ {2524, 12, 13, 12, 1, -12}, + /* 0xF0 */ {2544, 9, 13, 10, 1, -12}, + /* 0xF1 */ {2559, 8, 13, 10, 1, -12}, + /* 0xF2 */ {2572, 8, 13, 10, 1, -12}, + /* 0xF3 */ {2585, 8, 13, 10, 1, -12}, + /* 0xF4 */ {2598, 8, 13, 10, 1, -12}, + /* 0xF5 */ {2611, 8, 13, 10, 1, -12}, + /* 0xF6 */ {2624, 8, 12, 10, 1, -11}, + /* 0xF7 */ {2636, 9, 8, 11, 1, -7}, + /* 0xF8 */ {2645, 5, 13, 6, 1, -12}, + /* 0xF9 */ {2654, 8, 13, 10, 1, -12}, + /* 0xFA */ {2667, 8, 13, 10, 1, -12}, + /* 0xFB */ {2680, 8, 13, 10, 1, -12}, + /* 0xFC */ {2693, 8, 12, 10, 1, -11}, + /* 0xFD */ {2705, 8, 17, 9, 0, -12}, + /* 0xFE */ {2722, 5, 16, 5, 1, -11}, + /* 0xFF */ {2732, 2, 1, 6, 2, -11}, +}; + +const GFXfont FreeSans9pt_Win1250 PROGMEM = {(uint8_t *)FreeSans9pt_Win1250Bitmaps, (GFXglyph *)FreeSans9pt_Win1250Glyphs, 0x20, + 0xFF, 21}; diff --git a/src/graphics/niche/Fonts/FreeSans9pt_Win1251.h b/src/graphics/niche/Fonts/FreeSans9pt_Win1251.h new file mode 100644 index 000000000..82857cb91 --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans9pt_Win1251.h @@ -0,0 +1,493 @@ +#pragma once +const uint8_t FreeSans9pt_Win1251Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */ + 0xDE, 0xF7, 0x20, /* '"' 0x22 */ + 0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */ + 0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */ + 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04, + 0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */ + 0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */ + 0xFE, /* ''' 0x27 */ + 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */ + 0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */ + 0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */ + 0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */ + 0xD6, /* ',' 0x2C */ + 0xF0, /* '-' 0x2D */ + 0xC0, /* '.' 0x2E */ + 0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */ + 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */ + 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */ + 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */ + 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */ + 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */ + 0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */ + 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */ + 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */ + 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */ + 0xC0, 0x00, 0x30, /* ':' 0x3A */ + 0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */ + 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */ + 0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */ + 0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */ + 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11, + 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */ + 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, + 0x30, /* 'A' 0x41 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */ + 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */ + 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */ + 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */ + 0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F, + 0x10, /* 'G' 0x47 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */ + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */ + 0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */ + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */ + 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, + 0x80, /* 'M' 0x4D */ + 0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, + 0x00, /* 'O' 0x4F */ + 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB, + 0x00, 0x08, /* 'Q' 0x51 */ + 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, + 0x70, /* 'R' 0x52 */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */ + 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */ + 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */ + 0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C, + 0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */ + 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */ + 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, + 0x00, /* 'Y' 0x59 */ + 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */ + 0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */ + 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */ + 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */ + 0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */ + 0xFF, 0xC0, /* '_' 0x5F */ + 0xC6, 0x30, /* '`' 0x60 */ + 0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */ + 0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */ + 0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */ + 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */ + 0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */ + 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */ + 0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */ + 0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */ + 0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */ + 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */ + 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */ + 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */ + 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */ + 0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */ + 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */ + 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */ + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */ + 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */ + 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */ + 0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */ + 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */ + 0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */ + 0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */ + 0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */ + 0x61, 0x24, 0x38, /* '~' 0x7E */ + 0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00, + 0xFF, 0xFC, /* 0x7F */ + 0xFF, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xFE, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x30, 0x03, + 0x00, 0x30, 0x0E, /* 0x80 */ + 0x0C, 0x18, 0x00, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 0x81 */ + 0xDC, /* 0x82 */ + 0x18, 0x89, 0xFC, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0x83 */ + 0xDA, 0x76, /* 0x84 */ + 0xCC, 0xC0, /* 0x85 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */ + 0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x88 */ + 0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84, + 0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */ + 0x3F, 0x80, 0x18, 0xC0, 0x0C, 0x60, 0x06, 0x30, 0x03, 0x18, 0x01, 0x8C, 0x00, 0xC7, 0xF8, 0x63, 0x06, 0x31, 0x81, 0x90, 0xC0, + 0xD8, 0x60, 0x6C, 0x30, 0x6C, 0x1F, 0xE0, /* 0x8A */ + 0x69, /* 0x8B */ + 0xC0, 0xC0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0xFF, 0xF9, 0x81, 0x86, 0xC0, 0xC1, 0xE0, 0x60, + 0xF0, 0x30, 0x78, 0x18, 0x6C, 0x0F, 0xE0, /* 0x8C */ + 0x0C, 0x06, 0x0C, 0x1B, 0x0C, 0xC6, 0x33, 0x0D, 0x83, 0xC0, 0xF0, 0x3E, 0x0D, 0xC3, 0x38, 0xC7, 0x30, 0xEC, 0x1C, /* 0x8D */ + 0xFF, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xFE, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, + 0x30, /* 0x8E */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3F, 0xFE, 0x0C, 0x01, + 0x80, /* 0x8F */ + 0x60, 0x7C, 0x18, 0x0D, 0xE7, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x18, 0x18, 0x08, 0x08, /* 0x90 */ + 0x6B, /* 0x91 */ + 0xD6, /* 0x92 */ + 0x4C, 0xA5, 0xB0, /* 0x93 */ + 0xDA, 0x53, 0x20, /* 0x94 */ + 0x6F, 0xFF, 0x60, /* 0x95 */ + 0xFE, /* 0x96 */ + 0xFF, 0xFF, /* 0x97 */ + /* 0x98 */ + 0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC, + 0x33, 0x30, /* 0x99 */ + 0x7E, 0x03, 0x30, 0x19, 0x80, 0xCC, 0x06, 0x60, 0x33, 0xF9, 0x98, 0x6C, 0xC3, 0x46, 0x1E, 0x3F, 0x80, /* 0x9A */ + 0x96, /* 0x9B */ + 0xC3, 0x03, 0x0C, 0x0C, 0x30, 0x30, 0xC0, 0xC3, 0x03, 0xFF, 0xEC, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x0F, 0xE0, /* 0x9C */ + 0x0C, 0x30, 0x46, 0x3C, 0xDB, 0x34, 0x70, 0xF1, 0xB3, 0x36, 0x3C, 0x20, /* 0x9D */ + 0x60, 0x7C, 0x18, 0x0D, 0xE7, 0x3B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x18, /* 0x9E */ + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0x18, 0x18, /* 0x9F */ + /* 0xA0 */ + 0x21, 0x07, 0x8C, 0x0F, 0x06, 0x61, 0x98, 0xC3, 0x30, 0xD8, 0x1E, 0x07, 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x03, 0x00, /* 0xA1 */ + 0x66, 0x18, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xA2 */ + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 0xA3 */ + 0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */ + 0x00, 0xC0, 0x3F, 0xFF, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00, /* 0xA5 */ + 0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */ + 0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E, + 0x00, /* 0xA7 */ + 0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFE, /* 0xA8 */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18, + 0x0F, 0xC0, /* 0xA9 */ + 0x1F, 0x86, 0x19, 0x81, 0xB0, 0x3C, 0x01, 0x80, 0x3F, 0xC6, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 0xAA */ + 0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */ + 0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */ + /* 0xAD */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18, + 0x0F, 0xC0, /* 0xAE */ + 0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, /* 0xAF */ + 0x74, 0x63, 0x17, 0x00, /* 0xB0 */ + 0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 0xB2 */ + 0xC3, 0xFF, 0xFF, 0xC0, /* 0xB3 */ + 0x0C, 0x3F, 0xF0, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, /* 0xB4 */ + 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */ + 0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */ + 0xE0, /* 0xB7 */ + 0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xB8 */ + 0xC1, 0x81, 0x83, 0x03, 0x86, 0x05, 0x0C, 0xEB, 0x1A, 0x32, 0x34, 0x66, 0x68, 0xC4, 0xD1, 0x8D, 0xB3, 0x0B, 0x3A, 0x1E, 0x04, + 0x1C, 0x08, 0x1B, 0xC0, /* 0xB9 */ + 0x3C, 0x46, 0xC3, 0x80, 0xF8, 0x80, 0x80, 0xC3, 0x46, 0x3C, /* 0xBA */ + 0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */ + 0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 0xBC */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 0xBD */ + 0x3E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0xBE */ + 0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, /* 0xBF */ + 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, + 0x30, /* 0xC0 */ + 0xFF, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xE6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xC1 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xC2 */ + 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 0xC3 */ + 0x1F, 0xF0, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x03, 0x0C, 0x0C, + 0xFF, 0xFF, 0x00, 0x3C, 0x00, 0xF0, 0x03, /* 0xC4 */ + 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 0xC5 */ + 0x61, 0x86, 0x31, 0x8C, 0x19, 0x98, 0x19, 0x98, 0x0D, 0xB0, 0x07, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0D, 0xB0, 0x19, 0x98, 0x31, + 0x8C, 0x61, 0x86, 0xC1, 0x83, /* 0xC6 */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0x00, 0xC0, 0x60, 0xF0, 0x06, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 0xC7 */ + 0xC0, 0xF8, 0x1F, 0x07, 0xE0, 0xBC, 0x37, 0x8C, 0xF1, 0x1E, 0x63, 0xD8, 0x7A, 0x0F, 0xC1, 0xF0, 0x3E, 0x06, /* 0xC8 */ + 0x11, 0x03, 0xE0, 0x00, 0x60, 0x7C, 0x0F, 0x83, 0xF0, 0x5E, 0x1B, 0xC6, 0x78, 0x8F, 0x31, 0xEC, 0x3D, 0x07, 0xE0, 0xF8, 0x1F, + 0x03, /* 0xC9 */ + 0xC1, 0xB0, 0xCC, 0x63, 0x30, 0xD8, 0x3C, 0x0F, 0x03, 0xE0, 0xDC, 0x33, 0x8C, 0x73, 0x0E, 0xC1, 0xC0, /* 0xCA */ + 0x3F, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xC8, 0x36, 0x0D, 0x83, 0xC0, 0xC0, /* 0xCB */ + 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, + 0x80, /* 0xCC */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 0xCD */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, + 0x00, /* 0xCE */ + 0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 0xCF */ + 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 0xD0 */ + 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 0xD1 */ + 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 0xD2 */ + 0xC0, 0xF0, 0x66, 0x19, 0x8C, 0x33, 0x0D, 0x81, 0xE0, 0x70, 0x0C, 0x06, 0x01, 0x80, 0xC0, 0x30, 0x00, /* 0xD3 */ + 0x03, 0x00, 0x0C, 0x01, 0xFE, 0x1C, 0xCE, 0xE3, 0x1F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xE3, 0x1D, 0xCC, 0xE3, 0xFF, 0x00, 0xC0, + 0x03, 0x00, /* 0xD4 */ + 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 0xD5 */ + 0xC0, 0x66, 0x03, 0x30, 0x19, 0x80, 0xCC, 0x06, 0x60, 0x33, 0x01, 0x98, 0x0C, 0xC0, 0x66, 0x03, 0x30, 0x19, 0x80, 0xCF, 0xFF, + 0x80, 0x0C, 0x00, 0x60, /* 0xD6 */ + 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x06, 0xFF, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xD7 */ + 0xC3, 0x1E, 0x18, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xF0, 0xC7, 0x86, 0x3F, 0xFF, + 0x80, /* 0xD8 */ + 0xC3, 0x19, 0x86, 0x33, 0x0C, 0x66, 0x18, 0xCC, 0x31, 0x98, 0x63, 0x30, 0xC6, 0x61, 0x8C, 0xC3, 0x19, 0x86, 0x33, 0x0C, 0x66, + 0x18, 0xCF, 0xFF, 0xE0, 0x00, 0xC0, 0x01, 0x80, /* 0xD9 */ + 0xF8, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0F, 0xF0, 0x60, 0xC3, 0x03, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30, 0x61, 0xFE, + 0x00, /* 0xDA */ + 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0xFE, 0x3C, 0x0C, 0xF0, 0x1B, 0xC0, 0x6F, 0x01, 0xBC, 0x06, 0xF0, 0x33, + 0xFF, 0x8C, /* 0xDB */ + 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0xFF, 0x30, 0x36, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xDC */ + 0x3F, 0x0C, 0x33, 0x83, 0x60, 0x20, 0x06, 0x00, 0x47, 0xF8, 0x01, 0xC0, 0x78, 0x0D, 0x81, 0x30, 0xC1, 0xF0, /* 0xDD */ + 0xC0, 0xF8, 0x61, 0x83, 0x31, 0x80, 0xD8, 0xC0, 0x6C, 0xC0, 0x1E, 0x60, 0x0F, 0xF0, 0x07, 0x98, 0x03, 0xCC, 0x01, 0xE3, 0x01, + 0xB1, 0x80, 0xD8, 0x60, 0xCC, 0x0F, 0x80, /* 0xDE */ + 0x3F, 0xD8, 0x3C, 0x0F, 0x03, 0xC0, 0xD8, 0x33, 0xFC, 0x33, 0x18, 0xCC, 0x36, 0x0D, 0x83, 0xC0, 0xC0, /* 0xDF */ + 0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 0xE0 */ + 0x03, 0x1F, 0x78, 0x40, 0xFC, 0xE6, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xE1 */ + 0xFD, 0x8F, 0x0E, 0x3F, 0xDF, 0xB1, 0xE1, 0xC7, 0xF8, /* 0xE2 */ + 0xFE, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 0xE3 */ + 0x1F, 0x83, 0x30, 0x66, 0x0C, 0xC1, 0x98, 0x33, 0x06, 0x61, 0x8C, 0x31, 0x9F, 0xFF, 0x01, 0xE0, 0x30, /* 0xE4 */ + 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE5 */ + 0xC6, 0x36, 0x66, 0x36, 0xC1, 0xF8, 0x0F, 0x01, 0xF8, 0x36, 0xC6, 0x66, 0xC6, 0x38, 0x61, /* 0xE6 */ + 0x79, 0x8C, 0x18, 0x30, 0x43, 0x01, 0xE3, 0xC6, 0xF8, /* 0xE7 */ + 0xC7, 0xC7, 0xCF, 0xCB, 0xCB, 0xD3, 0xD3, 0xF3, 0xE3, 0xE3, /* 0xE8 */ + 0x66, 0x18, 0xC7, 0xC7, 0xCF, 0xCB, 0xCB, 0xD3, 0xD3, 0xF3, 0xE3, 0xE3, /* 0xE9 */ + 0xC7, 0x9B, 0x66, 0x8E, 0x1E, 0x36, 0x66, 0xC7, 0x84, /* 0xEA */ + 0x7E, 0xCD, 0x9B, 0x36, 0x6C, 0xD9, 0xA3, 0xC7, 0x0C, /* 0xEB */ + 0xE3, 0xF1, 0xF8, 0xFE, 0xFF, 0x7E, 0xAF, 0x77, 0x93, 0xC9, 0xE0, 0xC0, /* 0xEC */ + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xED */ + 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xEE */ + 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xEF */ + 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 0xF0 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xF1 */ + 0xFC, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, /* 0xF2 */ + 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xF3 */ + 0x03, 0x00, 0x0C, 0x03, 0xB7, 0x19, 0xE6, 0xC3, 0x0F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x0C, 0x36, 0x79, 0x8E, 0xDC, + 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, /* 0xF4 */ + 0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 0xF5 */ + 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x3F, 0xF0, 0x0C, 0x03, /* 0xF6 */ + 0xC7, 0x8F, 0x1E, 0x3C, 0x6F, 0xC1, 0x83, 0x06, 0x0C, /* 0xF7 */ + 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xFF, 0xF0, /* 0xF8 */ + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, 0xFF, 0x00, 0x30, 0x03, /* 0xF9 */ + 0xF0, 0x18, 0x0C, 0x06, 0x03, 0xF1, 0x8C, 0xC6, 0x63, 0x31, 0x9F, 0x80, /* 0xFA */ + 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFE, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF, 0xB0, /* 0xFB */ + 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC3, 0xC3, 0xC3, 0xC3, 0xFE, /* 0xFC */ + 0x3C, 0x62, 0xC3, 0x01, 0x1F, 0x01, 0x01, 0xC3, 0x62, 0x3C, /* 0xFD */ + 0xC7, 0xCC, 0xC6, 0xD8, 0x3D, 0x83, 0xF8, 0x3D, 0x83, 0xD8, 0x3C, 0xC2, 0xCC, 0x6C, 0x7C, /* 0xFE */ + 0x7F, 0xC3, 0xC3, 0xC3, 0x7F, 0x13, 0x33, 0x63, 0xC3, 0x83, /* 0xFF */ +}; + +const GFXglyph FreeSans9pt_Win1251Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 5, 0, 0}, + /* '!' 0x21 */ {0, 2, 13, 6, 2, -12}, + /* '"' 0x22 */ {4, 5, 4, 6, 1, -12}, + /* '#' 0x23 */ {7, 10, 12, 10, 0, -11}, + /* '$' 0x24 */ {22, 9, 16, 10, 1, -13}, + /* '%' 0x25 */ {40, 16, 13, 16, 1, -12}, + /* '&' 0x26 */ {66, 10, 13, 12, 1, -12}, + /* ''' 0x27 */ {83, 2, 4, 4, 1, -12}, + /* '(' 0x28 */ {84, 4, 17, 6, 1, -12}, + /* ')' 0x29 */ {93, 4, 17, 6, 1, -12}, + /* '*' 0x2A */ {102, 5, 5, 7, 1, -12}, + /* '+' 0x2B */ {106, 6, 8, 11, 3, -7}, + /* ',' 0x2C */ {112, 2, 4, 5, 2, 0}, + /* '-' 0x2D */ {113, 4, 1, 6, 1, -4}, + /* '.' 0x2E */ {114, 2, 1, 5, 1, 0}, + /* '/' 0x2F */ {115, 5, 13, 5, 0, -12}, + /* '0' 0x30 */ {124, 8, 13, 10, 1, -12}, + /* '1' 0x31 */ {137, 4, 13, 10, 3, -12}, + /* '2' 0x32 */ {144, 9, 13, 10, 1, -12}, + /* '3' 0x33 */ {159, 8, 13, 10, 1, -12}, + /* '4' 0x34 */ {172, 7, 13, 10, 2, -12}, + /* '5' 0x35 */ {184, 9, 13, 10, 1, -12}, + /* '6' 0x36 */ {199, 9, 13, 10, 1, -12}, + /* '7' 0x37 */ {214, 8, 13, 10, 0, -12}, + /* '8' 0x38 */ {227, 9, 13, 10, 1, -12}, + /* '9' 0x39 */ {242, 8, 13, 10, 1, -12}, + /* ':' 0x3A */ {255, 2, 10, 5, 1, -9}, + /* ';' 0x3B */ {258, 3, 12, 5, 1, -8}, + /* '<' 0x3C */ {263, 9, 9, 11, 1, -8}, + /* '=' 0x3D */ {274, 9, 4, 11, 1, -5}, + /* '>' 0x3E */ {279, 9, 8, 11, 1, -7}, + /* '?' 0x3F */ {288, 9, 13, 10, 1, -12}, + /* '@' 0x40 */ {303, 17, 16, 18, 1, -12}, + /* 'A' 0x41 */ {337, 12, 13, 12, 0, -12}, + /* 'B' 0x42 */ {357, 11, 13, 12, 1, -12}, + /* 'C' 0x43 */ {375, 11, 13, 13, 1, -12}, + /* 'D' 0x44 */ {393, 11, 13, 13, 1, -12}, + /* 'E' 0x45 */ {411, 9, 13, 11, 1, -12}, + /* 'F' 0x46 */ {426, 8, 13, 11, 1, -12}, + /* 'G' 0x47 */ {439, 12, 13, 14, 1, -12}, + /* 'H' 0x48 */ {459, 11, 13, 13, 1, -12}, + /* 'I' 0x49 */ {477, 2, 13, 5, 2, -12}, + /* 'J' 0x4A */ {481, 7, 13, 10, 1, -12}, + /* 'K' 0x4B */ {493, 10, 13, 12, 1, -12}, + /* 'L' 0x4C */ {510, 8, 13, 10, 1, -12}, + /* 'M' 0x4D */ {523, 13, 13, 15, 1, -12}, + /* 'N' 0x4E */ {545, 11, 13, 13, 1, -12}, + /* 'O' 0x4F */ {563, 13, 13, 14, 1, -12}, + /* 'P' 0x50 */ {585, 10, 13, 12, 1, -12}, + /* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12}, + /* 'R' 0x52 */ {625, 12, 13, 13, 1, -12}, + /* 'S' 0x53 */ {645, 10, 13, 12, 1, -12}, + /* 'T' 0x54 */ {662, 9, 13, 11, 1, -12}, + /* 'U' 0x55 */ {677, 11, 13, 13, 1, -12}, + /* 'V' 0x56 */ {695, 11, 13, 11, 0, -12}, + /* 'W' 0x57 */ {713, 16, 13, 17, 0, -12}, + /* 'X' 0x58 */ {739, 10, 13, 12, 1, -12}, + /* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12}, + /* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12}, + /* '[' 0x5B */ {793, 3, 17, 5, 1, -12}, + /* '\' 0x5C */ {800, 5, 13, 5, 0, -12}, + /* ']' 0x5D */ {809, 3, 17, 5, 0, -12}, + /* '^' 0x5E */ {816, 7, 7, 8, 1, -12}, + /* '_' 0x5F */ {823, 10, 1, 10, 0, 3}, + /* '`' 0x60 */ {825, 4, 3, 5, 0, -12}, + /* 'a' 0x61 */ {827, 9, 10, 10, 1, -9}, + /* 'b' 0x62 */ {839, 9, 13, 10, 1, -12}, + /* 'c' 0x63 */ {854, 8, 10, 9, 1, -9}, + /* 'd' 0x64 */ {864, 8, 13, 10, 1, -12}, + /* 'e' 0x65 */ {877, 8, 10, 10, 1, -9}, + /* 'f' 0x66 */ {887, 4, 13, 5, 1, -12}, + /* 'g' 0x67 */ {894, 8, 14, 10, 1, -9}, + /* 'h' 0x68 */ {908, 8, 13, 10, 1, -12}, + /* 'i' 0x69 */ {921, 2, 13, 4, 1, -12}, + /* 'j' 0x6A */ {925, 4, 17, 4, 0, -12}, + /* 'k' 0x6B */ {934, 8, 13, 9, 1, -12}, + /* 'l' 0x6C */ {947, 2, 13, 4, 1, -12}, + /* 'm' 0x6D */ {951, 13, 10, 15, 1, -9}, + /* 'n' 0x6E */ {968, 8, 10, 10, 1, -9}, + /* 'o' 0x6F */ {978, 8, 10, 10, 1, -9}, + /* 'p' 0x70 */ {988, 9, 13, 10, 1, -9}, + /* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9}, + /* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9}, + /* 's' 0x73 */ {1023, 8, 10, 9, 1, -9}, + /* 't' 0x74 */ {1033, 4, 12, 5, 1, -11}, + /* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9}, + /* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9}, + /* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9}, + /* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9}, + /* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9}, + /* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9}, + /* '{' 0x7B */ {1110, 4, 17, 6, 1, -12}, + /* '|' 0x7C */ {1119, 2, 17, 4, 2, -12}, + /* '}' 0x7D */ {1124, 4, 17, 6, 1, -12}, + /* '~' 0x7E */ {1133, 7, 3, 9, 1, -7}, + /* 0x7F */ {1136, 13, 14, 15, 1, -12}, + /* 0x80 */ {1159, 12, 16, 14, 1, -12}, + /* 0x81 */ {1183, 8, 15, 11, 1, -14}, + /* 0x82 */ {1198, 2, 3, 5, 1, 0}, + /* 0x83 */ {1199, 5, 13, 7, 1, -12}, + /* 0x84 */ {1208, 5, 3, 7, 1, 0}, + /* 0x85 */ {1210, 10, 1, 12, 1, 0}, + /* 0x86 */ {1212, 8, 16, 10, 1, -12}, + /* 0x87 */ {1228, 8, 16, 10, 1, -12}, + /* 0x88 */ {1244, 10, 13, 12, 1, -12}, + /* 0x89 */ {1261, 18, 13, 18, 0, -12}, + /* 0x8A */ {1291, 17, 13, 18, 1, -12}, + /* 0x8B */ {1319, 2, 4, 4, 1, -6}, + /* 0x8C */ {1320, 17, 13, 18, 1, -12}, + /* 0x8D */ {1348, 10, 15, 11, 1, -14}, + /* 0x8E */ {1367, 12, 13, 14, 1, -12}, + /* 0x8F */ {1387, 11, 15, 13, 1, -12}, + /* 0x90 */ {1408, 9, 16, 10, 1, -12}, + /* 0x91 */ {1426, 2, 4, 4, 2, -12}, + /* 0x92 */ {1427, 2, 4, 4, 1, -12}, + /* 0x93 */ {1428, 5, 4, 7, 2, -12}, + /* 0x94 */ {1431, 5, 4, 7, 1, -12}, + /* 0x95 */ {1434, 4, 5, 7, 1, -8}, + /* 0x96 */ {1437, 7, 1, 9, 1, -4}, + /* 0x97 */ {1438, 16, 1, 18, 1, -4}, + /* 0x98 */ {1440, 0, 0, 0, 0, 0}, + /* 0x99 */ {1440, 18, 10, 18, 1, -13}, + /* 0x9A */ {1463, 13, 10, 14, 1, -9}, + /* 0x9B */ {1480, 2, 4, 5, 2, -6}, + /* 0x9C */ {1481, 14, 10, 15, 1, -9}, + /* 0x9D */ {1499, 7, 13, 9, 1, -12}, + /* 0x9E */ {1511, 9, 13, 10, 1, -12}, + /* 0x9F */ {1526, 8, 12, 10, 1, -9}, + /* 0xA0 */ {1538, 0, 0, 5, 0, 0}, + /* 0xA1 */ {1538, 10, 15, 11, 1, -14}, + /* 0xA2 */ {1557, 8, 16, 9, 0, -11}, + /* 0xA3 */ {1573, 7, 13, 10, 1, -12}, + /* 0xA4 */ {1585, 7, 6, 10, 2, -8}, + /* 0xA5 */ {1591, 10, 14, 11, 1, -13}, + /* 0xA6 */ {1609, 2, 17, 5, 2, -12}, + /* 0xA7 */ {1614, 9, 17, 10, 1, -12}, + /* 0xA8 */ {1634, 9, 15, 12, 1, -14}, + /* 0xA9 */ {1651, 14, 13, 14, 1, -12}, + /* 0xAA */ {1674, 11, 13, 13, 1, -12}, + /* 0xAB */ {1692, 7, 6, 9, 1, -7}, + /* 0xAC */ {1698, 9, 5, 11, 2, -5}, + /* 0xAD */ {1704, 0, 0, 0, 0, 0}, + /* 0xAE */ {1704, 14, 13, 14, 1, -12}, + /* 0xAF */ {1727, 6, 15, 5, 0, -14}, + /* 0xB0 */ {1739, 5, 5, 11, 3, -11}, + /* 0xB1 */ {1743, 9, 11, 11, 1, -10}, + /* 0xB2 */ {1756, 2, 13, 4, 1, -12}, + /* 0xB3 */ {1760, 2, 13, 4, 1, -12}, + /* 0xB4 */ {1764, 6, 12, 7, 1, -11}, + /* 0xB5 */ {1773, 9, 13, 10, 1, -9}, + /* 0xB6 */ {1788, 8, 16, 10, 2, -12}, + /* 0xB7 */ {1804, 3, 1, 5, 1, -4}, + /* 0xB8 */ {1805, 8, 12, 10, 1, -11}, + /* 0xB9 */ {1817, 15, 13, 17, 1, -12}, + /* 0xBA */ {1842, 8, 10, 9, 1, -9}, + /* 0xBB */ {1852, 7, 6, 9, 1, -7}, + /* 0xBC */ {1858, 4, 17, 4, 0, -12}, + /* 0xBD */ {1867, 10, 13, 12, 1, -12}, + /* 0xBE */ {1884, 8, 10, 9, 1, -9}, + /* 0xBF */ {1894, 6, 12, 5, -1, -11}, + /* 0xC0 */ {1903, 12, 13, 12, 0, -12}, + /* 0xC1 */ {1923, 11, 13, 12, 1, -12}, + /* 0xC2 */ {1941, 11, 13, 12, 1, -12}, + /* 0xC3 */ {1959, 8, 13, 8, 1, -12}, + /* 0xC4 */ {1972, 14, 16, 15, 1, -12}, + /* 0xC5 */ {2000, 9, 13, 12, 1, -12}, + /* 0xC6 */ {2015, 16, 13, 16, 0, -12}, + /* 0xC7 */ {2041, 10, 13, 12, 1, -12}, + /* 0xC8 */ {2058, 11, 13, 13, 1, -12}, + /* 0xC9 */ {2076, 11, 16, 13, 1, -15}, + /* 0xCA */ {2098, 10, 13, 11, 1, -12}, + /* 0xCB */ {2115, 10, 13, 12, 1, -12}, + /* 0xCC */ {2132, 13, 13, 15, 1, -12}, + /* 0xCD */ {2154, 11, 13, 13, 1, -12}, + /* 0xCE */ {2172, 13, 13, 14, 1, -12}, + /* 0xCF */ {2194, 11, 13, 13, 1, -12}, + /* 0xD0 */ {2212, 10, 13, 12, 1, -12}, + /* 0xD1 */ {2229, 11, 13, 13, 1, -12}, + /* 0xD2 */ {2247, 9, 13, 11, 1, -12}, + /* 0xD3 */ {2262, 10, 13, 11, 1, -12}, + /* 0xD4 */ {2279, 14, 13, 15, 1, -12}, + /* 0xD5 */ {2302, 10, 13, 12, 1, -12}, + /* 0xD6 */ {2319, 13, 15, 13, 1, -12}, + /* 0xD7 */ {2344, 9, 13, 11, 1, -12}, + /* 0xD8 */ {2359, 13, 13, 15, 1, -12}, + /* 0xD9 */ {2381, 15, 15, 15, 1, -12}, + /* 0xDA */ {2410, 13, 13, 15, 2, -12}, + /* 0xDB */ {2432, 14, 13, 16, 1, -12}, + /* 0xDC */ {2455, 11, 13, 12, 1, -12}, + /* 0xDD */ {2473, 11, 13, 13, 1, -12}, + /* 0xDE */ {2491, 17, 13, 18, 1, -12}, + /* 0xDF */ {2519, 10, 13, 12, 1, -12}, + /* 0xE0 */ {2536, 9, 10, 10, 1, -9}, + /* 0xE1 */ {2548, 8, 14, 10, 1, -13}, + /* 0xE2 */ {2562, 7, 10, 9, 1, -9}, + /* 0xE3 */ {2571, 5, 10, 7, 1, -9}, + /* 0xE4 */ {2578, 11, 12, 10, 0, -9}, + /* 0xE5 */ {2595, 8, 10, 10, 1, -9}, + /* 0xE6 */ {2605, 12, 10, 14, 1, -9}, + /* 0xE7 */ {2620, 7, 10, 9, 1, -9}, + /* 0xE8 */ {2629, 8, 10, 10, 1, -9}, + /* 0xE9 */ {2639, 8, 12, 10, 1, -11}, + /* 0xEA */ {2651, 7, 10, 9, 1, -9}, + /* 0xEB */ {2660, 7, 10, 8, 0, -9}, + /* 0xEC */ {2669, 9, 10, 11, 1, -9}, + /* 0xED */ {2681, 8, 10, 10, 1, -9}, + /* 0xEE */ {2691, 8, 10, 10, 1, -9}, + /* 0xEF */ {2701, 8, 10, 10, 1, -9}, + /* 0xF0 */ {2711, 9, 13, 10, 1, -9}, + /* 0xF1 */ {2726, 8, 10, 9, 1, -9}, + /* 0xF2 */ {2736, 6, 10, 7, 1, -9}, + /* 0xF3 */ {2744, 8, 14, 9, 0, -9}, + /* 0xF4 */ {2758, 14, 15, 15, 1, -11}, + /* 0xF5 */ {2785, 7, 10, 9, 1, -9}, + /* 0xF6 */ {2794, 10, 12, 10, 1, -9}, + /* 0xF7 */ {2809, 7, 10, 9, 1, -9}, + /* 0xF8 */ {2818, 10, 10, 12, 1, -9}, + /* 0xF9 */ {2831, 12, 12, 13, 1, -9}, + /* 0xFA */ {2849, 9, 10, 12, 2, -9}, + /* 0xFB */ {2861, 10, 10, 12, 1, -9}, + /* 0xFC */ {2874, 8, 10, 9, 1, -9}, + /* 0xFD */ {2884, 8, 10, 9, 1, -9}, + /* 0xFE */ {2894, 12, 10, 13, 1, -9}, + /* 0xFF */ {2909, 8, 10, 10, 1, -9}, +}; + +const GFXfont FreeSans9pt_Win1251 PROGMEM = {(uint8_t *)FreeSans9pt_Win1251Bitmaps, (GFXglyph *)FreeSans9pt_Win1251Glyphs, 0x20, + 0xFF, 21}; diff --git a/src/graphics/niche/Fonts/FreeSans9pt_Win1252.h b/src/graphics/niche/Fonts/FreeSans9pt_Win1252.h new file mode 100644 index 000000000..20f2ddc2f --- /dev/null +++ b/src/graphics/niche/Fonts/FreeSans9pt_Win1252.h @@ -0,0 +1,494 @@ +#pragma once +const uint8_t FreeSans9pt_Win1252Bitmaps[] PROGMEM = { + /* ' ' 0x20 */ + 0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */ + 0xDE, 0xF7, 0x20, /* '"' 0x22 */ + 0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */ + 0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */ + 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04, + 0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */ + 0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */ + 0xFE, /* ''' 0x27 */ + 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */ + 0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */ + 0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */ + 0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */ + 0xD6, /* ',' 0x2C */ + 0xF0, /* '-' 0x2D */ + 0xC0, /* '.' 0x2E */ + 0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */ + 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */ + 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */ + 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */ + 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */ + 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */ + 0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */ + 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */ + 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */ + 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */ + 0xC0, 0x00, 0x30, /* ':' 0x3A */ + 0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */ + 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */ + 0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */ + 0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */ + 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */ + 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11, + 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */ + 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, + 0x30, /* 'A' 0x41 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */ + 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */ + 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */ + 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */ + 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */ + 0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F, + 0x10, /* 'G' 0x47 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */ + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */ + 0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */ + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */ + 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, + 0x80, /* 'M' 0x4D */ + 0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, + 0x00, /* 'O' 0x4F */ + 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */ + 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB, + 0x00, 0x08, /* 'Q' 0x51 */ + 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, + 0x70, /* 'R' 0x52 */ + 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */ + 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */ + 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */ + 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */ + 0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C, + 0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */ + 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */ + 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, + 0x00, /* 'Y' 0x59 */ + 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */ + 0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */ + 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */ + 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */ + 0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */ + 0xFF, 0xC0, /* '_' 0x5F */ + 0xC6, 0x30, /* '`' 0x60 */ + 0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */ + 0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */ + 0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */ + 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */ + 0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */ + 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */ + 0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */ + 0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */ + 0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */ + 0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */ + 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */ + 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */ + 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */ + 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */ + 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */ + 0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */ + 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */ + 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */ + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */ + 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */ + 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */ + 0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */ + 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */ + 0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */ + 0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */ + 0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */ + 0x61, 0x24, 0x38, /* '~' 0x7E */ + 0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00, + 0xFF, 0xFC, /* 0x7F */ + 0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x80 */ + /* 0x81 */ + 0xDC, /* 0x82 */ + 0x19, 0x8C, 0xF3, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0xE0, /* 0x83 */ + 0xDA, 0x76, /* 0x84 */ + 0xCC, 0xC0, /* 0x85 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */ + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */ + 0x72, 0xA2, /* 0x88 */ + 0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84, + 0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */ + 0x1B, 0x03, 0x80, 0x00, 0xFC, 0x61, 0xB0, 0x3C, 0x0F, 0x00, 0x78, 0x07, 0xC0, 0x38, 0x03, 0xC0, 0xF0, 0x36, 0x18, + 0xFC, /* 0x8A */ + 0x69, /* 0x8B */ + 0x1E, 0xFE, 0x43, 0x81, 0x83, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x3F, 0xE0, 0x60, 0xC0, 0xC1, 0x81, 0x81, 0x83, 0x01, + 0x8E, 0x01, 0xEF, 0xE0, /* 0x8C */ + /* 0x8D */ + 0x1B, 0x03, 0x80, 0x03, 0xFF, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C, 0x07, 0x01, 0x80, 0xC0, 0x60, 0x18, 0x0C, 0x03, + 0xFF, /* 0x8E */ + /* 0x8F */ + /* 0x90 */ + 0x6B, /* 0x91 */ + 0xD6, /* 0x92 */ + 0x4C, 0xA5, 0xB0, /* 0x93 */ + 0xDA, 0x53, 0x20, /* 0x94 */ + 0x6F, 0xFF, 0x60, /* 0x95 */ + 0xFE, /* 0x96 */ + 0xFF, 0xFF, /* 0x97 */ + 0x4D, 0xC0, /* 0x98 */ + 0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC, + 0x33, 0x30, /* 0x99 */ + 0x24, 0x3C, 0x18, 0x7E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9A */ + 0x96, /* 0x9B */ + 0x3C, 0xF8, 0xCF, 0x1B, 0x0C, 0x1E, 0x18, 0x3C, 0x3F, 0xF8, 0x60, 0x30, 0xC0, 0x61, 0x83, 0x67, 0x8C, 0x79, 0xF0, /* 0x9C */ + /* 0x9D */ + 0x48, 0xF0, 0xC7, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9E */ + 0x19, 0x80, 0x00, 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, + 0x60, /* 0x9F */ + /* 0xA0 */ + 0xCF, 0xFF, 0xFF, 0xC0, /* 0xA1 */ + 0x08, 0x04, 0x0F, 0x8D, 0x6C, 0x9E, 0x43, 0x21, 0x90, 0xC8, 0x64, 0xDA, 0xC7, 0xC0, 0x80, 0x40, /* 0xA2 */ + 0x1F, 0x0C, 0x66, 0x0D, 0x83, 0x60, 0x0C, 0x0F, 0xC0, 0x60, 0x18, 0x06, 0x03, 0x01, 0xF1, 0x43, 0xC0, /* 0xA3 */ + 0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */ + 0xC3, 0x42, 0x42, 0x24, 0x24, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, /* 0xA5 */ + 0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */ + 0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E, + 0x00, /* 0xA7 */ + 0xCC, /* 0xA8 */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18, + 0x0F, 0xC0, /* 0xA9 */ + 0x74, 0x8D, 0xA9, 0x7C, 0x1F, /* 0xAA */ + 0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */ + 0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */ + /* 0xAD */ + 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18, + 0x0F, 0xC0, /* 0xAE */ + 0xF8, /* 0xAF */ + 0x74, 0x63, 0x17, 0x00, /* 0xB0 */ + 0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */ + 0x7B, 0x30, 0xC3, 0x11, 0x84, 0x3F, /* 0xB2 */ + 0x7D, 0x8C, 0x18, 0xC0, 0x60, 0xF1, 0xBE, /* 0xB3 */ + 0x36, 0xC0, /* 0xB4 */ + 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */ + 0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */ + 0xE0, /* 0xB7 */ + 0x21, 0xC7, 0xE0, /* 0xB8 */ + 0x3D, 0xB6, 0xD8, /* 0xB9 */ + 0x74, 0x63, 0x18, 0xB8, 0x1F, /* 0xBA */ + 0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */ + 0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x84, 0x06, 0x21, 0x80, 0x86, 0x04, 0x78, 0x32, 0x60, 0x87, 0xC4, 0x06, + 0x10, 0x18, /* 0xBC */ + 0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x8D, 0xE6, 0x2C, 0xC1, 0x03, 0x0C, 0x0C, 0x20, 0x41, 0x86, 0x0C, 0x30, + 0x20, 0xFC, /* 0xBD */ + 0x78, 0x11, 0x98, 0x40, 0x31, 0x00, 0x82, 0x00, 0xC8, 0x01, 0x90, 0x33, 0x43, 0x3D, 0x06, 0x02, 0x3C, 0x08, 0x98, 0x10, 0xF8, + 0x40, 0x61, 0x00, 0xC0, /* 0xBE */ + 0x0C, 0x00, 0x00, 0x01, 0x80, 0xC0, 0xC0, 0xE0, 0xC0, 0xC0, 0x60, 0xF0, 0x6C, 0x63, 0xE0, /* 0xBF */ + 0x18, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC0 */ + 0x06, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC1 */ + 0x0C, 0x04, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC2 */ + 0x19, 0x09, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC3 */ + 0x33, 0x00, 0x00, 0xC0, 0x78, 0x1E, 0x04, 0x83, 0x30, 0xCC, 0x33, 0x1F, 0xE6, 0x19, 0x02, 0xC0, 0xF0, 0x30, /* 0xC4 */ + 0x0C, 0x04, 0x81, 0x20, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC5 */ + 0x07, 0xFF, 0x04, 0xC0, 0x0C, 0xC0, 0x08, 0xC0, 0x18, 0xC0, 0x18, 0xC0, 0x30, 0xFF, 0x30, 0xC0, 0x3F, 0xC0, 0x60, 0xC0, 0x60, + 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xC6 */ + 0x1F, 0x06, 0x19, 0x83, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0xE1, 0xF0, 0x08, 0x01, 0xC0, + 0x18, 0x0E, 0x00, /* 0xC7 */ + 0x18, 0x06, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC8 */ + 0x0C, 0x0C, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC9 */ + 0x1C, 0x1B, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCA */ + 0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCB */ + 0xCC, 0x36, 0xDB, 0x6D, 0xB6, 0xD8, /* 0xCC */ + 0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xC0, /* 0xCD */ + 0x76, 0xC0, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, /* 0xCE */ + 0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, /* 0xCF */ + 0x7F, 0x0C, 0x31, 0x83, 0x30, 0x36, 0x06, 0xC0, 0xFE, 0x1B, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x30, 0xE7, 0xF0, /* 0xD0 */ + 0x19, 0x02, 0xC3, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81, + 0xC0, /* 0xD1 */ + 0x0C, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD2 */ + 0x03, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD3 */ + 0x0F, 0x01, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD4 */ + 0x1C, 0x81, 0x38, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD5 */ + 0x19, 0x81, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C, + 0x0F, 0x00, /* 0xD6 */ + 0x83, 0x89, 0xA1, 0x83, 0x89, 0xA1, 0x80, /* 0xD7 */ + 0x0F, 0xD9, 0x83, 0x18, 0x1C, 0xC1, 0xEC, 0x19, 0xE0, 0x8F, 0x08, 0x78, 0x83, 0xC8, 0x1B, 0x81, 0x98, 0x0C, 0xE0, 0xC8, 0xF8, + 0x00, /* 0xD8 */ + 0x0C, 0x00, 0xC3, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xD9 */ + 0x06, 0x01, 0x83, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDA */ + 0x0E, 0x03, 0x63, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDB */ + 0x1B, 0x00, 0x03, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E, + 0x00, /* 0xDC */ + 0x03, 0x0C, 0x63, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x1D, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, + 0x60, /* 0xDD */ + 0xC0, 0x30, 0x0F, 0xF3, 0x06, 0xC0, 0xF0, 0x3C, 0x0F, 0x06, 0xFF, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 0xDE */ + 0x3C, 0x33, 0x30, 0xD8, 0x6C, 0x36, 0x33, 0x39, 0x86, 0xC1, 0xE0, 0xF0, 0x78, 0x6D, 0xE0, /* 0xDF */ + 0x60, 0x18, 0x06, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE0 */ + 0x0C, 0x04, 0x04, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE1 */ + 0x10, 0x14, 0x1B, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE2 */ + 0x24, 0x2E, 0x00, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE3 */ + 0x66, 0x00, 0x1F, 0x9C, 0x6C, 0x30, 0x18, 0x3C, 0xF6, 0xC3, 0x61, 0xB1, 0xCF, 0x70, /* 0xE4 */ + 0x1C, 0x1B, 0x0D, 0x83, 0x87, 0xE7, 0x1B, 0x0C, 0x06, 0x0F, 0x3D, 0xB0, 0xD8, 0x6C, 0x73, 0xDC, /* 0xE5 */ + 0x7E, 0xF9, 0xC7, 0x1B, 0x0C, 0x18, 0x18, 0x33, 0xFF, 0xFC, 0x60, 0x30, 0xC0, 0x61, 0x83, 0xC7, 0x8C, 0xF1, 0xF0, /* 0xE6 */ + 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x10, 0x1C, 0x0C, 0x38, /* 0xE7 */ + 0x60, 0x30, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE8 */ + 0x0C, 0x08, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE9 */ + 0x10, 0x28, 0x6C, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEA */ + 0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEB */ + 0xCC, 0xB6, 0xDB, 0x6D, 0xB6, /* 0xEC */ + 0x7A, 0x6D, 0xB6, 0xDB, 0x6C, /* 0xED */ + 0x6E, 0x96, 0x66, 0x66, 0x66, 0x66, 0x60, /* 0xEE */ + 0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, /* 0xEF */ + 0x34, 0x0C, 0x16, 0x03, 0x3F, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF0 */ + 0x24, 0x5C, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF1 */ + 0x30, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF2 */ + 0x0C, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF3 */ + 0x18, 0x24, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF4 */ + 0x34, 0x2C, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF5 */ + 0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF6 */ + 0x18, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x30, /* 0xF7 */ + 0x3D, 0x66, 0xC7, 0xCB, 0xCB, 0xD3, 0xD3, 0xE3, 0x66, 0xBC, /* 0xF8 */ + 0x60, 0x30, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xF9 */ + 0x06, 0x0C, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFA */ + 0x3C, 0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFB */ + 0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFC */ + 0x06, 0x04, 0x08, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFD */ + 0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE6, 0x03, 0x01, 0x80, /* 0xFE */ + 0x33, 0x00, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFF */ +}; + +const GFXglyph FreeSans9pt_Win1252Glyphs[] PROGMEM = { + /* ' ' 0x20 */ {0, 0, 0, 5, 0, 0}, + /* '!' 0x21 */ {0, 2, 13, 6, 2, -12}, + /* '"' 0x22 */ {4, 5, 4, 6, 1, -12}, + /* '#' 0x23 */ {7, 10, 12, 10, 0, -11}, + /* '$' 0x24 */ {22, 9, 16, 10, 1, -13}, + /* '%' 0x25 */ {40, 16, 13, 16, 1, -12}, + /* '&' 0x26 */ {66, 10, 13, 12, 1, -12}, + /* ''' 0x27 */ {83, 2, 4, 4, 1, -12}, + /* '(' 0x28 */ {84, 4, 17, 6, 1, -12}, + /* ')' 0x29 */ {93, 4, 17, 6, 1, -12}, + /* '*' 0x2A */ {102, 5, 5, 7, 1, -12}, + /* '+' 0x2B */ {106, 6, 8, 11, 3, -7}, + /* ',' 0x2C */ {112, 2, 4, 5, 2, 0}, + /* '-' 0x2D */ {113, 4, 1, 6, 1, -4}, + /* '.' 0x2E */ {114, 2, 1, 5, 1, 0}, + /* '/' 0x2F */ {115, 5, 13, 5, 0, -12}, + /* '0' 0x30 */ {124, 8, 13, 10, 1, -12}, + /* '1' 0x31 */ {137, 4, 13, 10, 3, -12}, + /* '2' 0x32 */ {144, 9, 13, 10, 1, -12}, + /* '3' 0x33 */ {159, 8, 13, 10, 1, -12}, + /* '4' 0x34 */ {172, 7, 13, 10, 2, -12}, + /* '5' 0x35 */ {184, 9, 13, 10, 1, -12}, + /* '6' 0x36 */ {199, 9, 13, 10, 1, -12}, + /* '7' 0x37 */ {214, 8, 13, 10, 0, -12}, + /* '8' 0x38 */ {227, 9, 13, 10, 1, -12}, + /* '9' 0x39 */ {242, 8, 13, 10, 1, -12}, + /* ':' 0x3A */ {255, 2, 10, 5, 1, -9}, + /* ';' 0x3B */ {258, 3, 12, 5, 1, -8}, + /* '<' 0x3C */ {263, 9, 9, 11, 1, -8}, + /* '=' 0x3D */ {274, 9, 4, 11, 1, -5}, + /* '>' 0x3E */ {279, 9, 8, 11, 1, -7}, + /* '?' 0x3F */ {288, 9, 13, 10, 1, -12}, + /* '@' 0x40 */ {303, 17, 16, 18, 1, -12}, + /* 'A' 0x41 */ {337, 12, 13, 12, 0, -12}, + /* 'B' 0x42 */ {357, 11, 13, 12, 1, -12}, + /* 'C' 0x43 */ {375, 11, 13, 13, 1, -12}, + /* 'D' 0x44 */ {393, 11, 13, 13, 1, -12}, + /* 'E' 0x45 */ {411, 9, 13, 11, 1, -12}, + /* 'F' 0x46 */ {426, 8, 13, 11, 1, -12}, + /* 'G' 0x47 */ {439, 12, 13, 14, 1, -12}, + /* 'H' 0x48 */ {459, 11, 13, 13, 1, -12}, + /* 'I' 0x49 */ {477, 2, 13, 5, 2, -12}, + /* 'J' 0x4A */ {481, 7, 13, 10, 1, -12}, + /* 'K' 0x4B */ {493, 10, 13, 12, 1, -12}, + /* 'L' 0x4C */ {510, 8, 13, 10, 1, -12}, + /* 'M' 0x4D */ {523, 13, 13, 15, 1, -12}, + /* 'N' 0x4E */ {545, 11, 13, 13, 1, -12}, + /* 'O' 0x4F */ {563, 13, 13, 14, 1, -12}, + /* 'P' 0x50 */ {585, 10, 13, 12, 1, -12}, + /* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12}, + /* 'R' 0x52 */ {625, 12, 13, 13, 1, -12}, + /* 'S' 0x53 */ {645, 10, 13, 12, 1, -12}, + /* 'T' 0x54 */ {662, 9, 13, 11, 1, -12}, + /* 'U' 0x55 */ {677, 11, 13, 13, 1, -12}, + /* 'V' 0x56 */ {695, 11, 13, 11, 0, -12}, + /* 'W' 0x57 */ {713, 16, 13, 17, 0, -12}, + /* 'X' 0x58 */ {739, 10, 13, 12, 1, -12}, + /* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12}, + /* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12}, + /* '[' 0x5B */ {793, 3, 17, 5, 1, -12}, + /* '\' 0x5C */ {800, 5, 13, 5, 0, -12}, + /* ']' 0x5D */ {809, 3, 17, 5, 0, -12}, + /* '^' 0x5E */ {816, 7, 7, 8, 1, -12}, + /* '_' 0x5F */ {823, 10, 1, 10, 0, 3}, + /* '`' 0x60 */ {825, 4, 3, 5, 0, -12}, + /* 'a' 0x61 */ {827, 9, 10, 10, 1, -9}, + /* 'b' 0x62 */ {839, 9, 13, 10, 1, -12}, + /* 'c' 0x63 */ {854, 8, 10, 9, 1, -9}, + /* 'd' 0x64 */ {864, 8, 13, 10, 1, -12}, + /* 'e' 0x65 */ {877, 8, 10, 10, 1, -9}, + /* 'f' 0x66 */ {887, 4, 13, 5, 1, -12}, + /* 'g' 0x67 */ {894, 8, 14, 10, 1, -9}, + /* 'h' 0x68 */ {908, 8, 13, 10, 1, -12}, + /* 'i' 0x69 */ {921, 2, 13, 4, 1, -12}, + /* 'j' 0x6A */ {925, 4, 17, 4, 0, -12}, + /* 'k' 0x6B */ {934, 8, 13, 9, 1, -12}, + /* 'l' 0x6C */ {947, 2, 13, 4, 1, -12}, + /* 'm' 0x6D */ {951, 13, 10, 15, 1, -9}, + /* 'n' 0x6E */ {968, 8, 10, 10, 1, -9}, + /* 'o' 0x6F */ {978, 8, 10, 10, 1, -9}, + /* 'p' 0x70 */ {988, 9, 13, 10, 1, -9}, + /* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9}, + /* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9}, + /* 's' 0x73 */ {1023, 8, 10, 9, 1, -9}, + /* 't' 0x74 */ {1033, 4, 12, 5, 1, -11}, + /* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9}, + /* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9}, + /* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9}, + /* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9}, + /* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9}, + /* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9}, + /* '{' 0x7B */ {1110, 4, 17, 6, 1, -12}, + /* '|' 0x7C */ {1119, 2, 17, 4, 2, -12}, + /* '}' 0x7D */ {1124, 4, 17, 6, 1, -12}, + /* '~' 0x7E */ {1133, 7, 3, 9, 1, -7}, + /* 0x7F */ {1136, 13, 14, 15, 1, -12}, + /* 0x80 */ {1159, 10, 13, 12, 1, -12}, + /* 0x81 */ {1176, 0, 0, 8, 0, 0}, + /* 0x82 */ {1176, 2, 3, 5, 1, 0}, + /* 0x83 */ {1177, 5, 17, 5, 0, -12}, + /* 0x84 */ {1188, 5, 3, 7, 1, 0}, + /* 0x85 */ {1190, 10, 1, 12, 1, 0}, + /* 0x86 */ {1192, 8, 16, 10, 1, -12}, + /* 0x87 */ {1208, 8, 16, 10, 1, -12}, + /* 0x88 */ {1224, 5, 3, 6, 0, -12}, + /* 0x89 */ {1226, 18, 13, 18, 0, -12}, + /* 0x8A */ {1256, 10, 16, 12, 1, -15}, + /* 0x8B */ {1276, 2, 4, 4, 1, -6}, + /* 0x8C */ {1277, 15, 13, 18, 1, -12}, + /* 0x8D */ {1302, 0, 0, 8, 0, 0}, + /* 0x8E */ {1302, 10, 16, 11, 1, -15}, + /* 0x8F */ {1322, 0, 0, 8, 0, 0}, + /* 0x90 */ {1322, 0, 0, 8, 0, 0}, + /* 0x91 */ {1322, 2, 4, 4, 2, -12}, + /* 0x92 */ {1323, 2, 4, 4, 1, -12}, + /* 0x93 */ {1324, 5, 4, 7, 2, -12}, + /* 0x94 */ {1327, 5, 4, 7, 1, -12}, + /* 0x95 */ {1330, 4, 5, 7, 1, -8}, + /* 0x96 */ {1333, 7, 1, 9, 1, -4}, + /* 0x97 */ {1334, 16, 1, 18, 1, -4}, + /* 0x98 */ {1336, 5, 2, 6, 0, -12}, + /* 0x99 */ {1338, 18, 10, 18, 1, -13}, + /* 0x9A */ {1361, 8, 13, 9, 1, -12}, + /* 0x9B */ {1374, 2, 4, 5, 2, -6}, + /* 0x9C */ {1375, 15, 10, 17, 1, -9}, + /* 0x9D */ {1394, 0, 0, 8, 0, 0}, + /* 0x9E */ {1394, 7, 13, 9, 1, -12}, + /* 0x9F */ {1406, 12, 14, 12, 0, -13}, + /* 0xA0 */ {1427, 0, 0, 5, 0, 0}, + /* 0xA1 */ {1427, 2, 13, 6, 2, -8}, + /* 0xA2 */ {1431, 9, 14, 10, 1, -11}, + /* 0xA3 */ {1447, 10, 13, 10, 0, -12}, + /* 0xA4 */ {1464, 7, 6, 10, 2, -8}, + /* 0xA5 */ {1470, 8, 13, 10, 1, -12}, + /* 0xA6 */ {1483, 2, 17, 5, 2, -12}, + /* 0xA7 */ {1488, 9, 17, 10, 1, -12}, + /* 0xA8 */ {1508, 6, 1, 6, 0, -11}, + /* 0xA9 */ {1509, 14, 13, 14, 1, -12}, + /* 0xAA */ {1532, 5, 8, 7, 1, -12}, + /* 0xAB */ {1537, 7, 6, 9, 1, -7}, + /* 0xAC */ {1543, 9, 5, 11, 2, -5}, + /* 0xAD */ {1549, 0, 0, 0, 0, 0}, + /* 0xAE */ {1549, 14, 13, 14, 1, -12}, + /* 0xAF */ {1572, 5, 1, 6, 0, -12}, + /* 0xB0 */ {1573, 5, 5, 11, 3, -11}, + /* 0xB1 */ {1577, 9, 11, 11, 1, -10}, + /* 0xB2 */ {1590, 6, 8, 6, 1, -13}, + /* 0xB3 */ {1596, 7, 8, 6, 0, -13}, + /* 0xB4 */ {1603, 4, 3, 6, 2, -12}, + /* 0xB5 */ {1605, 9, 13, 10, 1, -9}, + /* 0xB6 */ {1620, 8, 16, 10, 2, -12}, + /* 0xB7 */ {1636, 3, 1, 5, 1, -4}, + /* 0xB8 */ {1637, 5, 4, 6, 1, 1}, + /* 0xB9 */ {1640, 3, 7, 6, 2, -13}, + /* 0xBA */ {1643, 5, 8, 7, 1, -12}, + /* 0xBB */ {1648, 7, 6, 9, 1, -7}, + /* 0xBC */ {1654, 14, 13, 16, 2, -12}, + /* 0xBD */ {1677, 14, 13, 16, 2, -12}, + /* 0xBE */ {1700, 15, 13, 16, 1, -12}, + /* 0xBF */ {1725, 9, 13, 10, 1, -8}, + /* 0xC0 */ {1740, 10, 14, 12, 1, -13}, + /* 0xC1 */ {1758, 10, 14, 12, 1, -13}, + /* 0xC2 */ {1776, 10, 14, 12, 1, -13}, + /* 0xC3 */ {1794, 10, 14, 12, 1, -13}, + /* 0xC4 */ {1812, 10, 14, 12, 1, -13}, + /* 0xC5 */ {1830, 10, 14, 12, 1, -13}, + /* 0xC6 */ {1848, 16, 13, 18, 1, -12}, + /* 0xC7 */ {1874, 11, 17, 13, 1, -12}, + /* 0xC8 */ {1898, 9, 14, 11, 1, -13}, + /* 0xC9 */ {1914, 9, 14, 11, 1, -13}, + /* 0xCA */ {1930, 9, 14, 11, 1, -13}, + /* 0xCB */ {1946, 9, 14, 11, 1, -13}, + /* 0xCC */ {1962, 3, 15, 5, 1, -13}, + /* 0xCD */ {1968, 3, 14, 5, 1, -13}, + /* 0xCE */ {1974, 5, 14, 5, 0, -13}, + /* 0xCF */ {1983, 6, 14, 5, 0, -13}, + /* 0xD0 */ {1994, 11, 13, 13, 1, -12}, + /* 0xD1 */ {2012, 11, 14, 13, 1, -13}, + /* 0xD2 */ {2032, 12, 15, 13, 1, -14}, + /* 0xD3 */ {2055, 12, 15, 13, 1, -14}, + /* 0xD4 */ {2078, 12, 15, 13, 1, -14}, + /* 0xD5 */ {2101, 12, 15, 13, 1, -14}, + /* 0xD6 */ {2124, 12, 15, 13, 1, -14}, + /* 0xD7 */ {2147, 7, 7, 11, 2, -7}, + /* 0xD8 */ {2154, 13, 13, 14, 1, -12}, + /* 0xD9 */ {2176, 11, 14, 13, 1, -13}, + /* 0xDA */ {2196, 11, 14, 13, 1, -13}, + /* 0xDB */ {2216, 11, 14, 13, 1, -13}, + /* 0xDC */ {2236, 11, 14, 13, 1, -13}, + /* 0xDD */ {2256, 12, 14, 12, 0, -13}, + /* 0xDE */ {2277, 10, 13, 12, 1, -12}, + /* 0xDF */ {2294, 9, 13, 11, 1, -12}, + /* 0xE0 */ {2309, 9, 13, 10, 1, -12}, + /* 0xE1 */ {2324, 9, 13, 10, 1, -12}, + /* 0xE2 */ {2339, 9, 13, 10, 1, -12}, + /* 0xE3 */ {2354, 9, 13, 10, 1, -12}, + /* 0xE4 */ {2369, 9, 12, 10, 1, -11}, + /* 0xE5 */ {2383, 9, 14, 10, 1, -13}, + /* 0xE6 */ {2399, 15, 10, 16, 1, -9}, + /* 0xE7 */ {2418, 8, 14, 9, 1, -9}, + /* 0xE8 */ {2432, 8, 13, 10, 1, -12}, + /* 0xE9 */ {2445, 8, 13, 10, 1, -12}, + /* 0xEA */ {2458, 8, 13, 10, 1, -12}, + /* 0xEB */ {2471, 8, 12, 10, 1, -11}, + /* 0xEC */ {2483, 3, 13, 4, 0, -12}, + /* 0xED */ {2488, 3, 13, 4, 1, -12}, + /* 0xEE */ {2493, 4, 13, 5, 0, -12}, + /* 0xEF */ {2500, 6, 12, 5, -1, -11}, + /* 0xF0 */ {2509, 8, 13, 10, 1, -12}, + /* 0xF1 */ {2522, 8, 13, 10, 1, -12}, + /* 0xF2 */ {2535, 8, 13, 10, 1, -12}, + /* 0xF3 */ {2548, 8, 13, 10, 1, -12}, + /* 0xF4 */ {2561, 8, 13, 10, 1, -12}, + /* 0xF5 */ {2574, 8, 13, 10, 1, -12}, + /* 0xF6 */ {2587, 8, 12, 10, 1, -11}, + /* 0xF7 */ {2599, 9, 8, 11, 1, -7}, + /* 0xF8 */ {2608, 8, 10, 10, 1, -9}, + /* 0xF9 */ {2618, 8, 13, 10, 1, -12}, + /* 0xFA */ {2631, 8, 13, 10, 1, -12}, + /* 0xFB */ {2644, 8, 13, 10, 1, -12}, + /* 0xFC */ {2657, 8, 12, 10, 1, -11}, + /* 0xFD */ {2669, 8, 17, 9, 0, -12}, + /* 0xFE */ {2686, 9, 16, 10, 1, -12}, + /* 0xFF */ {2704, 8, 16, 9, 0, -11}, +}; + +const GFXfont FreeSans9pt_Win1252 PROGMEM = {(uint8_t *)FreeSans9pt_Win1252Bitmaps, (GFXglyph *)FreeSans9pt_Win1252Glyphs, 0x20, + 0xFF, 21}; diff --git a/src/graphics/niche/InkHUD/Applet.cpp b/src/graphics/niche/InkHUD/Applet.cpp index 6c6245ec3..f63bd4bbe 100644 --- a/src/graphics/niche/InkHUD/Applet.cpp +++ b/src/graphics/niche/InkHUD/Applet.cpp @@ -263,22 +263,10 @@ uint16_t InkHUD::Applet::Y(float f) // Print text, specifying the position of any edge / corner of the textbox void InkHUD::Applet::printAt(int16_t x, int16_t y, const char *text, HorizontalAlignment ha, VerticalAlignment va) { - printAt(x, y, std::string(text), ha, va); -} - -// Print text, specifying the position of any edge / corner of the textbox -void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalAlignment ha, VerticalAlignment va) -{ - // Custom font - // - set with AppletFont::addSubstitution - // - find certain UTF8 chars - // - replace with glyph from custom font (or suitable ASCII addSubstitution?) - getFont().applySubstitutions(&text); - // We do still have to run getTextBounds to find the width int16_t textOffsetX, textOffsetY; uint16_t textWidth, textHeight; - getTextBounds(text.c_str(), 0, 0, &textOffsetX, &textOffsetY, &textWidth, &textHeight); + getTextBounds(text, 0, 0, &textOffsetX, &textOffsetY, &textWidth, &textHeight); int16_t cursorX = 0; int16_t cursorY = 0; @@ -310,7 +298,13 @@ void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalA } setCursor(cursorX, cursorY); - print(text.c_str()); + print(text); +} + +// Print text, specifying the position of any edge / corner of the textbox +void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalAlignment ha, VerticalAlignment va) +{ + printAt(x, y, text.c_str(), ha, va); } // Set which font should be used for subsequent drawing @@ -328,11 +322,52 @@ InkHUD::AppletFont InkHUD::Applet::getFont() return currentFont; } +// Parse any text which might have "special characters" +// Re-encodes UTF-8 characters to match our 8-bit encoded fonts +std::string InkHUD::Applet::parse(std::string text) +{ + return getFont().decodeUTF8(text); +} + +// Get the best version of a node's short name available to us +// Parses any non-ascii chars +// Swaps for last-four of node-id if the real short name is unknown or can't be rendered (emoji) +std::string InkHUD::Applet::parseShortName(meshtastic_NodeInfoLite *node) +{ + assert(node); + + // Use the true shortname if known, and doesn't contain any unprintable characters (emoji, etc.) + if (node->has_user) { + std::string parsed = parse(node->user.short_name); + if (isPrintable(parsed)) + return parsed; + } + + // Otherwise, use the "last 4" of node id + // - if short name unknown, or + // - if short name is emoji (we can't render this) + std::string nodeID = hexifyNodeNum(node->num); + return nodeID.substr(nodeID.length() - 4); +} + +// Determine if all characters of a string are printable using the current font +bool InkHUD::Applet::isPrintable(std::string text) +{ + // Scan for DEL (0x7F), which is the value assigned by AppletFont::applyEncoding if a unicode character is not handled + // Todo: move this to from DEL to SUB, once the fonts have been changed for this + for (char &c : text) { + if (c == '\x7F') + return false; + } + + // No unprintable characters found + return true; +} + // Gets rendered width of a string // Wrapper for getTextBounds uint16_t InkHUD::Applet::getTextWidth(const char *text) { - // We do still have to run getTextBounds to find the width int16_t textOffsetX, textOffsetY; uint16_t textWidth, textHeight; @@ -345,8 +380,6 @@ uint16_t InkHUD::Applet::getTextWidth(const char *text) // Wrapper for getTextBounds uint16_t InkHUD::Applet::getTextWidth(std::string text) { - getFont().applySubstitutions(&text); - return getTextWidth(text.c_str()); } @@ -395,12 +428,6 @@ std::string InkHUD::Applet::hexifyNodeNum(NodeNum num) // Avoids splitting words in half, instead moving the entire word to a new line wherever possible void InkHUD::Applet::printWrapped(int16_t left, int16_t top, uint16_t width, std::string text) { - // Custom font glyphs - // - set with AppletFont::addSubstitution - // - find certain UTF8 chars - // - replace with glyph from custom font (or suitable ASCII addSubstitution?) - getFont().applySubstitutions(&text); - // Place the AdafruitGFX cursor to suit our "top" coord setCursor(left, top + getFont().heightAboveCursor()); diff --git a/src/graphics/niche/InkHUD/Applet.h b/src/graphics/niche/InkHUD/Applet.h index 8f4466647..c6a8a8aad 100644 --- a/src/graphics/niche/InkHUD/Applet.h +++ b/src/graphics/niche/InkHUD/Applet.h @@ -133,12 +133,15 @@ class Applet : public GFX void drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height, Color color = BLACK); // Draw the Meshtastic logo - std::string hexifyNodeNum(NodeNum num); // Style as !0123abdc - SignalStrength getSignalStrength(float snr, float rssi); // Interpret SNR and RSSI, as an easy to understand value - std::string getTimeString(uint32_t epochSeconds); // Human readable - std::string getTimeString(); // Current time, human readable - uint16_t getActiveNodeCount(); // Duration determined by user, in onscreen menu - std::string localizeDistance(uint32_t meters); // Human readable distance, imperial or metric + std::string hexifyNodeNum(NodeNum num); // Style as !0123abdc + SignalStrength getSignalStrength(float snr, float rssi); // Interpret SNR and RSSI, as an easy to understand value + std::string getTimeString(uint32_t epochSeconds); // Human readable + std::string getTimeString(); // Current time, human readable + uint16_t getActiveNodeCount(); // Duration determined by user, in onscreen menu + std::string localizeDistance(uint32_t meters); // Human readable distance, imperial or metric + std::string parse(std::string text); // Handle text which might contain special chars + std::string parseShortName(meshtastic_NodeInfoLite *node); // Get the shortname, or a substitute if has unprintable chars + bool isPrintable(std::string); // Check for characters which the font can't print // Convenient references diff --git a/src/graphics/niche/InkHUD/AppletFont.cpp b/src/graphics/niche/InkHUD/AppletFont.cpp index 25597c9b9..88fb4054b 100644 --- a/src/graphics/niche/InkHUD/AppletFont.cpp +++ b/src/graphics/niche/InkHUD/AppletFont.cpp @@ -2,14 +2,17 @@ #include "./AppletFont.h" +#include + using namespace NicheGraphics; InkHUD::AppletFont::AppletFont() { - // Default constructor uses the in-built AdafruitGFX font + // Default constructor uses the in-built AdafruitGFX font (not recommended) } -InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafruitGFXFont) +InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont, Encoding encoding, int8_t paddingTop, int8_t paddingBottom) + : gfxFont(&adafruitGFXFont), encoding(encoding) { // AdafruitGFX fonts are drawn relative to a "cursor line"; // they print as if the glyphs are resting on the line of piece of ruled paper. @@ -22,6 +25,10 @@ InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafru // AdafruitGFX fonts do declare a line-height, but this seems to include a certain amount of padding, // which we'd rather not deal with. If we want padding, we'll add it manually. + this->ascenderHeight = 0; + this->descenderHeight = 0; + this->height = 0; + // Scan each glyph in the AdafruitGFX font for (uint16_t i = 0; i <= (gfxFont->last - gfxFont->first); i++) { uint8_t glyphHeight = gfxFont->glyph[i].height; // Height of glyph @@ -33,10 +40,16 @@ InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafru int8_t glyphAscender = 0 - gfxFont->glyph[i].yOffset; if (glyphAscender > 0) this->ascenderHeight = max(this->ascenderHeight, (uint8_t)glyphAscender); + + int8_t glyphDescender = gfxFont->glyph[i].height + gfxFont->glyph[i].yOffset; + if (glyphDescender > 0) + this->descenderHeight = max(this->descenderHeight, (uint8_t)glyphDescender); } - // Determine how far characters may hang "below the line" - descenderHeight = height - ascenderHeight; + // Apply any manual padding to grow or shrink the line size + // Helpful if a font has one or two exceptionally large characters, which would make the lines ridiculously tall + ascenderHeight += paddingTop; + descenderHeight += paddingBottom; // Find how far the cursor advances when we "print" a space character spaceCharWidth = gfxFont->glyph[(uint8_t)' ' - gfxFont->first].xAdvance; @@ -83,139 +96,533 @@ uint8_t InkHUD::AppletFont::widthBetweenWords() return this->spaceCharWidth; } -// Add to the list of substituted glyphs -// This "find and replace" operation will be run before text is printed -// Used to swap out UTF8 special characters, either with a custom font, or with a suitable ASCII approximation -void InkHUD::AppletFont::addSubstitution(const char *from, const char *to) +// Convert a unicode char from set of UTF-8 bytes to UTF-32 +// Used by AppletFont::applyEncoding, which remaps unicode chars for extended ASCII fonts, based on their UTF-32 value +uint32_t InkHUD::AppletFont::toUtf32(std::string utf8) { - substitutions.push_back({.from = from, .to = to}); + uint32_t utf32 = 0; + + switch (utf8.length()) { + case 2: + // 5 bits + 6 bits + utf32 |= (utf8.at(0) & 0b00011111) << 6; + utf32 |= (utf8.at(1) & 0b00111111); + break; + + case 3: + // 4 bits + 6 bits + 6 bits + utf32 |= (utf8.at(0) & 0b00001111) << (6 + 6); + utf32 |= (utf8.at(1) & 0b00111111) << 6; + utf32 |= (utf8.at(2) & 0b00111111); + break; + + case 4: + // 3 bits + 6 bits + 6 bits + 6 bits + utf32 |= (utf8.at(0) & 0b00000111) << (6 + 6 + 6); + utf32 |= (utf8.at(1) & 0b00111111) << (6 + 6); + utf32 |= (utf8.at(2) & 0b00111111) << 6; + utf32 |= (utf8.at(3) & 0b00111111); + break; + default: + assert(false); + } + + return utf32; } -// Run all registered substitutions on a string -// Used to swap out UTF8 special chars -void InkHUD::AppletFont::applySubstitutions(std::string *text) +// Process a string, collating UTF-8 bytes, and sending them off for re-encoding to extended ASCII +// Not all InkHUD text is passed through here, only text which could potentially contain non-ASCII chars +std::string InkHUD::AppletFont::decodeUTF8(std::string encoded) { - // For each substitution - for (Substitution s : substitutions) { + // Final processed output + std::string decoded; - // Find and replace - // - search for Substitution::from - // - replace with Substitution::to - size_t i = text->find(s.from); - while (i != std::string::npos) { - text->replace(i, strlen(s.from), s.to); - i = text->find(s.from, i); // Continue looking from last position + // Holds bytes for one UTF-8 char during parsing + std::string utf8Char; + uint8_t utf8CharSize = 0; + + for (char &c : encoded) { + + // If first byte + if (utf8Char.empty()) { + // If MSB is unset, byte is an ASCII char + // If MSB is set, byte is part of a UTF-8 char. Counting number of higher-order bits tells how many bytes in char + if ((c & 0x80)) { + char c1 = c; + while (c1 & 0x80) { + c1 <<= 1; + utf8CharSize++; + } + } + } + + // Append the byte to the UTF-8 char we're building + utf8Char += c; + + // More bytes left to collect. Iterate. + if (utf8Char.length() < utf8CharSize) + continue; + + // Now collected all bytes for this char + // Remap the value to match the encoding of our 8-bit AppletFont + decoded += applyEncoding(utf8Char); + + // Reset, ready to build next UTF-8 char from the encoded bytes + utf8Char.clear(); + utf8CharSize = 0; + } // For each char + + // All chars processed, return result + return decoded; +} + +// Re-encode a single UTF-8 character to extended ASCII +// Target encoding depends on the font +char InkHUD::AppletFont::applyEncoding(std::string utf8) +{ + // ##################################################### Syntactic Sugar ##################################################### +#define REMAP(in, out) \ + case in: \ + return out; + // ########################################################################################################################### + + // Latin - Central Europe + // https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT + if (encoding == WINDOWS_1250) { + // 1-Byte chars: no remapping + if (utf8.length() == 1) + return utf8.at(0); + + // Multi-byte chars: + switch (toUtf32(utf8)) { + REMAP(0x20AC, 0x80); // EURO SIGN + REMAP(0x201A, 0x82); // SINGLE LOW-9 QUOTATION MARK + REMAP(0x201E, 0x84); // DOUBLE LOW-9 QUOTATION MARK + REMAP(0x2026, 0x85); // HORIZONTAL ELLIPSIS + REMAP(0x2020, 0x86); // DAGGER + REMAP(0x2021, 0x87); // DOUBLE DAGGER + REMAP(0x2030, 0x89); // PER MILLE SIGN + REMAP(0x0160, 0x8A); // LATIN CAPITAL LETTER S WITH CARON + REMAP(0x2039, 0x8B); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + REMAP(0x015A, 0x8C); // LATIN CAPITAL LETTER S WITH ACUTE + REMAP(0x0164, 0x8D); // LATIN CAPITAL LETTER T WITH CARON + REMAP(0x017D, 0x8E); // LATIN CAPITAL LETTER Z WITH CARON + REMAP(0x0179, 0x8F); // LATIN CAPITAL LETTER Z WITH ACUTE + + REMAP(0x2018, 0x91); // LEFT SINGLE QUOTATION MARK + REMAP(0x2019, 0x92); // RIGHT SINGLE QUOTATION MARK + REMAP(0x201C, 0x93); // LEFT DOUBLE QUOTATION MARK + REMAP(0x201D, 0x94); // RIGHT DOUBLE QUOTATION MARK + REMAP(0x2022, 0x95); // BULLET + REMAP(0x2013, 0x96); // EN DASH + REMAP(0x2014, 0x97); // EM DASH + REMAP(0x2122, 0x99); // TRADE MARK SIGN + REMAP(0x0161, 0x9A); // LATIN SMALL LETTER S WITH CARON + REMAP(0x203A, 0x9B); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + REMAP(0x015B, 0x9C); // LATIN SMALL LETTER S WITH ACUTE + REMAP(0x0165, 0x9D); // LATIN SMALL LETTER T WITH CARON + REMAP(0x017E, 0x9E); // LATIN SMALL LETTER Z WITH CARON + REMAP(0x017A, 0x9F); // LATIN SMALL LETTER Z WITH ACUTE + + REMAP(0x00A0, 0xA0); // NO-BREAK SPACE + REMAP(0x02C7, 0xA1); // CARON + REMAP(0x02D8, 0xA2); // BREVE + REMAP(0x0141, 0xA3); // LATIN CAPITAL LETTER L WITH STROKE + REMAP(0x00A4, 0xA4); // CURRENCY SIGN + REMAP(0x0104, 0xA5); // LATIN CAPITAL LETTER A WITH OGONEK + REMAP(0x00A6, 0xA6); // BROKEN BAR + REMAP(0x00A7, 0xA7); // SECTION SIGN + REMAP(0x00A8, 0xA8); // DIAERESIS + REMAP(0x00A9, 0xA9); // COPYRIGHT SIGN + REMAP(0x015E, 0xAA); // LATIN CAPITAL LETTER S WITH CEDILLA + REMAP(0x00AB, 0xAB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x00AC, 0xAC); // NOT SIGN + REMAP(0x00AD, 0xAD); // SOFT HYPHEN + REMAP(0x00AE, 0xAE); // REGISTERED SIGN + REMAP(0x017B, 0xAF); // LATIN CAPITAL LETTER Z WITH DOT ABOVE + + REMAP(0x00B0, 0xB0); // DEGREE SIGN + REMAP(0x00B1, 0xB1); // PLUS-MINUS SIGN + REMAP(0x02DB, 0xB2); // OGONEK + REMAP(0x0142, 0xB3); // LATIN SMALL LETTER L WITH STROKE + REMAP(0x00B4, 0xB4); // ACUTE ACCENT + REMAP(0x00B5, 0xB5); // MICRO SIGN + REMAP(0x00B6, 0xB6); // PILCROW SIGN + REMAP(0x00B7, 0xB7); // MIDDLE DOT + REMAP(0x00B8, 0xB8); // CEDILLA + REMAP(0x0105, 0xB9); // LATIN SMALL LETTER A WITH OGONEK + REMAP(0x015F, 0xBA); // LATIN SMALL LETTER S WITH CEDILLA + REMAP(0x00BB, 0xBB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x013D, 0xBC); // LATIN CAPITAL LETTER L WITH CARON + REMAP(0x02DD, 0xBD); // DOUBLE ACUTE ACCENT + REMAP(0x013E, 0xBE); // LATIN SMALL LETTER L WITH CARON + REMAP(0x017C, 0xBF); // LATIN SMALL LETTER Z WITH DOT ABOVE + + REMAP(0x0154, 0xC0); // LATIN CAPITAL LETTER R WITH ACUTE + REMAP(0x00C1, 0xC1); // LATIN CAPITAL LETTER A WITH ACUTE + REMAP(0x00C2, 0xC2); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX + REMAP(0x0102, 0xC3); // LATIN CAPITAL LETTER A WITH BREVE + REMAP(0x00C4, 0xC4); // LATIN CAPITAL LETTER A WITH DIAERESIS + REMAP(0x0139, 0xC5); // LATIN CAPITAL LETTER L WITH ACUTE + REMAP(0x0106, 0xC6); // LATIN CAPITAL LETTER C WITH ACUTE + REMAP(0x00C7, 0xC7); // LATIN CAPITAL LETTER C WITH CEDILLA + REMAP(0x010C, 0xC8); // LATIN CAPITAL LETTER C WITH CARON + REMAP(0x00C9, 0xC9); // LATIN CAPITAL LETTER E WITH ACUTE + REMAP(0x0118, 0xCA); // LATIN CAPITAL LETTER E WITH OGONEK + REMAP(0x00CB, 0xCB); // LATIN CAPITAL LETTER E WITH DIAERESIS + REMAP(0x011A, 0xCC); // LATIN CAPITAL LETTER E WITH CARON + REMAP(0x00CD, 0xCD); // LATIN CAPITAL LETTER I WITH ACUTE + REMAP(0x00CE, 0xCE); // LATIN CAPITAL LETTER I WITH CIRCUMFLEX + REMAP(0x010E, 0xCF); // LATIN CAPITAL LETTER D WITH CARON + + REMAP(0x0110, 0xD0); // LATIN CAPITAL LETTER D WITH STROKE + REMAP(0x0143, 0xD1); // LATIN CAPITAL LETTER N WITH ACUTE + REMAP(0x0147, 0xD2); // LATIN CAPITAL LETTER N WITH CARON + REMAP(0x00D3, 0xD3); // LATIN CAPITAL LETTER O WITH ACUTE + REMAP(0x00D4, 0xD4); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX + REMAP(0x0150, 0xD5); // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + REMAP(0x00D6, 0xD6); // LATIN CAPITAL LETTER O WITH DIAERESIS + REMAP(0x00D7, 0xD7); // MULTIPLICATION SIGN + REMAP(0x0158, 0xD8); // LATIN CAPITAL LETTER R WITH CARON + REMAP(0x016E, 0xD9); // LATIN CAPITAL LETTER U WITH RING ABOVE + REMAP(0x00DA, 0xDA); // LATIN CAPITAL LETTER U WITH ACUTE + REMAP(0x0170, 0xDB); // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + REMAP(0x00DC, 0xDC); // LATIN CAPITAL LETTER U WITH DIAERESIS + REMAP(0x00DD, 0xDD); // LATIN CAPITAL LETTER Y WITH ACUTE + REMAP(0x0162, 0xDE); // LATIN CAPITAL LETTER T WITH CEDILLA + REMAP(0x00DF, 0xDF); // LATIN SMALL LETTER SHARP S + + REMAP(0x0155, 0xE0); // LATIN SMALL LETTER R WITH ACUTE + REMAP(0x00E1, 0xE1); // LATIN SMALL LETTER A WITH ACUTE + REMAP(0x00E2, 0xE2); // LATIN SMALL LETTER A WITH CIRCUMFLEX + REMAP(0x0103, 0xE3); // LATIN SMALL LETTER A WITH BREVE + REMAP(0x00E4, 0xE4); // LATIN SMALL LETTER A WITH DIAERESIS + REMAP(0x013A, 0xE5); // LATIN SMALL LETTER L WITH ACUTE + REMAP(0x0107, 0xE6); // LATIN SMALL LETTER C WITH ACUTE + REMAP(0x00E7, 0xE7); // LATIN SMALL LETTER C WITH CEDILLA + REMAP(0x010D, 0xE8); // LATIN SMALL LETTER C WITH CARON + REMAP(0x00E9, 0xE9); // LATIN SMALL LETTER E WITH ACUTE + REMAP(0x0119, 0xEA); // LATIN SMALL LETTER E WITH OGONEK + REMAP(0x00EB, 0xEB); // LATIN SMALL LETTER E WITH DIAERESIS + REMAP(0x011B, 0xEC); // LATIN SMALL LETTER E WITH CARON + REMAP(0x00ED, 0xED); // LATIN SMALL LETTER I WITH ACUTE + REMAP(0x00EE, 0xEE); // LATIN SMALL LETTER I WITH CIRCUMFLEX + REMAP(0x010F, 0xEF); // LATIN SMALL LETTER D WITH CARON + + REMAP(0x0111, 0xF0); // LATIN SMALL LETTER D WITH STROKE + REMAP(0x0144, 0xF1); // LATIN SMALL LETTER N WITH ACUTE + REMAP(0x0148, 0xF2); // LATIN SMALL LETTER N WITH CARON + REMAP(0x00F3, 0xF3); // LATIN SMALL LETTER O WITH ACUTE + REMAP(0x00F4, 0xF4); // LATIN SMALL LETTER O WITH CIRCUMFLEX + REMAP(0x0151, 0xF5); // LATIN SMALL LETTER O WITH DOUBLE ACUTE + REMAP(0x00F6, 0xF6); // LATIN SMALL LETTER O WITH DIAERESIS + REMAP(0x00F7, 0xF7); // DIVISION SIGN + REMAP(0x0159, 0xF8); // LATIN SMALL LETTER R WITH CARON + REMAP(0x016F, 0xF9); // LATIN SMALL LETTER U WITH RING ABOVE + REMAP(0x00FA, 0xFA); // LATIN SMALL LETTER U WITH ACUTE + REMAP(0x0171, 0xFB); // LATIN SMALL LETTER U WITH DOUBLE ACUTE + REMAP(0x00FC, 0xFC); // LATIN SMALL LETTER U WITH DIAERESIS + REMAP(0x00FD, 0xFD); // LATIN SMALL LETTER Y WITH ACUTE + REMAP(0x0163, 0xFE); // LATIN SMALL LETTER T WITH CEDILLA + REMAP(0x02D9, 0xFF); // DOT ABOVE } } -} -// Apply a set of substitutions which remap UTF8 for a Windows-1251 font -// Windows-1251 is an 8-bit character encoding, suitable for several languages which use the Cyrillic script -void InkHUD::AppletFont::addSubstitutionsWin1251() -{ - addSubstitution("Ђ", "\x80"); - addSubstitution("Ѓ", "\x81"); - addSubstitution("ѓ", "\x83"); - addSubstitution("€", "\x88"); - addSubstitution("Љ", "\x8A"); - addSubstitution("Њ", "\x8C"); - addSubstitution("Ќ", "\x8D"); - addSubstitution("Ћ", "\x8E"); - addSubstitution("Џ", "\x8F"); + // Latin - Cyrillic + // https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT + else if (encoding == WINDOWS_1251) { + // 1-Byte chars: no remapping + if (utf8.length() == 1) + return utf8.at(0); - addSubstitution("ђ", "\x90"); - addSubstitution("љ", "\x9A"); - addSubstitution("њ", "\x9C"); - addSubstitution("ќ", "\x9D"); - addSubstitution("ћ", "\x9E"); - addSubstitution("џ", "\x9F"); + // Multi-byte chars: + switch (toUtf32(utf8)) { + REMAP(0x0402, 0x80); // CYRILLIC CAPITAL LETTER DJE + REMAP(0x0403, 0x81); // CYRILLIC CAPITAL LETTER GJE + REMAP(0x201A, 0x82); // SINGLE LOW-9 QUOTATION MARK + REMAP(0x0453, 0x83); // CYRILLIC SMALL LETTER GJE + REMAP(0x201E, 0x84); // DOUBLE LOW-9 QUOTATION MARK + REMAP(0x2026, 0x85); // HORIZONTAL ELLIPSIS + REMAP(0x2020, 0x86); // DAGGER + REMAP(0x2021, 0x87); // DOUBLE DAGGER + REMAP(0x20AC, 0x88); // EURO SIGN + REMAP(0x2030, 0x89); // PER MILLE SIGN + REMAP(0x0409, 0x8A); // CYRILLIC CAPITAL LETTER LJE + REMAP(0x2039, 0x8B); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + REMAP(0x040A, 0x8C); // CYRILLIC CAPITAL LETTER NJE + REMAP(0x040C, 0x8D); // CYRILLIC CAPITAL LETTER KJE + REMAP(0x040B, 0x8E); // CYRILLIC CAPITAL LETTER TSHE + REMAP(0x040F, 0x8F); // CYRILLIC CAPITAL LETTER DZHE - addSubstitution("Ў", "\xA1"); - addSubstitution("ў", "\xA2"); - addSubstitution("Ј", "\xA3"); - addSubstitution("Ґ", "\xA5"); - addSubstitution("Ё", "\xA8"); - addSubstitution("Є", "\xAA"); - addSubstitution("Ї", "\xAF"); + REMAP(0x0452, 0x90); // CYRILLIC SMALL LETTER DJE + REMAP(0x2018, 0x91); // LEFT SINGLE QUOTATION MARK + REMAP(0x2019, 0x92); // RIGHT SINGLE QUOTATION MARK + REMAP(0x201C, 0x93); // LEFT DOUBLE QUOTATION MARK + REMAP(0x201D, 0x94); // RIGHT DOUBLE QUOTATION MARK + REMAP(0x2022, 0x95); // BULLET + REMAP(0x2013, 0x96); // EN DASH + REMAP(0x2014, 0x97); // EM DASH + REMAP(0x2122, 0x99); // TRADE MARK SIGN + REMAP(0x0459, 0x9A); // CYRILLIC SMALL LETTER LJE + REMAP(0x203A, 0x9B); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + REMAP(0x045A, 0x9C); // CYRILLIC SMALL LETTER NJE + REMAP(0x045C, 0x9D); // CYRILLIC SMALL LETTER KJE + REMAP(0x045B, 0x9E); // CYRILLIC SMALL LETTER TSHE + REMAP(0x045F, 0x9F); // CYRILLIC SMALL LETTER DZHE - addSubstitution("І", "\xB2"); - addSubstitution("і", "\xB3"); - addSubstitution("ґ", "\xB4"); - addSubstitution("ё", "\xB8"); - addSubstitution("№", "\xB9"); - addSubstitution("є", "\xBA"); - addSubstitution("ј", "\xBC"); - addSubstitution("Ѕ", "\xBD"); - addSubstitution("ѕ", "\xBE"); - addSubstitution("ї", "\xBF"); + REMAP(0x00A0, 0xA0); // NO-BREAK SPACE + REMAP(0x040E, 0xA1); // CYRILLIC CAPITAL LETTER SHORT U + REMAP(0x045E, 0xA2); // CYRILLIC SMALL LETTER SHORT U + REMAP(0x0408, 0xA3); // CYRILLIC CAPITAL LETTER JE + REMAP(0x00A4, 0xA4); // CURRENCY SIGN + REMAP(0x0490, 0xA5); // CYRILLIC CAPITAL LETTER GHE WITH UPTURN + REMAP(0x00A6, 0xA6); // BROKEN BAR + REMAP(0x00A7, 0xA7); // SECTION SIGN + REMAP(0x0401, 0xA8); // CYRILLIC CAPITAL LETTER IO + REMAP(0x00A9, 0xA9); // COPYRIGHT SIGN + REMAP(0x0404, 0xAA); // CYRILLIC CAPITAL LETTER UKRAINIAN IE + REMAP(0x00AB, 0xAB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x00AC, 0xAC); // NOT SIGN + REMAP(0x00AD, 0xAD); // SOFT HYPHEN + REMAP(0x00AE, 0xAE); // REGISTERED SIGN + REMAP(0x0407, 0xAF); // CYRILLIC CAPITAL LETTER YI - addSubstitution("А", "\xC0"); - addSubstitution("Б", "\xC1"); - addSubstitution("В", "\xC2"); - addSubstitution("Г", "\xC3"); - addSubstitution("Д", "\xC4"); - addSubstitution("Е", "\xC5"); - addSubstitution("Ж", "\xC6"); - addSubstitution("З", "\xC7"); - addSubstitution("И", "\xC8"); - addSubstitution("Й", "\xC9"); - addSubstitution("К", "\xCA"); - addSubstitution("Л", "\xCB"); - addSubstitution("М", "\xCC"); - addSubstitution("Н", "\xCD"); - addSubstitution("О", "\xCE"); - addSubstitution("П", "\xCF"); + REMAP(0x00B0, 0xB0); // DEGREE SIGN + REMAP(0x00B1, 0xB1); // PLUS-MINUS SIGN + REMAP(0x0406, 0xB2); // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + REMAP(0x0456, 0xB3); // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + REMAP(0x0491, 0xB4); // CYRILLIC SMALL LETTER GHE WITH UPTURN + REMAP(0x00B5, 0xB5); // MICRO SIGN + REMAP(0x00B6, 0xB6); // PILCROW SIGN + REMAP(0x00B7, 0xB7); // MIDDLE DOT + REMAP(0x0451, 0xB8); // CYRILLIC SMALL LETTER IO + REMAP(0x2116, 0xB9); // NUMERO SIGN + REMAP(0x0454, 0xBA); // CYRILLIC SMALL LETTER UKRAINIAN IE + REMAP(0x00BB, 0xBB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x0458, 0xBC); // CYRILLIC SMALL LETTER JE + REMAP(0x0405, 0xBD); // CYRILLIC CAPITAL LETTER DZE + REMAP(0x0455, 0xBE); // CYRILLIC SMALL LETTER DZE + REMAP(0x0457, 0xBF); // CYRILLIC SMALL LETTER YI - addSubstitution("Р", "\xD0"); - addSubstitution("С", "\xD1"); - addSubstitution("Т", "\xD2"); - addSubstitution("У", "\xD3"); - addSubstitution("Ф", "\xD4"); - addSubstitution("Х", "\xD5"); - addSubstitution("Ц", "\xD6"); - addSubstitution("Ч", "\xD7"); - addSubstitution("Ш", "\xD8"); - addSubstitution("Щ", "\xD9"); - addSubstitution("Ъ", "\xDA"); - addSubstitution("Ы", "\xDB"); - addSubstitution("Ь", "\xDC"); - addSubstitution("Э", "\xDD"); - addSubstitution("Ю", "\xDE"); - addSubstitution("Я", "\xDF"); + REMAP(0x0410, 0xC0); // CYRILLIC CAPITAL LETTER A + REMAP(0x0411, 0xC1); // CYRILLIC CAPITAL LETTER BE + REMAP(0x0412, 0xC2); // CYRILLIC CAPITAL LETTER VE + REMAP(0x0413, 0xC3); // CYRILLIC CAPITAL LETTER GHE + REMAP(0x0414, 0xC4); // CYRILLIC CAPITAL LETTER DE + REMAP(0x0415, 0xC5); // CYRILLIC CAPITAL LETTER IE + REMAP(0x0416, 0xC6); // CYRILLIC CAPITAL LETTER ZHE + REMAP(0x0417, 0xC7); // CYRILLIC CAPITAL LETTER ZE + REMAP(0x0418, 0xC8); // CYRILLIC CAPITAL LETTER I + REMAP(0x0419, 0xC9); // CYRILLIC CAPITAL LETTER SHORT I + REMAP(0x041A, 0xCA); // CYRILLIC CAPITAL LETTER KA + REMAP(0x041B, 0xCB); // CYRILLIC CAPITAL LETTER EL + REMAP(0x041C, 0xCC); // CYRILLIC CAPITAL LETTER EM + REMAP(0x041D, 0xCD); // CYRILLIC CAPITAL LETTER EN + REMAP(0x041E, 0xCE); // CYRILLIC CAPITAL LETTER O + REMAP(0x041F, 0xCF); // CYRILLIC CAPITAL LETTER PE - addSubstitution("а", "\xE0"); - addSubstitution("б", "\xE1"); - addSubstitution("в", "\xE2"); - addSubstitution("г", "\xE3"); - addSubstitution("д", "\xE4"); - addSubstitution("е", "\xE5"); - addSubstitution("ж", "\xE6"); - addSubstitution("з", "\xE7"); - addSubstitution("и", "\xE8"); - addSubstitution("й", "\xE9"); - addSubstitution("к", "\xEA"); - addSubstitution("л", "\xEB"); - addSubstitution("м", "\xEC"); - addSubstitution("н", "\xED"); - addSubstitution("о", "\xEE"); - addSubstitution("п", "\xEF"); + REMAP(0x0420, 0xD0); // CYRILLIC CAPITAL LETTER ER + REMAP(0x0421, 0xD1); // CYRILLIC CAPITAL LETTER ES + REMAP(0x0422, 0xD2); // CYRILLIC CAPITAL LETTER TE + REMAP(0x0423, 0xD3); // CYRILLIC CAPITAL LETTER U + REMAP(0x0424, 0xD4); // CYRILLIC CAPITAL LETTER EF + REMAP(0x0425, 0xD5); // CYRILLIC CAPITAL LETTER HA + REMAP(0x0426, 0xD6); // CYRILLIC CAPITAL LETTER TSE + REMAP(0x0427, 0xD7); // CYRILLIC CAPITAL LETTER CHE + REMAP(0x0428, 0xD8); // CYRILLIC CAPITAL LETTER SHA + REMAP(0x0429, 0xD9); // CYRILLIC CAPITAL LETTER SHCHA + REMAP(0x042A, 0xDA); // CYRILLIC CAPITAL LETTER HARD SIGN + REMAP(0x042B, 0xDB); // CYRILLIC CAPITAL LETTER YERU + REMAP(0x042C, 0xDC); // CYRILLIC CAPITAL LETTER SOFT SIGN + REMAP(0x042D, 0xDD); // CYRILLIC CAPITAL LETTER E + REMAP(0x042E, 0xDE); // CYRILLIC CAPITAL LETTER YU + REMAP(0x042F, 0xDF); // CYRILLIC CAPITAL LETTER YA - addSubstitution("р", "\xF0"); - addSubstitution("с", "\xF1"); - addSubstitution("т", "\xF2"); - addSubstitution("у", "\xF3"); - addSubstitution("ф", "\xF4"); - addSubstitution("х", "\xF5"); - addSubstitution("ц", "\xF6"); - addSubstitution("ч", "\xF7"); - addSubstitution("ш", "\xF8"); - addSubstitution("щ", "\xF9"); - addSubstitution("ъ", "\xFA"); - addSubstitution("ы", "\xFB"); - addSubstitution("ь", "\xFC"); - addSubstitution("э", "\xFD"); - addSubstitution("ю", "\xFE"); - addSubstitution("я", "\xFF"); + REMAP(0x0430, 0xE0); // CYRILLIC SMALL LETTER A + REMAP(0x0431, 0xE1); // CYRILLIC SMALL LETTER BE + REMAP(0x0432, 0xE2); // CYRILLIC SMALL LETTER VE + REMAP(0x0433, 0xE3); // CYRILLIC SMALL LETTER GHE + REMAP(0x0434, 0xE4); // CYRILLIC SMALL LETTER DE + REMAP(0x0435, 0xE5); // CYRILLIC SMALL LETTER IE + REMAP(0x0436, 0xE6); // CYRILLIC SMALL LETTER ZHE + REMAP(0x0437, 0xE7); // CYRILLIC SMALL LETTER ZE + REMAP(0x0438, 0xE8); // CYRILLIC SMALL LETTER I + REMAP(0x0439, 0xE9); // CYRILLIC SMALL LETTER SHORT I + REMAP(0x043A, 0xEA); // CYRILLIC SMALL LETTER KA + REMAP(0x043B, 0xEB); // CYRILLIC SMALL LETTER EL + REMAP(0x043C, 0xEC); // CYRILLIC SMALL LETTER EM + REMAP(0x043D, 0xED); // CYRILLIC SMALL LETTER EN + REMAP(0x043E, 0xEE); // CYRILLIC SMALL LETTER O + REMAP(0x043F, 0xEF); // CYRILLIC SMALL LETTER PE + + REMAP(0x0440, 0xF0); // CYRILLIC SMALL LETTER ER + REMAP(0x0441, 0xF1); // CYRILLIC SMALL LETTER ES + REMAP(0x0442, 0xF2); // CYRILLIC SMALL LETTER TE + REMAP(0x0443, 0xF3); // CYRILLIC SMALL LETTER U + REMAP(0x0444, 0xF4); // CYRILLIC SMALL LETTER EF + REMAP(0x0445, 0xF5); // CYRILLIC SMALL LETTER HA + REMAP(0x0446, 0xF6); // CYRILLIC SMALL LETTER TSE + REMAP(0x0447, 0xF7); // CYRILLIC SMALL LETTER CHE + REMAP(0x0448, 0xF8); // CYRILLIC SMALL LETTER SHA + REMAP(0x0449, 0xF9); // CYRILLIC SMALL LETTER SHCHA + REMAP(0x044A, 0xFA); // CYRILLIC SMALL LETTER HARD SIGN + REMAP(0x044B, 0xFB); // CYRILLIC SMALL LETTER YERU + REMAP(0x044C, 0xFC); // CYRILLIC SMALL LETTER SOFT SIGN + REMAP(0x044D, 0xFD); // CYRILLIC SMALL LETTER E + REMAP(0x044E, 0xFE); // CYRILLIC SMALL LETTER YU + REMAP(0x044F, 0xFF); // CYRILLIC SMALL LETTER YA + } + } + + // Latin - Western Europe + // https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT + else if (encoding == WINDOWS_1252) { + // 1-Byte chars: no remapping + if (utf8.length() == 1) + return utf8.at(0); + + // Multi-byte chars: + switch (toUtf32(utf8)) { + REMAP(0x20AC, 0x80) // EURO SIGN + REMAP(0x201A, 0x82) // SINGLE LOW-9 QUOTATION MARK + REMAP(0x0192, 0x83) // LATIN SMALL LETTER F WITH HOOK + REMAP(0x201E, 0x84) // DOUBLE LOW-9 QUOTATION MARK + REMAP(0x2026, 0x85) // HORIZONTAL ELLIPSIS + REMAP(0x2020, 0x86) // DAGGER + REMAP(0x2021, 0x87) // DOUBLE DAGGER + REMAP(0x02C6, 0x88) // MODIFIER LETTER CIRCUMFLEX ACCENT + REMAP(0x2030, 0x89) // PER MILLE SIGN + REMAP(0x0160, 0x8A) // LATIN CAPITAL LETTER S WITH CARON + REMAP(0x2039, 0x8B) // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + REMAP(0x0152, 0x8C) // LATIN CAPITAL LIGATURE OE + REMAP(0x017D, 0x8E) // LATIN CAPITAL LETTER Z WITH CARON + + REMAP(0x2018, 0x91) // LEFT SINGLE QUOTATION MARK + REMAP(0x2019, 0x92) // RIGHT SINGLE QUOTATION MARK + REMAP(0x201C, 0x93) // LEFT DOUBLE QUOTATION MARK + REMAP(0x201D, 0x94) // RIGHT DOUBLE QUOTATION MARK + REMAP(0x2022, 0x95) // BULLET + REMAP(0x2013, 0x96) // EN DASH + REMAP(0x2014, 0x97) // EM DASH + REMAP(0x02DC, 0x98) // SMALL TILDE + REMAP(0x2122, 0x99) // TRADE MARK SIGN + REMAP(0x0161, 0x9A) // LATIN SMALL LETTER S WITH CARON + REMAP(0x203A, 0x9B) // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + REMAP(0x0153, 0x9C) // LATIN SMALL LIGATURE OE + REMAP(0x017E, 0x9E) // LATIN SMALL LETTER Z WITH CARON + REMAP(0x0178, 0x9F) // LATIN CAPITAL LETTER Y WITH DIAERESIS + + REMAP(0x00A0, 0xA0) // NO-BREAK SPACE + REMAP(0x00A1, 0xA1) // INVERTED EXCLAMATION MARK + REMAP(0x00A2, 0xA2) // CENT SIGN + REMAP(0x00A3, 0xA3) // POUND SIGN + REMAP(0x00A4, 0xA4) // CURRENCY SIGN + REMAP(0x00A5, 0xA5) // YEN SIGN + REMAP(0x00A6, 0xA6) // BROKEN BAR + REMAP(0x00A7, 0xA7) // SECTION SIGN + REMAP(0x00A8, 0xA8) // DIAERESIS + REMAP(0x00A9, 0xA9) // COPYRIGHT SIGN + REMAP(0x00AA, 0xAA) // FEMININE ORDINAL INDICATOR + REMAP(0x00AB, 0xAB) // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x00AC, 0xAC) // NOT SIGN + REMAP(0x00AD, 0xAD) // SOFT HYPHEN + REMAP(0x00AE, 0xAE) // REGISTERED SIGN + REMAP(0x00AF, 0xAF) // MACRON + + REMAP(0x00B0, 0xB0) // DEGREE SIGN + REMAP(0x00B1, 0xB1) // PLUS-MINUS SIGN + REMAP(0x00B2, 0xB2) // SUPERSCRIPT TWO + REMAP(0x00B3, 0xB3) // SUPERSCRIPT THREE + REMAP(0x00B4, 0xB4) // ACUTE ACCENT + REMAP(0x00B5, 0xB5) // MICRO SIGN + REMAP(0x00B6, 0xB6) // PILCROW SIGN + REMAP(0x00B7, 0xB7) // MIDDLE DOT + REMAP(0x00B8, 0xB8) // CEDILLA + REMAP(0x00B9, 0xB9) // SUPERSCRIPT ONE + REMAP(0x00BA, 0xBA) // MASCULINE ORDINAL INDICATOR + REMAP(0x00BB, 0xBB) // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + REMAP(0x00BC, 0xBC) // VULGAR FRACTION ONE QUARTER + REMAP(0x00BD, 0xBD) // VULGAR FRACTION ONE HALF + REMAP(0x00BE, 0xBE) // VULGAR FRACTION THREE QUARTERS + REMAP(0x00BF, 0xBF) // INVERTED QUESTION MARK + + REMAP(0x00C0, 0xC0) // LATIN CAPITAL LETTER A WITH GRAVE + REMAP(0x00C1, 0xC1) // LATIN CAPITAL LETTER A WITH ACUTE + REMAP(0x00C2, 0xC2) // LATIN CAPITAL LETTER A WITH CIRCUMFLEX + REMAP(0x00C3, 0xC3) // LATIN CAPITAL LETTER A WITH TILDE + REMAP(0x00C4, 0xC4) // LATIN CAPITAL LETTER A WITH DIAERESIS + REMAP(0x00C5, 0xC5) // LATIN CAPITAL LETTER A WITH RING ABOVE + REMAP(0x00C6, 0xC6) // LATIN CAPITAL LETTER AE + REMAP(0x00C7, 0xC7) // LATIN CAPITAL LETTER C WITH CEDILLA + REMAP(0x00C8, 0xC8) // LATIN CAPITAL LETTER E WITH GRAVE + REMAP(0x00C9, 0xC9) // LATIN CAPITAL LETTER E WITH ACUTE + REMAP(0x00CA, 0xCA) // LATIN CAPITAL LETTER E WITH CIRCUMFLEX + REMAP(0x00CB, 0xCB) // LATIN CAPITAL LETTER E WITH DIAERESIS + REMAP(0x00CC, 0xCC) // LATIN CAPITAL LETTER I WITH GRAVE + REMAP(0x00CD, 0xCD) // LATIN CAPITAL LETTER I WITH ACUTE + REMAP(0x00CE, 0xCE) // LATIN CAPITAL LETTER I WITH CIRCUMFLEX + REMAP(0x00CF, 0xCF) // LATIN CAPITAL LETTER I WITH DIAERESIS + + REMAP(0x00D0, 0xD0) // LATIN CAPITAL LETTER ETH + REMAP(0x00D1, 0xD1) // LATIN CAPITAL LETTER N WITH TILDE + REMAP(0x00D2, 0xD2) // LATIN CAPITAL LETTER O WITH GRAVE + REMAP(0x00D3, 0xD3) // LATIN CAPITAL LETTER O WITH ACUTE + REMAP(0x00D4, 0xD4) // LATIN CAPITAL LETTER O WITH CIRCUMFLEX + REMAP(0x00D5, 0xD5) // LATIN CAPITAL LETTER O WITH TILDE + REMAP(0x00D6, 0xD6) // LATIN CAPITAL LETTER O WITH DIAERESIS + REMAP(0x00D7, 0xD7) // MULTIPLICATION SIGN + REMAP(0x00D8, 0xD8) // LATIN CAPITAL LETTER O WITH STROKE + REMAP(0x00D9, 0xD9) // LATIN CAPITAL LETTER U WITH GRAVE + REMAP(0x00DA, 0xDA) // LATIN CAPITAL LETTER U WITH ACUTE + REMAP(0x00DB, 0xDB) // LATIN CAPITAL LETTER U WITH CIRCUMFLEX + REMAP(0x00DC, 0xDC) // LATIN CAPITAL LETTER U WITH DIAERESIS + REMAP(0x00DD, 0xDD) // LATIN CAPITAL LETTER Y WITH ACUTE + REMAP(0x00DE, 0xDE) // LATIN CAPITAL LETTER THORN + REMAP(0x00DF, 0xDF) // LATIN SMALL LETTER SHARP S + + REMAP(0x00E0, 0xE0) // LATIN SMALL LETTER A WITH GRAVE + REMAP(0x00E1, 0xE1) // LATIN SMALL LETTER A WITH ACUTE + REMAP(0x00E2, 0xE2) // LATIN SMALL LETTER A WITH CIRCUMFLEX + REMAP(0x00E3, 0xE3) // LATIN SMALL LETTER A WITH TILDE + REMAP(0x00E4, 0xE4) // LATIN SMALL LETTER A WITH DIAERESIS + REMAP(0x00E5, 0xE5) // LATIN SMALL LETTER A WITH RING ABOVE + REMAP(0x00E6, 0xE6) // LATIN SMALL LETTER AE + REMAP(0x00E7, 0xE7) // LATIN SMALL LETTER C WITH CEDILLA + REMAP(0x00E8, 0xE8) // LATIN SMALL LETTER E WITH GRAVE + REMAP(0x00E9, 0xE9) // LATIN SMALL LETTER E WITH ACUTE + REMAP(0x00EA, 0xEA) // LATIN SMALL LETTER E WITH CIRCUMFLEX + REMAP(0x00EB, 0xEB) // LATIN SMALL LETTER E WITH DIAERESIS + REMAP(0x00EC, 0xEC) // LATIN SMALL LETTER I WITH GRAVE + REMAP(0x00ED, 0xED) // LATIN SMALL LETTER I WITH ACUTE + REMAP(0x00EE, 0xEE) // LATIN SMALL LETTER I WITH CIRCUMFLEX + REMAP(0x00EF, 0xEF) // LATIN SMALL LETTER I WITH DIAERESIS + + REMAP(0x00F0, 0xF0) // LATIN SMALL LETTER ETH + REMAP(0x00F1, 0xF1) // LATIN SMALL LETTER N WITH TILDE + REMAP(0x00F2, 0xF2) // LATIN SMALL LETTER O WITH GRAVE + REMAP(0x00F3, 0xF3) // LATIN SMALL LETTER O WITH ACUTE + REMAP(0x00F4, 0xF4) // LATIN SMALL LETTER O WITH CIRCUMFLEX + REMAP(0x00F5, 0xF5) // LATIN SMALL LETTER O WITH TILDE + REMAP(0x00F6, 0xF6) // LATIN SMALL LETTER O WITH DIAERESIS + REMAP(0x00F7, 0xF7) // DIVISION SIGN + REMAP(0x00F8, 0xF8) // LATIN SMALL LETTER O WITH STROKE + REMAP(0x00F9, 0xF9) // LATIN SMALL LETTER U WITH GRAVE + REMAP(0x00FA, 0xFA) // LATIN SMALL LETTER U WITH ACUTE + REMAP(0x00FB, 0xFB) // LATIN SMALL LETTER U WITH CIRCUMFLEX + REMAP(0x00FC, 0xFC) // LATIN SMALL LETTER U WITH DIAERESIS + REMAP(0x00FD, 0xFD) // LATIN SMALL LETTER Y WITH ACUTE + REMAP(0x00FE, 0xFE) // LATIN SMALL LETTER THORN + REMAP(0x00FF, 0xFF) // LATIN SMALL LETTER Y WITH DIAERESIS + } + } + + // If not handled, return DEL + // Todo: swap this to SUB, and modify the fonts + return '\x7F'; + +// Sweep up the syntactic sugar +// Don't want ants in the house +#undef REMAP } #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/AppletFont.h b/src/graphics/niche/InkHUD/AppletFont.h index 504bd12b3..67348b8d3 100644 --- a/src/graphics/niche/InkHUD/AppletFont.h +++ b/src/graphics/niche/InkHUD/AppletFont.h @@ -4,10 +4,7 @@ Wrapper class for an AdafruitGFX font Pre-calculates some font dimension info which InkHUD uses repeatedly - - Also contains an optional set of "substitutions". - These can be used to detect special UTF8 chars, and replace occurrences with a remapped char val to suit a custom font - These can also be used to swap UTF8 chars for a suitable ASCII substitution (e.g. German ö -> oe, etc) + Re-encodes UTF-8 characters to suit extended ASCII AdafruitGFX fonts */ @@ -24,36 +21,61 @@ namespace NicheGraphics::InkHUD class AppletFont { public: + enum Encoding { + ASCII, + WINDOWS_1250, + WINDOWS_1251, + WINDOWS_1252, + }; + AppletFont(); - explicit AppletFont(const GFXfont &adafruitGFXFont); + AppletFont(const GFXfont &adafruitGFXFont, Encoding encoding = ASCII, int8_t paddingTop = 0, int8_t paddingBottom = 0); uint8_t lineHeight(); uint8_t heightAboveCursor(); uint8_t heightBelowCursor(); uint8_t widthBetweenWords(); // Width of the space character - void applySubstitutions(std::string *text); // Run all char-substitution operations, prior to printing - void addSubstitution(const char *from, const char *to); // Register a find-replace action, for remapping UTF8 chars - void addSubstitutionsWin1251(); // Cyrillic fonts: remap UTF8 values to their Win-1251 equivalent - // Todo: Polish font + std::string decodeUTF8(std::string encoded); const GFXfont *gfxFont = NULL; // Default value: in-built AdafruitGFX font private: + uint32_t toUtf32(std::string utf8); + char applyEncoding(std::string utf8); + uint8_t height = 8; // Default value: in-built AdafruitGFX font uint8_t ascenderHeight = 0; // Default value: in-built AdafruitGFX font uint8_t descenderHeight = 8; // Default value: in-built AdafruitGFX font uint8_t spaceCharWidth = 8; // Default value: in-built AdafruitGFX font - // One pair of find-replace values, for substituting or remapping UTF8 chars - struct Substitution { - const char *from; - const char *to; - }; - - std::vector substitutions; // List of all character substitutions to run, prior to printing a string + Encoding encoding = ASCII; }; } // namespace NicheGraphics::InkHUD +// Macros for InkHUD's standard fonts +// -------------------------------------- + +// Use these once only, passing them to InkHUD::Applet::fontLarge and InkHUD::Applet:fontSmall +// Line padding has been adjusted manually, to compensate for a few *extra tall* diacritics + +// Central European +#include "graphics/niche/Fonts/FreeSans6pt_Win1250.h" +#include "graphics/niche/Fonts/FreeSans9pt_Win1250.h" +#define FREESANS_9PT_WIN1250 InkHUD::AppletFont(FreeSans9pt_Win1250, InkHUD::AppletFont::WINDOWS_1250, -1, -1) +#define FREESANS_6PT_WIN1250 InkHUD::AppletFont(FreeSans6pt_Win1250, InkHUD::AppletFont::WINDOWS_1250, -1, -2) + +// Cyrillic +#include "graphics/niche/Fonts/FreeSans6pt_Win1251.h" +#include "graphics/niche/Fonts/FreeSans9pt_Win1251.h" +#define FREESANS_9PT_WIN1251 InkHUD::AppletFont(FreeSans9pt_Win1251, InkHUD::AppletFont::WINDOWS_1251, -2, -1) +#define FREESANS_6PT_WIN1251 InkHUD::AppletFont(FreeSans6pt_Win1251, InkHUD::AppletFont::WINDOWS_1251, -1, -2) + +// Western European +#include "graphics/niche/Fonts/FreeSans6pt_Win1252.h" +#include "graphics/niche/Fonts/FreeSans9pt_Win1252.h" +#define FREESANS_9PT_WIN1252 InkHUD::AppletFont(FreeSans9pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -2, -1) +#define FREESANS_6PT_WIN1252 InkHUD::AppletFont(FreeSans6pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -1, -2) + #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp index ea7b74262..db0805f4e 100644 --- a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp @@ -286,6 +286,10 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node) bool isOurNode = node->num == nodeDB->getNodeNum(); bool unknownHops = !node->has_hops_away && !isOurNode; + // Parse any non-ascii chars in the short name, + // and use last 4 instead if unknown / can't render + std::string shortName = parseShortName(node); + // We will draw a left or right hand variant, to place text towards screen center // Hopefully avoid text spilling off screen // Most values are the same, regardless of left-right handedness @@ -299,7 +303,7 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node) markerSize = map(node->hops_away, 0, config.lora.hop_limit, markerSizeMax, markerSizeMin); // Common dimensions (left or right variant) - textW = getTextWidth(node->user.short_name); + textW = getTextWidth(shortName); if (textW == 0) paddingInnerW = 0; // If no text, no padding for text textH = fontSmall.lineHeight(); @@ -325,7 +329,7 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node) drawRect(labelX, labelY, labelW, labelH, BLACK); // Short name - printAt(textX, textY, node->user.short_name, LEFT, MIDDLE); + printAt(textX, textY, shortName, LEFT, MIDDLE); // If the label is for our own node, // fade it by overdrawing partially with white diff --git a/src/graphics/niche/InkHUD/Applets/Bases/NodeList/NodeListApplet.cpp b/src/graphics/niche/InkHUD/Applets/Bases/NodeList/NodeListApplet.cpp index 8ede40780..7fa31b244 100644 --- a/src/graphics/niche/InkHUD/Applets/Bases/NodeList/NodeListApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/Bases/NodeList/NodeListApplet.cpp @@ -142,16 +142,18 @@ void InkHUD::NodeListApplet::onRender() meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeNum); // -- Shortname -- - // use "?" if unknown - if (node && node->has_user) - shortName = node->user.short_name; + // Parse special chars in the short name + // Use "?" if unknown + if (node) + shortName = parseShortName(node); else shortName = "?"; // -- Longname -- - // use node id if unknown + // Parse special chars in long name + // Use node id if unknown if (node && node->has_user) - longName = node->user.long_name; // Found in nodeDB + longName = parse(node->user.long_name); // Found in nodeDB else { // Not found in nodeDB, show a hex nodeid instead longName = hexifyNodeNum(nodeNum); diff --git a/src/graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.cpp b/src/graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.cpp index b12ea4809..c52719e55 100644 --- a/src/graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.cpp @@ -9,6 +9,12 @@ using namespace NicheGraphics; void InkHUD::BasicExampleApplet::onRender() { printAt(0, 0, "Hello, World!"); + + // If text might contain "special characters", is needs parsing first + // This applies to data such as text-messages and and node names + + // std::string greeting = parse("Grüezi mitenand!"); + // printAt(0, 0, greeting); } #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h b/src/graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h index f280afcda..22670a0f0 100644 --- a/src/graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h +++ b/src/graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h @@ -5,7 +5,7 @@ An example of an InkHUD applet. Tells us when a new text message arrives. -This applet makes use of the MeshModule API to detect new messages, +This applet makes use of the Module API to detect new messages, which is a general part of the Meshtastic firmware, and not part of InkHUD. In variants//nicheGraphics.h: diff --git a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp index 5ca9692c8..9fdfad8ee 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Menu/MenuApplet.cpp @@ -244,6 +244,7 @@ void InkHUD::MenuApplet::execute(MenuItem item) void InkHUD::MenuApplet::showPage(MenuPage page) { items.clear(); + items.shrink_to_fit(); switch (page) { case ROOT: diff --git a/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp index aa702c032..f9439fab8 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp @@ -33,11 +33,6 @@ int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket if (getFrom(p) == nodeDB->getNodeNum()) return 0; - // Abort if message was only an "emoji reaction" - // Possibly some implementation of this in future? - if (p->decoded.emoji) - return 0; - Notification n; n.timestamp = getValidTime(RTCQuality::RTCQualityDevice, true); // Current RTC time @@ -122,7 +117,7 @@ void InkHUD::NotificationApplet::onRender() int16_t textM = divX + padW + (getTextWidth(text) / 2); // Restrict area for printing - // - don't overlap border, or diveder + // - don't overlap border, or divider setCrop(divX + 1, 1, (width() - (divX + 1) - 1), height() - 2); // Drop shadow @@ -241,7 +236,8 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila } } - return text; + // Parse any non-ascii characters and return + return parse(text); } #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/Applets/System/Pairing/PairingApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Pairing/PairingApplet.cpp index 81de05b30..3f51c7f88 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Pairing/PairingApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Pairing/PairingApplet.cpp @@ -23,9 +23,9 @@ void InkHUD::PairingApplet::onRender() // Device's bluetooth name, if it will fit setFont(fontSmall); - std::string name = "Name: " + std::string(getDeviceName()); + std::string name = "Name: " + parse(getDeviceName()); if (getTextWidth(name) > width()) // Too wide, try without the leading "Name: " - name = std::string(getDeviceName()); + name = parse(getDeviceName()); if (getTextWidth(name) < width()) // Does it fit? printAt(X(0.5), Y(0.75), name, CENTER, MIDDLE); } diff --git a/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp index f7e2a8e9d..968775302 100644 --- a/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp @@ -27,11 +27,6 @@ int InkHUD::AllMessageApplet::onReceiveTextMessage(const meshtastic_MeshPacket * if (getFrom(p) == nodeDB->getNodeNum()) return 0; - // Abort if message was only an "emoji reaction" - // Possibly some implemetation of this in future? - if (p->decoded.emoji) - return 0; - requestAutoshow(); // Want to become foreground, if permitted requestUpdate(); // Want to update display, if applet is foreground @@ -100,19 +95,22 @@ void InkHUD::AllMessageApplet::onRender() // Print message text // =================== + // Parse any non-ascii chars in the message + std::string text = parse(message->text); + // Extra gap below the header int16_t textTop = headerDivY + padDivH; // Determine size if printed large setFont(fontLarge); - uint32_t textHeight = getWrappedTextHeight(0, width(), message->text); + uint32_t textHeight = getWrappedTextHeight(0, width(), text); // If too large, swap to small font if (textHeight + textTop > (uint32_t)height()) // (compare signed and unsigned) setFont(fontSmall); // Print text - printWrapped(0, textTop, width(), message->text); + printWrapped(0, textTop, width(), text); } // Don't show notifications for text messages when our applet is displayed diff --git a/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp index 7a1d14f32..3c69495ed 100644 --- a/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp @@ -23,11 +23,6 @@ int InkHUD::DMApplet::onReceiveTextMessage(const meshtastic_MeshPacket *p) if (!isActive()) return 0; - // Abort if only an "emoji reactions" - // Possibly some implemetation of this in future? - if (p->decoded.emoji) - return 0; - // If DM (not broadcast) if (!isBroadcast(p->to)) { // Want to update display, if applet is foreground @@ -96,19 +91,22 @@ void InkHUD::DMApplet::onRender() // Print message text // =================== + // Parse any non-ascii chars in the message + std::string text = parse(latestMessage->dm.text); + // Extra gap below the header int16_t textTop = headerDivY + padDivH; // Determine size if printed large setFont(fontLarge); - uint32_t textHeight = getWrappedTextHeight(0, width(), latestMessage->dm.text); + uint32_t textHeight = getWrappedTextHeight(0, width(), text); // If too large, swap to small font if (textHeight + textTop > (uint32_t)height()) // (compare signed and unsigned) setFont(fontSmall); // Print text - printWrapped(0, textTop, width(), latestMessage->dm.text); + printWrapped(0, textTop, width(), text); } // Don't show notifications for direct messages when our applet is displayed diff --git a/src/graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.cpp index ceb9c01fe..5a659c606 100644 --- a/src/graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.cpp @@ -16,7 +16,7 @@ void InkHUD::HeardApplet::onActivate() void InkHUD::HeardApplet::onDeactivate() { - // Avoid an unlikely situation where frquent activation / deactivation populated duplicate info from node DB + // Avoid an unlikely situation where frequent activation / deactivation populates duplicate info from node DB cards.clear(); } @@ -41,6 +41,7 @@ void InkHUD::HeardApplet::handleParsed(CardInfo c) cards.push_front(c); // Insert into base class' card collection cards.resize(min(maxCards(), (uint8_t)cards.size())); // Don't keep more cards than we could *ever* fit on screen + cards.shrink_to_fit(); // Our rendered image needs to change if: if (previous.nodeNum != c.nodeNum // Different node @@ -54,7 +55,7 @@ void InkHUD::HeardApplet::handleParsed(CardInfo c) } // When applet is activated, pre-fill with stale data from NodeDB -// We're sorting using the last_heard value. Succeptible to weirdness if node's RTC changes. +// We're sorting using the last_heard value. Susceptible to weirdness if node's RTC changes. // No SNR is available in node db, so we can't calculate signal either // These initial cards from node db will be gradually pushed out by new packets which originate from out base applet instead void InkHUD::HeardApplet::populateFromNodeDB() @@ -72,7 +73,7 @@ void InkHUD::HeardApplet::populateFromNodeDB() return (top->last_heard > bottom->last_heard); }); - // Keep the most recent entries onlyt + // Keep the most recent entries only // Just enough to fill the screen if (ordered.size() > maxCards()) ordered.resize(maxCards()); diff --git a/src/graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.cpp index 02aa4a721..1ccf7fc14 100644 --- a/src/graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.cpp @@ -53,6 +53,7 @@ void InkHUD::RecentsListApplet::handleParsed(CardInfo c) cards.push_front(c); // Store this CardInfo cards.resize(min(maxCards(), (uint8_t)cards.size())); // Don't keep more cards than we could *ever* fit on screen + cards.shrink_to_fit(); // Record the time of this observation // Used to count active nodes, and to know when to prune inactive nodes @@ -99,10 +100,12 @@ void InkHUD::RecentsListApplet::prune() if (!isActive(ages.at(i).seenAtMs)) { // Drop this item, and all others behind it ages.resize(i); + ages.shrink_to_fit(); cards.resize(i); + cards.shrink_to_fit(); // Request an update, if pruning did modify our data - // Required if pruning was scheduled. Redundent if pruning was prior to rendering. + // Required if pruning was scheduled. Redundant if pruning was prior to rendering. requestAutoshow(); requestUpdate(); diff --git a/src/graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.cpp index d7d2e79c8..d5d7f77f8 100644 --- a/src/graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.cpp @@ -71,27 +71,28 @@ void InkHUD::ThreadedMessageApplet::onRender() MessageStore::Message &m = store->messages.at(i); bool outgoing = (m.sender == 0); meshtastic_NodeInfoLite *sender = nodeDB->getMeshNode(m.sender); + std::string bodyText = parse(m.text); // Parse any non-ascii chars in the message // Cache bottom Y of message text // - Used when drawing vertical line alongside const int16_t dotsB = msgB; // Get dimensions for message text - uint16_t bodyH = getWrappedTextHeight(msgL, msgW, m.text); + uint16_t bodyH = getWrappedTextHeight(msgL, msgW, bodyText); int16_t bodyT = msgB - bodyH; // Print message // - if incoming if (!outgoing) - printWrapped(msgL, bodyT, msgW, m.text); + printWrapped(msgL, bodyT, msgW, bodyText); // Print message // - if outgoing else { - if (getTextWidth(m.text) < width()) // If short, - printAt(msgR, bodyT, m.text, RIGHT); // print right align - else // If long, - printWrapped(msgL, bodyT, msgW, m.text); // need printWrapped(), which doesn't support right align + if (getTextWidth(bodyText) < width()) // If short, + printAt(msgR, bodyT, bodyText, RIGHT); // print right align + else // If long, + printWrapped(msgL, bodyT, msgW, bodyText); // need printWrapped(), which doesn't support right align } // Move cursor up @@ -103,12 +104,16 @@ void InkHUD::ThreadedMessageApplet::onRender() // - shortname, if possible, or "me" // - time received, if possible std::string info; - if (sender && sender->has_user) - info += sender->user.short_name; - else if (outgoing) + if (outgoing) info += "Me"; - else - info += hexifyNodeNum(m.sender); + else { + // Check if sender is node db + meshtastic_NodeInfoLite *sender = nodeDB->getMeshNode(m.sender); + if (sender) + info += parseShortName(sender); // Handle any unprintable chars in short name + else + info += hexifyNodeNum(m.sender); // No node info at all. Print the node num + } std::string timeString = getTimeString(m.timestamp); if (timeString.length() > 0) { @@ -195,11 +200,6 @@ int InkHUD::ThreadedMessageApplet::onReceiveTextMessage(const meshtastic_MeshPac if (p->to != NODENUM_BROADCAST) return 0; - // Abort if messages was an "emoji reaction" - // Possibly some implemetation of this in future? - if (p->decoded.emoji) - return 0; - // Extract info into our slimmed-down "StoredMessage" type MessageStore::Message newMessage; newMessage.timestamp = getValidTime(RTCQuality::RTCQualityDevice, true); // Current RTC time diff --git a/src/graphics/niche/InkHUD/Events.cpp b/src/graphics/niche/InkHUD/Events.cpp index d0bd35250..ee6c04938 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -146,11 +146,6 @@ int InkHUD::Events::onReceiveTextMessage(const meshtastic_MeshPacket *packet) if (getFrom(packet) == nodeDB->getNodeNum()) return 0; - // Short circuit: don't store "emoji reactions" - // Possibly some implementation of this in future? - if (packet->decoded.emoji) - return 0; - // Determine whether the message is broadcast or a DM // Store this info to prevent confusion after a reboot // Avoids need to compare timestamps, because of situation where "future" messages block newly received, if time not set diff --git a/src/graphics/niche/InkHUD/docs/README.md b/src/graphics/niche/InkHUD/docs/README.md index c3082add1..b504d46c1 100644 --- a/src/graphics/niche/InkHUD/docs/README.md +++ b/src/graphics/niche/InkHUD/docs/README.md @@ -13,7 +13,7 @@ This document is intended as a reference for maintainers. A haphazard collection - [Non-interactive](#non-interactive) - [Customizable](#customizable) - [Event-Driven Rendering](#event-driven-rendering) - - [No `#ifdef` spaghetti](#no-ifdef-spaghetti) + - [Avoid the Preprocessor](#avoid-the-preprocessor) - [The Implementation](#the-implementation) - [The Rendering Process](#the-rendering-process) - [Concepts](#concepts) @@ -23,6 +23,10 @@ This document is intended as a reference for maintainers. A haphazard collection - [Adding a Variant](#adding-a-variant) - [platformio.ini](#platformioini) - [nicheGraphics.h](#nichegraphicsh) +- [Fonts](#fonts) + - [Parsing Unicode Text](#parsing-unicode-text) + - [Localization](#localization) + - [Creating / Modifying](#creating--modifying) - [Class Notes](#class-notes) - [`InkHUD::InkHUD`](#inkhudinkhud) - [`InkHUD::Persistence`](#inkhudpersistence) @@ -73,9 +77,11 @@ The user should be given the choice to decide which information they would like The display image does not update "automatically". Individual applets are responsible for deciding when they have new information to show, and then requesting a display update. -### No `#ifdef` spaghetti +### Avoid the Preprocessor -**Don't** use preprocessor macros for device-specific configuration. This should be achieved with config methods, in [`nicheGraphics.h`](#nichegraphicsh). +**Don't** use preprocessor macros to write code which targets individual devices. + +**Do** configure InkHUD to suit each device in [`nicheGraphics.h`](#nichegraphicsh). **Do** use preprocessor macros to guard all files @@ -103,7 +109,7 @@ The display image does not update "automatically". Individual applets are respon (animated diagram) -animated process diagram of InkHUD rendering +animated process diagram of InkHUD rendering An overview: @@ -281,11 +287,14 @@ ${esp32s3_base.lib_deps} ### nicheGraphics.h -⚠ Wrap this file in `#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS` +Should contain a `setupNicheGraphics` method, which creates and configures the various components for InkHUD. -`nicheGraphics.h` should be placed in the same folder as your variant's `platformio.ini`. If this is not possible, modify `build_src_filter`. +For well commented examples, see: -`nicheGraphics.h` should contain a `setupNicheGraphics` method, which creates and configures the various components for InkHUD. +- `/variants/heltec_vision_master_e290/nicheGraphics.h` (ESP32) +- `/variants/ELECROW-ThinkNode-M1/nicheGraphics.h` (NRF52) + +As a general overview: - Display - Start SPI @@ -301,10 +310,80 @@ ${esp32s3_base.lib_deps} - Setup `TwoButton` driver (user button, optional "auxiliary" button) - Connect to InkHUD handlers (use lambdas) -For well commented examples, see: +## Fonts -- `variants/heltec_vision_master_e290/nicheGraphics.h` (ESP32) -- `variants/t-echo/nicheGraphics.h` (NRF52) +InkHUD uses AdafruitGFX fonts. The large and small font which are shared by all applets are set in nicheGraphics.h. + +```cpp +// Prepare fonts +InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; +InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; + +// Using a generic AdafruitGFX font instead: +// InkHUD::Applet::fontLarge = FreeSerif9pt7b; +``` + +Any generic AdafruitGFX font may be used, but the fonts which are bundled with InkHUD have been customized with extended-ASCII character sets. + +### Parsing Unicode Text + +Text received by the firmware is encoded as UTF-8. + +Applets must manually parse any text which may contain non-ASCII characters. Strings like text-messages and node names should be parsed. + +```cpp +std::string greeting = "Góðan daginn!"; +std::string parsed = parse(greeting); +``` + +This will re-encode the characters to match whichever extended-ASCII font InkHUD has been built with. + +### Localization + +InkHUD is bundled with extended-ASCII fonts for: + +- Windows-1250 (Central European) +- Windows-1251 (Cyrillic) +- Windows-1252 (Western European) + +The default builds use Windows-1252 encoding. This can be changed in nicheGraphics.h. + +```cpp +InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1250; +InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1250; + +InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1251; +InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1251; +``` + +### Creating / Modifying + +For basic conversion and editing, online tools might be sufficient: + +- [https://rop.nl/truetype2gfx/](https://rop.nl/truetype2gfx/) - converting from ttf +- [https://tchapi.github.io/Adafruit-GFX-Font-Customiser/](https://tchapi.github.io/Adafruit-GFX-Font-Customiser/) - editing glyphs + +For heavy editing, this offline workflow is suggested: + +- [FontForge](https://fontforge.org/en-US/) + - re-ordering glyphs + - Encoding > Load Encoding + - Encoding > Reencode + - .ttf to .bdf conversion + - Element > Bitmap Strikes Available.. + - File > Generate Fonts +- [GFXFontEditor](https://github.com/ScottFerg56/GFXFontEditor) + - manual glyph correction + - .bdf to AdafruitGFX .h conversion + - File > Edit Font Properties + - right-click glyph list, flatten font + - File > Save As + - manually edit exported .h + - remove `#include ` + +If possible, custom Extended-ASCII fonts should use one of the encodings which InkHUD already supports. If this is not possible, a mapping for the new encoding will need to be added. + +See [Encoding](#encoding) for details on using an extended-ASCII font. ## Class Notes @@ -628,17 +707,30 @@ The default AdafruitGFX text handling places characters "upon a line", as if han The height of this box is `AppletFont::lineHeight`, which is the height of the tallest character in the font. This gives us a fixed-height for text, which is much tighter than with AdafruitGFX's default line spacing. -#### UTF-8 Substitutions +#### Encoding -To enable non-English text, the `AppletFont` class includes a mechanism to detect specific UTF-8 characters, and replace them with alternative glyphs from the AdafruitGFX font. This can be used to remap characters for a custom font, or to offer a suitable ASCII replacement. +An AppletFont may be constructed from a standard 7bit ASCII AdafruitGFX font, however InkHUD also supports 8bit extended-ASCII fonts. + +For this, the encoding must be specified when instantiating the AppletFont. ```cpp -// With a custom font -// ї is ASCII 0xBF, in Windows-1251 encoding -addSubstitution("ї", "\xBF"); - -// Substitution (with a default font) -addSubstitution("ö", "oe"); +InkHUD::AppletFont(FreeSans9pt_Win1250, InkHUD::AppletFont::WINDOWS_1250); ``` -These substitutions should be performed in a variant's `setupNicheGraphics` method. For convenience, some common ASCII encodings have ready-to-go sets of substitutions you can apply, for example `AppletFont::addSubstitutionsWin1251` +Currently supported encodings are: + +- ASCII +- Windows-1250 (Central European) +- Windows-1251 (Cyrillic) +- Windows-1252 (Western European) + +To add support for additional encodings, add to the `AppletFont::Encodings` enum, and then define the mapping from unicode in `AppletFont::applyEncoding`. + +#### Custom Line Height + +Some fonts may have a handful of especially tall characters, especially extended-ASCII fonts with diacritcs. Ideally, the font should be modified to help resolve this, but if the problem remains, manual offsets to the automatically determined line height can be specified in the constructor. + +```cpp +// -2 px of padding above, +1 px of padding below +InkHUD::AppletFont(FreeSans9pt7b, ASCII, -2, 1); +``` diff --git a/variants/ELECROW-ThinkNode-M1/nicheGraphics.h b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h index f68ac9edd..c2c351925 100644 --- a/variants/ELECROW-ThinkNode-M1/nicheGraphics.h +++ b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h @@ -22,10 +22,6 @@ #include "graphics/niche/Drivers/EInk/GDEY0154D67.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; @@ -33,14 +29,13 @@ void setupNicheGraphics() // SPI // ----------------------------- - // For NRF52 platforms, SPI pins are defined in variant.h, not passed to begin() + // For NRF52 platforms, SPI pins are defined in variant.h SPI1.begin(); - // Driver + // E-Ink Driver // ----------------------------- - // Use E-Ink driver - Drivers::EInk *driver = new Drivers::GDEY0154D67; // Todo: confirm display model + Drivers::EInk *driver = new Drivers::GDEY0154D67; driver->begin(&SPI1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); // InkHUD @@ -48,7 +43,7 @@ void setupNicheGraphics() InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update @@ -57,33 +52,27 @@ void setupNicheGraphics() // Currently set to the values given by Elecrow for EInkDynamicDisplay. inkhud->setDisplayResilience(10, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // Two applets side-by-side - inkhud->persistence->settings.rotation = 0; // To be confirmed? inkhud->persistence->settings.optionalFeatures.batteryIcon = true; // Device definitely has a battery - // Setup backlight - // Note: button mapping for this configured further down + // Setup backlight controller + // Note: button is attached further down Drivers::LatchingBacklight *backlight = Drivers::LatchingBacklight::getInstance(); backlight->setPin(PIN_EINK_EN); // Pick applets // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, no autoshow, default on tile 0 // Start running InkHUD @@ -94,25 +83,25 @@ void setupNicheGraphics() Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component - // As labeled on Elecrow diagram: https://www.elecrow.com/download/product/CIL12901M/ThinkNode-M1_User_Manual.pdf - constexpr uint8_t PAGE_TURN_BUTTON = 0; - constexpr uint8_t FUNCTION_BUTTON = 1; + // Elecrow diagram: https://www.elecrow.com/download/product/CIL12901M/ThinkNode-M1_User_Manual.pdf - // Setup the main user button - buttons->setWiring(PAGE_TURN_BUTTON, PIN_BUTTON2); - buttons->setTiming(PAGE_TURN_BUTTON, 50, 500); // Todo: confirm 50ms is adequate debounce - buttons->setHandlerShortPress(PAGE_TURN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(PAGE_TURN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + // #0: Main User Button + // Labeled "Page Turn Button" by manual + buttons->setWiring(0, PIN_BUTTON2); + buttons->setTiming(0, 50, 500); // Todo: confirm 50ms is adequate debounce + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); - // Setup the aux button - // Initial testing only: mapped to the backlight + // #1: Aux Button + // Labeled "Function Button" by manual // Todo: additional features - buttons->setWiring(FUNCTION_BUTTON, PIN_BUTTON1); - buttons->setTiming(FUNCTION_BUTTON, 50, 500); // 500ms before latch - buttons->setHandlerDown(FUNCTION_BUTTON, [backlight]() { backlight->peek(); }); - buttons->setHandlerLongPress(FUNCTION_BUTTON, [backlight]() { backlight->latch(); }); - buttons->setHandlerShortPress(FUNCTION_BUTTON, [backlight]() { backlight->off(); }); + buttons->setWiring(1, PIN_BUTTON1); + buttons->setTiming(1, 50, 500); // 500ms before latch + buttons->setHandlerDown(1, [backlight]() { backlight->peek(); }); + buttons->setHandlerLongPress(1, [backlight]() { backlight->latch(); }); + buttons->setHandlerShortPress(1, [backlight]() { backlight->off(); }); + // Begin handling button events buttons->start(); } diff --git a/variants/heltec_mesh_pocket/nicheGraphics.h b/variants/heltec_mesh_pocket/nicheGraphics.h index b697faa57..271a35d6d 100644 --- a/variants/heltec_mesh_pocket/nicheGraphics.h +++ b/variants/heltec_mesh_pocket/nicheGraphics.h @@ -16,54 +16,42 @@ #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; // SPI // ----------------------------- - SPIClass *spi1 = &SPI1; - spi1->begin(); - // Display is connected to SPI1 + + // For NRF52 platforms, SPI pins are defined in variant.h + SPI1.begin(); // E-Ink Driver // ----------------------------- - // Use E-Ink driver + Drivers::EInk *driver = new Drivers::LCMEN2R13ECC1; - driver->begin(spi1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); + driver->begin(&SPI1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); // InkHUD // ---------------------------- InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(10, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? @@ -72,15 +60,14 @@ void setupNicheGraphics() inkhud->persistence->settings.optionalMenuItems.nextTile = true; // Pick applets + // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, no autoshow, default on tile 0 // Start running InkHUD inkhud->begin(); @@ -89,18 +76,13 @@ void setupNicheGraphics() // -------------------------- Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component - constexpr uint8_t MAIN_BUTTON = 0; - // constexpr uint8_t AUX_BUTTON = 1; - // Setup the main user button - buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); - buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + // #0: Main User Button + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); - // Setup the aux button - // Bonus feature of VME213 - // buttons->setWiring(AUX_BUTTON, BUTTON_PIN_SECONDARY); - // buttons->setHandlerShortPress(AUX_BUTTON, []() { InkHUD::InkHUD::getInstance()->nextTile(); }); + // Begin handling button events buttons->start(); } diff --git a/variants/heltec_vision_master_e213/nicheGraphics.h b/variants/heltec_vision_master_e213/nicheGraphics.h index d6983bafe..7eccb2955 100644 --- a/variants/heltec_vision_master_e213/nicheGraphics.h +++ b/variants/heltec_vision_master_e213/nicheGraphics.h @@ -16,18 +16,11 @@ #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/LCMEN2R13EFC1.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; @@ -42,7 +35,6 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - // Use E-Ink driver Drivers::EInk *driver = new Drivers::LCMEN213EFC1; driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); @@ -51,21 +43,16 @@ void setupNicheGraphics() InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(10, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? @@ -74,15 +61,14 @@ void setupNicheGraphics() inkhud->persistence->settings.optionalMenuItems.nextTile = false; // Behavior handled by aux button instead // Pick applets + // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); // Start running InkHUD inkhud->begin(); @@ -91,18 +77,17 @@ void setupNicheGraphics() // -------------------------- Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component - constexpr uint8_t MAIN_BUTTON = 0; - constexpr uint8_t AUX_BUTTON = 1; - // Setup the main user button - buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); - buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + // #0: Main User Button + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); - // Setup the aux button - // Bonus feature of VME213 - buttons->setWiring(AUX_BUTTON, BUTTON_PIN_SECONDARY); - buttons->setHandlerShortPress(AUX_BUTTON, []() { InkHUD::InkHUD::getInstance()->nextTile(); }); + // #1: Aux Button + buttons->setWiring(1, BUTTON_PIN_SECONDARY); + buttons->setHandlerShortPress(1, [inkhud]() { inkhud->nextTile(); }); + + // Begin handling button events buttons->start(); } diff --git a/variants/heltec_vision_master_e290/nicheGraphics.h b/variants/heltec_vision_master_e290/nicheGraphics.h index c2f26c7ff..af78df746 100644 --- a/variants/heltec_vision_master_e290/nicheGraphics.h +++ b/variants/heltec_vision_master_e290/nicheGraphics.h @@ -29,18 +29,11 @@ Different NicheGraphics UIs and different hardware variants will each have their #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/DEPG0290BNS800.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; @@ -55,7 +48,6 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - // Use E-Ink driver Drivers::EInk *driver = new Drivers::DEPG0290BNS800; driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY); @@ -64,21 +56,16 @@ void setupNicheGraphics() InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(7, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? @@ -87,22 +74,14 @@ void setupNicheGraphics() inkhud->persistence->settings.optionalMenuItems.nextTile = false; // Behavior handled by aux button instead // Pick applets - - // Order of applets determines priority of "auto-show" feature. - // Optional arguments for default state: - // - is activated? - // - is autoshown? - // - is foreground on a specific tile (index)? - + // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); // Start running InkHUD inkhud->begin(); @@ -112,16 +91,16 @@ void setupNicheGraphics() Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // A shared NicheGraphics component - // Setup the main user button (0) + // #0: Main User Button buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); - buttons->setHandlerShortPress(0, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(0, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); - // Setup the aux button (1) - // Bonus feature of VME290 + // #1: Aux Button buttons->setWiring(1, BUTTON_PIN_SECONDARY); - buttons->setHandlerShortPress(1, []() { InkHUD::InkHUD::getInstance()->nextTile(); }); + buttons->setHandlerShortPress(1, [inkhud]() { inkhud->nextTile(); }); + // Begin handling button events buttons->start(); } diff --git a/variants/heltec_wireless_paper/nicheGraphics.h b/variants/heltec_wireless_paper/nicheGraphics.h index 5e938fa64..c8994b7f1 100644 --- a/variants/heltec_wireless_paper/nicheGraphics.h +++ b/variants/heltec_wireless_paper/nicheGraphics.h @@ -16,18 +16,11 @@ #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/LCMEN2R13EFC1.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; @@ -42,7 +35,6 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - // Use E-Ink driver Drivers::EInk *driver = new Drivers::LCMEN213EFC1; driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); @@ -51,21 +43,16 @@ void setupNicheGraphics() InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(10, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? @@ -73,15 +60,14 @@ void setupNicheGraphics() inkhud->persistence->settings.userTiles.count = 1; // One tile only by default, keep things simple for new users // Pick applets + // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); // Start running InkHUD inkhud->begin(); @@ -90,15 +76,15 @@ void setupNicheGraphics() // -------------------------- Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component - constexpr uint8_t MAIN_BUTTON = 0; - // Setup the main user button - buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); - buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + // #0: Main User Button + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); // No aux button on this board + // Begin handling button events buttons->start(); } diff --git a/variants/t-echo/nicheGraphics.h b/variants/t-echo/nicheGraphics.h index af310db25..03185cf5b 100644 --- a/variants/t-echo/nicheGraphics.h +++ b/variants/t-echo/nicheGraphics.h @@ -16,19 +16,12 @@ #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/Backlight/LatchingBacklight.h" #include "graphics/niche/Drivers/EInk/GDEY0154D67.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - // Special case - fix T-Echo's touch button // ---------------------------------------- // On a handful of T-Echos, LoRa TX triggers the capacitive touch @@ -42,37 +35,30 @@ void setupNicheGraphics() // SPI // ----------------------------- - // For NRF52 platforms, SPI pins are defined in variant.h, not passed to begin() - SPIClass *inkSPI = &SPI1; - inkSPI->begin(); + // For NRF52 platforms, SPI pins are defined in variant.h + SPI1.begin(); - // Driver + // E-Ink Driver // ----------------------------- - // Use E-Ink driver Drivers::EInk *driver = new Drivers::GDEY0154D67; - driver->begin(inkSPI, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); + driver->begin(&SPI1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); // InkHUD // ---------------------------- InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); - // Set the driver + // Set the E-Ink driver inkhud->setDriver(driver); // Set how many FAST updates per FULL update // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(20, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // Two applets side-by-side @@ -80,22 +66,20 @@ void setupNicheGraphics() inkhud->persistence->settings.optionalFeatures.batteryIcon = true; // Device definitely has a battery inkhud->persistence->settings.optionalMenuItems.backlight = true; // Until proves capacitive button works by touching it - // Setup backlight - // Note: AUX button behavior configured further down + // Setup backlight controller + // Note: AUX button attached further down Drivers::LatchingBacklight *backlight = Drivers::LatchingBacklight::getInstance(); backlight->setPin(PIN_EINK_EN); // Pick applets // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, no autoshow, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - + inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, no autoshow, default on tile 0 // Start running InkHUD inkhud->begin(); @@ -105,22 +89,19 @@ void setupNicheGraphics() Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component - // (To improve code readability only) - constexpr uint8_t MAIN_BUTTON = 0; - constexpr uint8_t TOUCH_BUTTON = 1; + // #0: Main User Button + buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin()); + buttons->setTiming(0, 75, 500); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); - // Setup the main user button - buttons->setWiring(MAIN_BUTTON, Inputs::TwoButton::getUserButtonPin()); - buttons->setTiming(MAIN_BUTTON, 75, 500); - buttons->setHandlerShortPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(MAIN_BUTTON, []() { InkHUD::InkHUD::getInstance()->longpress(); }); - - // Setup the capacitive touch button + // #1: Aux Button (Capacitive Touch Button) // - short: momentary backlight // - long: latch backlight on - buttons->setWiring(TOUCH_BUTTON, PIN_BUTTON_TOUCH); - buttons->setTiming(TOUCH_BUTTON, 50, 5000); // 5 seconds before latch - limited by T-Echo's capacitive touch IC - buttons->setHandlerDown(TOUCH_BUTTON, [backlight]() { + buttons->setWiring(1, PIN_BUTTON_TOUCH); + buttons->setTiming(1, 50, 5000); // 5 seconds before latch - limited by T-Echo's capacitive touch IC + + buttons->setHandlerDown(1, [inkhud, backlight]() { // Discard the button press if radio is active // Rare hardware fault: LoRa activity triggers touch button if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending()) @@ -131,10 +112,11 @@ void setupNicheGraphics() // Handler has run, which confirms touch button wasn't removed as part of DIY build. // No longer need the fallback backlight toggle in menu. - InkHUD::InkHUD::getInstance()->persistence->settings.optionalMenuItems.backlight = false; + inkhud->persistence->settings.optionalMenuItems.backlight = false; }); - buttons->setHandlerLongPress(TOUCH_BUTTON, [backlight]() { backlight->latch(); }); - buttons->setHandlerShortPress(TOUCH_BUTTON, [backlight]() { backlight->off(); }); + + buttons->setHandlerLongPress(1, [backlight]() { backlight->latch(); }); + buttons->setHandlerShortPress(1, [backlight]() { backlight->off(); }); // Begin handling button events buttons->start(); diff --git a/variants/tlora_t3s3_epaper/nicheGraphics.h b/variants/tlora_t3s3_epaper/nicheGraphics.h index 55bb9a203..5184037e8 100644 --- a/variants/tlora_t3s3_epaper/nicheGraphics.h +++ b/variants/tlora_t3s3_epaper/nicheGraphics.h @@ -16,18 +16,11 @@ #include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" #include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/BasicExample/BasicExampleApplet.h" -// #include "graphics/niche/InkHUD/Applets/Examples/NewMsgExample/NewMsgExampleApplet.h" - // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/DEPG0213BNS800.h" #include "graphics/niche/Inputs/TwoButton.h" -#include "graphics/niche/Fonts/FreeSans6pt7b.h" -#include "graphics/niche/Fonts/FreeSans6pt8bCyrillic.h" -#include - void setupNicheGraphics() { using namespace NicheGraphics; @@ -42,7 +35,6 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - // Use E-Ink driver Drivers::EInk *driver = new Drivers::DEPG0213BNS800; driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); @@ -58,14 +50,9 @@ void setupNicheGraphics() // Set how unhealthy additional FAST updates beyond this number are inkhud->setDisplayResilience(15, 1.5); - // Prepare fonts - InkHUD::Applet::fontLarge = InkHUD::AppletFont(FreeSans9pt7b); - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt7b); - /* - // Font localization demo: Cyrillic - InkHUD::Applet::fontSmall = InkHUD::AppletFont(FreeSans6pt8bCyrillic); - InkHUD::Applet::fontSmall.addSubstitutionsWin1251(); - */ + // Select fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; // Customize default settings inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? @@ -73,15 +60,14 @@ void setupNicheGraphics() inkhud->persistence->settings.userTiles.count = 1; // One tile only by default, keep things simple for new users // Pick applets + // Note: order of applets determines priority of "auto-show" feature inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown - inkhud->addApplet("DMs", new InkHUD::DMApplet); // Inactive - inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // Inactive - inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // Inactive + inkhud->addApplet("DMs", new InkHUD::DMApplet); // - + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); // - + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); // - inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated - inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // Inactive + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); // - inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 - // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); - // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); // Start running InkHUD inkhud->begin(); @@ -93,8 +79,8 @@ void setupNicheGraphics() // Setup the main user button buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin(), true); - buttons->setHandlerShortPress(0, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); - buttons->setHandlerLongPress(0, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); }); + buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); }); buttons->start(); } From beba1b4882391f841fa18495a8e3db1ead279745 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 22 May 2025 20:33:46 -0500 Subject: [PATCH 195/238] Added map report precision bounds (#6862) * Added map report precision bounds * Log warning * Precision range should be 12-15 * Missed commit * Update tests * That method was renamed * Removed now-defunct test call * Remove defunct test --- src/mqtt/MQTT.cpp | 29 +++++++++++++++-------------- test/test_mqtt/MQTT.cpp | 29 +++-------------------------- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 713077272..dca8a3b44 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -773,15 +773,20 @@ void MQTT::perhapsReportToMap() !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly())) return; + // Coerce the map position precision to be within the valid range + // This removes obtusely large radius and privacy problematic ones from the map + if (map_position_precision < 12 || map_position_precision > 15) { + LOG_WARN("MQTT Map report position precision %u is out of range, using default %u", map_position_precision, + default_map_position_precision); + map_position_precision = default_map_position_precision; + } + if (Throttle::isWithinTimespanMs(last_report_to_map, map_publish_interval_msecs)) return; - if (map_position_precision == 0 || (localPosition.latitude_i == 0 && localPosition.longitude_i == 0)) { + if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) { last_report_to_map = millis(); - if (map_position_precision == 0) - LOG_WARN("MQTT Map report enabled, but precision is 0"); - if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) - LOG_WARN("MQTT Map report enabled, but no position available"); + LOG_WARN("MQTT Map report enabled, but no position available"); return; } @@ -805,15 +810,11 @@ void MQTT::perhapsReportToMap() mapReport.has_opted_report_location = true; // Set position with precision (same as in PositionModule) - if (map_position_precision < 32 && map_position_precision > 0) { - mapReport.latitude_i = localPosition.latitude_i & (UINT32_MAX << (32 - map_position_precision)); - mapReport.longitude_i = localPosition.longitude_i & (UINT32_MAX << (32 - map_position_precision)); - mapReport.latitude_i += (1 << (31 - map_position_precision)); - mapReport.longitude_i += (1 << (31 - map_position_precision)); - } else { - mapReport.latitude_i = localPosition.latitude_i; - mapReport.longitude_i = localPosition.longitude_i; - } + mapReport.latitude_i = localPosition.latitude_i & (UINT32_MAX << (32 - map_position_precision)); + mapReport.longitude_i = localPosition.longitude_i & (UINT32_MAX << (32 - map_position_precision)); + mapReport.latitude_i += (1 << (31 - map_position_precision)); + mapReport.longitude_i += (1 << (31 - map_position_precision)); + mapReport.altitude = localPosition.altitude; mapReport.position_precision = map_position_precision; diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index c1f5da358..8047079ba 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -708,42 +708,21 @@ void test_reportToMapDefaultImprecise(void) TEST_ASSERT_EQUAL(1, pubsub->published_.size()); const auto &[topic, payload] = pubsub->published_.front(); TEST_ASSERT_EQUAL_STRING("msh/2/map/", topic.c_str()); - verifyLatLong(std::get(payload), 70123520, 30015488); -} - -// Precise location is reported when configured. -void test_reportToMapPrecise(void) -{ - unitTest->reportToMap(/*precision=*/32); - - TEST_ASSERT_EQUAL(1, pubsub->published_.size()); - const auto &[topic, payload] = pubsub->published_.front(); - TEST_ASSERT_EQUAL_STRING("msh/2/map/", topic.c_str()); - verifyLatLong(std::get(payload), localPosition.latitude_i, localPosition.longitude_i); } // Location is sent over the phone proxy. -void test_reportToMapPreciseProxied(void) +void test_reportToMapImpreciseProxied(void) { moduleConfig.mqtt.proxy_to_client_enabled = true; MQTTUnitTest::restart(); - unitTest->reportToMap(/*precision=*/32); + unitTest->reportToMap(/*precision=*/14); TEST_ASSERT_EQUAL(1, mockMeshService->messages_.size()); const meshtastic_MqttClientProxyMessage &message = mockMeshService->messages_.front(); TEST_ASSERT_EQUAL_STRING("msh/2/map/", message.topic); TEST_ASSERT_EQUAL(meshtastic_MqttClientProxyMessage_data_tag, message.which_payload_variant); const DecodedServiceEnvelope env(message.payload_variant.data.bytes, message.payload_variant.data.size); - verifyLatLong(env, localPosition.latitude_i, localPosition.longitude_i); -} - -// No location is reported when the precision is invalid. -void test_reportToMapInvalidPrecision(void) -{ - unitTest->reportToMap(/*precision=*/0); - - TEST_ASSERT_TRUE(pubsub->published_.empty()); } // isUsingDefaultServer returns true when using the default server. @@ -920,9 +899,7 @@ void setup() RUN_TEST(test_publishTextMessageDirect); RUN_TEST(test_publishTextMessageWithProxy); RUN_TEST(test_reportToMapDefaultImprecise); - RUN_TEST(test_reportToMapPrecise); - RUN_TEST(test_reportToMapPreciseProxied); - RUN_TEST(test_reportToMapInvalidPrecision); + RUN_TEST(test_reportToMapImpreciseProxied); RUN_TEST(test_usingDefaultServer); RUN_TEST(test_usingDefaultServerWithPort); RUN_TEST(test_usingDefaultServerWithInvalidPort); From c01db9881983200e2fc97fbf726a2e5f1f6fa2be Mon Sep 17 00:00:00 2001 From: dylanli Date: Fri, 23 May 2025 21:04:17 +0800 Subject: [PATCH 196/238] update seeed solar node led pin (#6871) --- variants/seeed_solar_node/variant.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/variants/seeed_solar_node/variant.h b/variants/seeed_solar_node/variant.h index 86682302b..30d5c5888 100644 --- a/variants/seeed_solar_node/variant.h +++ b/variants/seeed_solar_node/variant.h @@ -20,8 +20,8 @@ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // LEDs // LEDs -#define PIN_LED1 (11) // LED P1.15 -#define PIN_LED2 (12) // +#define PIN_LED1 (12) // LED P1.15 +#define PIN_LED2 (11) // #define LED_BUILTIN PIN_LED1 #define LED_CONN PIN_LED2 @@ -154,4 +154,4 @@ extern "C" { } #endif -#endif // _SEEED_SOLAR_NODE_H_ \ No newline at end of file +#endif // _SEEED_SOLAR_NODE_H_ From 3aed7b4190fb98906715c2448e62401cd174d1d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 15:51:26 +0200 Subject: [PATCH 197/238] Update Adafruit PM25 AQI Sensor to v2 (#6778) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ae3cbd53b..458aabed2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -132,7 +132,7 @@ lib_deps = # renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219 adafruit/Adafruit INA219@1.2.3 # renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor - adafruit/Adafruit PM25 AQI Sensor@1.2.0 + adafruit/Adafruit PM25 AQI Sensor@2.0.0 # renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050 adafruit/Adafruit MPU6050@2.2.6 # renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH From 067d01b8324071ef0146a6d109ea66e3afe92947 Mon Sep 17 00:00:00 2001 From: Austin Date: Fri, 23 May 2025 16:35:13 -0400 Subject: [PATCH 198/238] Bosch bsec2: Switch back to official releases (#6870) --- platformio.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 458aabed2..7502de0d7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -147,8 +147,6 @@ lib_deps = emotibit/EmotiBit MLX90632@1.0.8 # renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library adafruit/Adafruit MLX90614 Library@2.1.5 - # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library - boschsensortec/BME68x Sensor Library@1.2.40408 # renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221 https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip # renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass @@ -185,7 +183,9 @@ lib_deps = sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 ClosedCube OPT3001@1.1.2 - # renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script - https://github.com/meshtastic/Bosch-BSEC2-Library/archive/e16952dfe5addd4287e1eb8c4f6ecac0fa3dd3de.zip + # renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2 + boschsensortec/bsec2@1.10.2610 + # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library + boschsensortec/BME68x Sensor Library@1.3.40408 # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip From 2c9e1694514961791f93dca91ce857822f44d53a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 24 May 2025 11:33:21 +0200 Subject: [PATCH 199/238] Update meshtastic/device-ui digest to 0e9bb79 (#6880) fix bluetooth fixedPin during restart (#135) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 7502de0d7..836b723af 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/405ca495322b7dc3b61f7588d28267d49b2ebc38.zip + https://github.com/meshtastic/device-ui/archive/0e9bb792bb4b015b487397427781eda2767c87e6.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 30e83d36b7474159524952bdef83f5e7a345a582 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 24 May 2025 19:55:19 -0500 Subject: [PATCH 200/238] Update meshtastic/device-ui digest to 2fba9de (#6882) 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 836b723af..c1012c810 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/0e9bb792bb4b015b487397427781eda2767c87e6.zip + https://github.com/meshtastic/device-ui/archive/2fba9def30b52bbfd13cc5b76f61f257428325e7.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 9b69c2a9af7f950c825869000d908da17a12dd33 Mon Sep 17 00:00:00 2001 From: Chiho Sin Date: Sun, 25 May 2025 19:08:41 +0800 Subject: [PATCH 201/238] graphics: Add GDEY0213B74 E-Ink display driver (#6879) Implement the GDEY0213B74 driver with configuration methods for scanning, waveform, update sequence, and polling for refresh completion. This driver supports both fast and full update types for the 2.13 inch E-Ink display. Signed-off-by: ChihoSin chihosin@icloud.com Signed-off-by: ChihoSin chihosin@icloud.com --- .../niche/Drivers/EInk/GDEY0213B74.cpp | 61 +++++++++++++++++++ src/graphics/niche/Drivers/EInk/GDEY0213B74.h | 42 +++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp create mode 100644 src/graphics/niche/Drivers/EInk/GDEY0213B74.h diff --git a/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp new file mode 100644 index 000000000..a0ff63258 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp @@ -0,0 +1,61 @@ +#include "./GDEY0213B74.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +using namespace NicheGraphics::Drivers; + +// Map the display controller IC's output to the connected panel +void GDEY0213B74::configScanning() +{ + // "Driver output control" + sendCommand(0x01); + sendData(0xF9); + sendData(0x00); + sendData(0x00); + + // To-do: delete this method? + // Values set here might be redundant: F9, 00, 00 seems to be default +} + +// Specify which information is used to control the sequence of voltages applied to move the pixels +// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from +// the controller IC's OTP memory, when the update procedure begins. +void GDEY0213B74::configWaveform() +{ + sendCommand(0x3C); // Border waveform: + sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white) + + sendCommand(0x18); // Temperature sensor: + sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform +} + +void GDEY0213B74::configUpdateSequence() +{ + switch (updateType) { + case FAST: + sendCommand(0x22); // Set "update sequence" + sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh" + break; + + case FULL: + default: + sendCommand(0x22); // Set "update sequence" + sendData(0xF7); // Will load LUT from OTP memory + break; + } +} + +// Once the refresh operation has been started, +// begin periodically polling the display to check for completion, using the normal Meshtastic threading code +// Only used when refresh is "async" +void GDEY0213B74::detachFromUpdate() +{ + switch (updateType) { + case FAST: + return beginPolling(50, 500); // At least 500ms for fast refresh + case FULL: + default: + return beginPolling(100, 2000); // At least 2 seconds for full refresh + } +} +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/GDEY0213B74.h b/src/graphics/niche/Drivers/EInk/GDEY0213B74.h new file mode 100644 index 000000000..2212fe92a --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/GDEY0213B74.h @@ -0,0 +1,42 @@ +/* + +E-Ink display driver + - GDEY0213B74 + - Manufacturer: Goodisplay + - Size: 2.13 inch + - Resolution: 250px x 122px + - Flex connector marking: FPC-A002 + +*/ + +#pragma once + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +#include "configuration.h" + +#include "./SSD16XX.h" + +namespace NicheGraphics::Drivers +{ +class GDEY0213B74 : public SSD16XX +{ + // Display properties + private: + static constexpr uint32_t width = 122; + static constexpr uint32_t height = 250; + static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); + + public: + GDEY0213B74() : SSD16XX(width, height, supported) {} + + protected: + virtual void configScanning() override; + virtual void configWaveform() override; + virtual void configUpdateSequence() override; + void detachFromUpdate() override; +}; + +} // namespace NicheGraphics::Drivers + +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file From e29588d2e20acde737dc15e6137956efc72e7234 Mon Sep 17 00:00:00 2001 From: Andrew Yong Date: Sun, 25 May 2025 18:26:31 +0700 Subject: [PATCH 202/238] feat(RadioInterface): Tx power gain calculation rework (#6796) - Rename REGULATORY_GAIN_LORA to TX_GAIN_LORA - Move gain-based Tx power clamping from RadioInterface::applyModemConfig() to RadioInterface::limitPower() - User-configured Tx power now matches the Tx power out of the device connector - Re-order [LoRa Chip]Interface.cpp limitPower() to take place before the final Tx power clamping so we clamp based on the pre-PA Tx power rather than user-configured Tx power Tested on XIAO BLE variant. Signed-off-by: Andrew Yong Co-authored-by: Ben Meadors --- src/configuration.h | 8 ++++---- src/mesh/LR11x0Interface.cpp | 4 ++-- src/mesh/RF95Interface.cpp | 4 ++-- src/mesh/RadioInterface.cpp | 11 ++++++++--- src/mesh/STM32WLE5JCInterface.cpp | 4 ++-- src/mesh/SX126xInterface.cpp | 4 ++-- src/mesh/SX128xInterface.cpp | 4 ++-- variants/xiao_ble/variant.h | 4 ++-- 8 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index d319ddb0a..5f6930646 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -80,10 +80,10 @@ along with this program. If not, see . // Override user saved region, for producing region-locked builds // #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923 -// Total system gain in dBm to subtract from Tx power to remain within regulatory ERP limit for non-licensed operators -// This value should be set in variant.h and is PA gain + antenna gain (if system ships with an antenna) -#ifndef REGULATORY_GAIN_LORA -#define REGULATORY_GAIN_LORA 0 +// Total system gain in dBm to subtract from Tx power to remain within regulatory and Tx PA limits +// This value should be set in variant.h and is PA gain + antenna gain (if variant has a non-removable antenna) +#ifndef TX_GAIN_LORA +#define TX_GAIN_LORA 0 #endif // ----------------------------------------------------------------------------- diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index aecc8f722..8cc05994c 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -71,6 +71,8 @@ template bool LR11x0Interface::init() RadioLibInterface::init(); + limitPower(); + if (power > LR1110_MAX_POWER) // Clamp power to maximum defined level power = LR1110_MAX_POWER; @@ -80,8 +82,6 @@ template bool LR11x0Interface::init() preambleLength = 12; // 12 is the default for operation above 2GHz } - limitPower(); - #ifdef LR11X0_RF_SWITCH_SUBGHZ pinMode(LR11X0_RF_SWITCH_SUBGHZ, OUTPUT); digitalWrite(LR11X0_RF_SWITCH_SUBGHZ, getFreq() < 1e9 ? HIGH : LOW); diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 1dfc72708..943a79a5f 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -122,11 +122,11 @@ bool RF95Interface::init() power = dacDbValues.db; #endif + limitPower(); + if (power > RF95_MAX_POWER) // This chip has lower power limits than some power = RF95_MAX_POWER; - limitPower(); - iface = lora = new RadioLibRF95(&module); #ifdef RF95_TCXO diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 86903153b..06398e6c3 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -528,8 +528,8 @@ void RadioInterface::applyModemConfig() power = loraConfig.tx_power; - if ((power == 0) || ((power + REGULATORY_GAIN_LORA > myRegion->powerLimit) && !devicestate.owner.is_licensed)) - power = myRegion->powerLimit - REGULATORY_GAIN_LORA; + if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed)) + power = myRegion->powerLimit; if (power == 0) power = 17; // Default to this power level if we don't have a valid regional power limit (powerLimit of myRegion defaults @@ -616,7 +616,12 @@ void RadioInterface::limitPower() power = maxPower; } - LOG_INFO("Set radio: final power level=%d", power); + if (TX_GAIN_LORA > 0) { + LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA); + power -= TX_GAIN_LORA; + } + + LOG_INFO("Final Tx power: %d dBm", power); } void RadioInterface::deliverToReceiver(meshtastic_MeshPacket *p) diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp index 6a340dd28..3c8bf89c3 100644 --- a/src/mesh/STM32WLE5JCInterface.cpp +++ b/src/mesh/STM32WLE5JCInterface.cpp @@ -25,11 +25,11 @@ bool STM32WLE5JCInterface::init() lora.setRfSwitchTable(rfswitch_pins, rfswitch_table); + limitPower(); + if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some power = STM32WLx_MAX_POWER; - limitPower(); - int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage); LOG_INFO("STM32WLx init result %d", res); diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index c867466b7..e5ecd9302 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -69,11 +69,11 @@ template bool SX126xInterface::init() RadioLibInterface::init(); + limitPower(); + if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level power = SX126X_MAX_POWER; - limitPower(); - int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO); // \todo Display actual typename of the adapter, not just `SX126x` LOG_INFO("SX126x init result %d", res); diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 23a023d3f..2b17543fc 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -62,11 +62,11 @@ template bool SX128xInterface::init() RadioLibInterface::init(); + limitPower(); + if (power > SX128X_MAX_POWER) // This chip has lower power limits than some power = SX128X_MAX_POWER; - limitPower(); - preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength); diff --git a/variants/xiao_ble/variant.h b/variants/xiao_ble/variant.h index d00f8be89..b46aa96ae 100644 --- a/variants/xiao_ble/variant.h +++ b/variants/xiao_ble/variant.h @@ -145,12 +145,12 @@ static const uint8_t SCK = PIN_SPI_SCK; #ifdef EBYTE_E22_900M30S // 10dB PA gain and 30dB rated output; based on measurements from // https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/E22-900M30S%20power%20output%20testing.txt -#define REGULATORY_GAIN_LORA 7 +#define TX_GAIN_LORA 7 #define SX126X_MAX_POWER 22 #endif #ifdef EBYTE_E22_900M33S // 25dB PA gain and 33dB rated output; based on TX Power Curve from E22-900M33S_UserManual_EN_v1.0.pdf -#define REGULATORY_GAIN_LORA 25 +#define TX_GAIN_LORA 25 #define SX126X_MAX_POWER 8 #endif #endif From d3b16c1e474519b3e51ad8fdc0d04e9ccb848ebd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 06:29:00 -0500 Subject: [PATCH 203/238] Upgrade trunk (#6843) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 79bdf4778..bcb75d550 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,14 +10,14 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.29 + - trufflehog@3.88.32 - yamllint@1.37.1 - bandit@1.8.3 - trivy@0.62.1 - taplo@0.9.3 - - ruff@0.11.9 + - ruff@0.11.10 - isort@6.0.1 - - markdownlint@0.44.0 + - markdownlint@0.45.0 - oxipng@9.1.5 - svgo@3.3.2 - actionlint@1.7.7 From c47bdd11f9b17d1e81ee2377d1ee361e80ea869a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 06:56:21 -0500 Subject: [PATCH 204/238] [create-pull-request] automated change (#6885) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/protobufs b/protobufs index 0b32ce24f..91484534a 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 0b32ce24f029f69635026aec9428b5c8176e2ce1 +Subproject commit 91484534a58cb4da8ab68ac046f1e76fd1936bf7 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 4071c611e..4fa673df8 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -277,6 +277,10 @@ typedef struct _meshtastic_LocalStats { /* Number of times we canceled a packet to be relayed, because someone else did it before us. This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you. */ uint32_t num_tx_relay_canceled; + /* Number of bytes used in the heap */ + uint32_t heap_total_bytes; + /* Number of bytes free in the heap */ + uint32_t heap_free_bytes; } meshtastic_LocalStats; /* Health telemetry metrics */ @@ -374,7 +378,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} #define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} @@ -383,7 +387,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} #define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} @@ -447,6 +451,8 @@ extern "C" { #define meshtastic_LocalStats_num_rx_dupe_tag 9 #define meshtastic_LocalStats_num_tx_relay_tag 10 #define meshtastic_LocalStats_num_tx_relay_canceled_tag 11 +#define meshtastic_LocalStats_heap_total_bytes_tag 12 +#define meshtastic_LocalStats_heap_free_bytes_tag 13 #define meshtastic_HealthMetrics_heart_bpm_tag 1 #define meshtastic_HealthMetrics_spO2_tag 2 #define meshtastic_HealthMetrics_temperature_tag 3 @@ -544,7 +550,9 @@ X(a, STATIC, SINGULAR, UINT32, num_online_nodes, 7) \ X(a, STATIC, SINGULAR, UINT32, num_total_nodes, 8) \ X(a, STATIC, SINGULAR, UINT32, num_rx_dupe, 9) \ X(a, STATIC, SINGULAR, UINT32, num_tx_relay, 10) \ -X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11) +X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11) \ +X(a, STATIC, SINGULAR, UINT32, heap_total_bytes, 12) \ +X(a, STATIC, SINGULAR, UINT32, heap_free_bytes, 13) #define meshtastic_LocalStats_CALLBACK NULL #define meshtastic_LocalStats_DEFAULT NULL @@ -621,7 +629,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 #define meshtastic_HostMetrics_size 264 -#define meshtastic_LocalStats_size 60 +#define meshtastic_LocalStats_size 72 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 #define meshtastic_Telemetry_size 272 From 5fbdf4b6dc5f2b01f380cddd74ba17e156ba7bd3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 07:12:03 -0500 Subject: [PATCH 205/238] chore(deps): update meshtastic/device-ui digest to e63b219 (#6883) 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 c1012c810..fc6c06162 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/2fba9def30b52bbfd13cc5b76f61f257428325e7.zip + https://github.com/meshtastic/device-ui/archive/e63b219e78e9655be10745b4037cefd2c608d258.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 2e72850d99a9d2546d69fe529b3025aed6aec12f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 25 May 2025 07:24:28 -0500 Subject: [PATCH 206/238] Fix is_unmessagable plumbing (#6886) --- src/mesh/TypeConversions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mesh/TypeConversions.cpp b/src/mesh/TypeConversions.cpp index c47a67e68..17cd92851 100644 --- a/src/mesh/TypeConversions.cpp +++ b/src/mesh/TypeConversions.cpp @@ -87,6 +87,8 @@ meshtastic_UserLite TypeConversions::ConvertToUserLite(meshtastic_User user) memcpy(lite.macaddr, user.macaddr, sizeof(lite.macaddr)); memcpy(lite.public_key.bytes, user.public_key.bytes, sizeof(lite.public_key.bytes)); lite.public_key.size = user.public_key.size; + lite.has_is_unmessagable = user.has_is_unmessagable; + lite.is_unmessagable = user.is_unmessagable; return lite; } @@ -103,6 +105,8 @@ meshtastic_User TypeConversions::ConvertToUser(uint32_t nodeNum, meshtastic_User memcpy(user.macaddr, lite.macaddr, sizeof(user.macaddr)); memcpy(user.public_key.bytes, lite.public_key.bytes, sizeof(user.public_key.bytes)); user.public_key.size = lite.public_key.size; + user.has_is_unmessagable = lite.has_is_unmessagable; + user.is_unmessagable = lite.is_unmessagable; return user; } \ No newline at end of file From 7d95b487efb4da5194e4e3ac66905ab18ffff894 Mon Sep 17 00:00:00 2001 From: Michael Cullen Date: Sun, 25 May 2025 14:29:02 +0200 Subject: [PATCH 207/238] Add PCT2075 Temperature Sensor (#6829) This is an I2C temperature sensor. It is intended to be a drop-in compatible sensor for the LM75, however it is more accurate. Co-authored-by: Ben Meadors --- platformio.ini | 2 ++ src/configuration.h | 1 + src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 1 + src/main.cpp | 1 + .../Telemetry/EnvironmentTelemetry.cpp | 13 +++++++ .../Telemetry/Sensor/PCT2075Sensor.cpp | 35 +++++++++++++++++++ src/modules/Telemetry/Sensor/PCT2075Sensor.h | 24 +++++++++++++ 8 files changed, 78 insertions(+) create mode 100644 src/modules/Telemetry/Sensor/PCT2075Sensor.cpp create mode 100644 src/modules/Telemetry/Sensor/PCT2075Sensor.h diff --git a/platformio.ini b/platformio.ini index fc6c06162..d7504e6c5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -161,6 +161,8 @@ lib_deps = sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 + # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/Adafruit PCT2075 + adafruit/Adafruit PCT2075@1.0.5 ; (not included in native / portduino) [environmental_extra] diff --git a/src/configuration.h b/src/configuration.h index 5f6930646..0c23e677d 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -153,6 +153,7 @@ along with this program. If not, see . #define CGRADSENS_ADDR 0x66 #define LTR390UV_ADDR 0x53 #define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418 +#define PCT2075_ADDR 0x37 // ----------------------------------------------------------------------------- // ACCELEROMETER diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index c363db1b5..72184db69 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -71,6 +71,7 @@ class ScanI2C DPS310, LTR390UV, TCA8418KB, + PCT2075, } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 9781cbf56..e2ba78a92 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -434,6 +434,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address); SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address); #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); #endif diff --git a/src/main.cpp b/src/main.cpp index 1e46d9db1..7a11ca2e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -732,6 +732,7 @@ void setup() scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LTR390UV, meshtastic_TelemetrySensorType_LTR390UV); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075); i2cScanner.reset(); #endif diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 56f9d7433..51f076552 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -157,6 +157,13 @@ BMP3XXSensor bmp3xxSensor; NullSensor bmp3xxSensor; #endif +#if __has_include() +#include "Sensor/PCT2075Sensor.h" +PCT2075Sensor pct2075Sensor; +#else +NullSensor pct2075Sensor; +#endif + RCWL9620Sensor rcwl9620Sensor; CGRadSensSensor cgRadSens; #endif @@ -264,6 +271,8 @@ int32_t EnvironmentTelemetryModule::runOnce() result = max17048Sensor.runOnce(); if (cgRadSens.hasSensor()) result = cgRadSens.runOnce(); + if (pct2075Sensor.hasSensor()) + result = pct2075Sensor.runOnce(); // this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the // sensormap here. #ifdef HAS_RAKPROT @@ -595,6 +604,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && cgRadSens.getMetrics(m); hasSensor = true; } + if (pct2075Sensor.hasSensor()) { + valid = valid && pct2075Sensor.getMetrics(m); + hasSensor = true; + } #ifdef HAS_RAKPROT valid = valid && rak9154Sensor.getMetrics(m); hasSensor = true; diff --git a/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp b/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp new file mode 100644 index 000000000..d2b50d983 --- /dev/null +++ b/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp @@ -0,0 +1,35 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "PCT2075Sensor.h" +#include "TelemetrySensor.h" +#include + +PCT2075Sensor::PCT2075Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_PCT2075, "PCT2075") {} + +int32_t PCT2075Sensor::runOnce() +{ + LOG_INFO("Init sensor: %s", sensorName); + if (!hasSensor()) { + return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; + } + + status = pct2075.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second); + + return initI2CSensor(); +} + +void PCT2075Sensor::setup() {} + +bool PCT2075Sensor::getMetrics(meshtastic_Telemetry *measurement) +{ + measurement->variant.environment_metrics.has_temperature = true; + + measurement->variant.environment_metrics.temperature = pct2075.getTemperature(); + + return true; +} + +#endif diff --git a/src/modules/Telemetry/Sensor/PCT2075Sensor.h b/src/modules/Telemetry/Sensor/PCT2075Sensor.h new file mode 100644 index 000000000..842c973d0 --- /dev/null +++ b/src/modules/Telemetry/Sensor/PCT2075Sensor.h @@ -0,0 +1,24 @@ +#pragma once +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include + +class PCT2075Sensor : public TelemetrySensor +{ + private: + Adafruit_PCT2075 pct2075; + + protected: + virtual void setup() override; + + public: + PCT2075Sensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; +}; + +#endif From 75a49d348622ff537c99a0673f8a9b400448eb9d Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 25 May 2025 11:08:56 -0500 Subject: [PATCH 208/238] Add heap metrics to Local stats (#6887) --- src/modules/Telemetry/DeviceTelemetry.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 251608641..43c2dd84c 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -9,6 +9,7 @@ #include "Router.h" #include "configuration.h" #include "main.h" +#include "memGet.h" #include #include #include @@ -133,6 +134,9 @@ meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry() telemetry.variant.local_stats.num_packets_rx_bad = SimRadio::instance->rxBad; telemetry.variant.local_stats.num_tx_relay = SimRadio::instance->txRelay; } +#else + telemetry.variant.local_stats.heap_total_bytes = memGet.getHeapSize(); + telemetry.variant.local_stats.heap_free_bytes = memGet.getFreeHeap(); #endif if (router) { telemetry.variant.local_stats.num_rx_dupe = router->rxDupe; From f223b8a55d1b6a04d2203d43a32bbb880b428af3 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 26 May 2025 06:12:52 +1200 Subject: [PATCH 209/238] Add missing parsing of UTF-8 chars (#6889) --- .../Applets/System/Notification/NotificationApplet.cpp | 4 ++-- .../InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp | 6 +++--- src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp index f9439fab8..ae0836d19 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Notification/NotificationApplet.cpp @@ -213,7 +213,7 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila // Sender id if (node && node->has_user) - text += node->user.short_name; + text += parseShortName(node); else text += hexifyNodeNum(message->sender); @@ -227,7 +227,7 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila // Sender id if (node && node->has_user) - text += node->user.short_name; + text += parseShortName(node); else text += hexifyNodeNum(message->sender); diff --git a/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp index 968775302..17d724aee 100644 --- a/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.cpp @@ -67,13 +67,13 @@ void InkHUD::AllMessageApplet::onRender() } // Sender's id - // - shortname, if available, or + // - short name and long name, if available, or // - node id meshtastic_NodeInfoLite *sender = nodeDB->getMeshNode(message->sender); if (sender && sender->has_user) { - header += sender->user.short_name; + header += parseShortName(sender); // May be last-four of node if unprintable (emoji, etc) header += " ("; - header += sender->user.long_name; + header += parse(sender->user.long_name); header += ")"; } else header += hexifyNodeNum(message->sender); diff --git a/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp b/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp index 3c69495ed..dbf5c08fb 100644 --- a/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/User/DM/DMApplet.cpp @@ -63,13 +63,13 @@ void InkHUD::DMApplet::onRender() } // Sender's id - // - shortname, if available, or + // - shortname and long name, if available, or // - node id meshtastic_NodeInfoLite *sender = nodeDB->getMeshNode(latestMessage->dm.sender); if (sender && sender->has_user) { - header += sender->user.short_name; + header += parseShortName(sender); // May be last-four of node if unprintable (emoji, etc) header += " ("; - header += sender->user.long_name; + header += parse(sender->user.long_name); header += ")"; } else header += hexifyNodeNum(latestMessage->dm.sender); From 106dd087104d67bc77a3f7c075b8baae996ee95d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 16:53:02 -0500 Subject: [PATCH 210/238] automated bumps (#6890) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ debian/changelog | 7 +++++-- version.properties | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 1a7ad284d..30f684fef 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.10 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9 diff --git a/debian/changelog b/debian/changelog index ae27bc3e9..87e3aea9b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -meshtasticd (2.6.9.0) UNRELEASED; urgency=medium +meshtasticd (2.6.10.0) UNRELEASED; urgency=medium [ Austin Lane ] * Initial packaging @@ -13,4 +13,7 @@ meshtasticd (2.6.9.0) UNRELEASED; urgency=medium [ ] * GitHub Actions Automatic version bump - -- Thu, 15 May 2025 11:13:30 +0000 + [ ] + * GitHub Actions Automatic version bump + + -- Sun, 25 May 2025 20:46:49 +0000 diff --git a/version.properties b/version.properties index b0e960697..71de951f1 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 9 +build = 10 From baefda213a0dcb28196ecad4c92170ca6eef773e Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 26 May 2025 07:31:10 -0400 Subject: [PATCH 211/238] Linux: Adjust udev rules for gpio (#6891) --- bin/99-meshtasticd-udev.rules | 5 ++++- debian/meshtasticd.postinst | 7 ++++--- debian/meshtasticd.udev | 5 ++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/99-meshtasticd-udev.rules b/bin/99-meshtasticd-udev.rules index 69a468d7a..1151efafd 100644 --- a/bin/99-meshtasticd-udev.rules +++ b/bin/99-meshtasticd-udev.rules @@ -1,4 +1,7 @@ -# Set spidev ownership to 'spi' group. +# Set spidev ownership to 'spi' group SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" # Allow access to USB CH341 devices SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" +# Set gpio ownership to 'gpio' group +SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660" +SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660" diff --git a/debian/meshtasticd.postinst b/debian/meshtasticd.postinst index 324865718..fe0dbc332 100755 --- a/debian/meshtasticd.postinst +++ b/debian/meshtasticd.postinst @@ -20,16 +20,17 @@ set -e case "$1" in configure|reconfigure) - # create spi group (for udev rules) - # this group already exists on Raspberry Pi OS + # create spi, gpio groups (for udev rules) + # these groups already exist on Raspberry Pi OS getent group spi >/dev/null 2>/dev/null || addgroup --system spi + getent group gpio >/dev/null 2>/dev/null || addgroup --system gpio # create a meshtasticd group and user getent passwd meshtasticd >/dev/null 2>/dev/null || adduser --system --home /var/lib/meshtasticd --no-create-home meshtasticd getent group meshtasticd >/dev/null 2>/dev/null || addgroup --system meshtasticd adduser meshtasticd meshtasticd >/dev/null 2>/dev/null adduser meshtasticd spi >/dev/null 2>/dev/null + adduser meshtasticd gpio >/dev/null 2>/dev/null # add meshtasticd user to appropriate groups (if they exist) - getent group gpio >/dev/null 2>/dev/null && adduser meshtasticd gpio >/dev/null 2>/dev/null getent group plugdev >/dev/null 2>/dev/null && adduser meshtasticd plugdev >/dev/null 2>/dev/null getent group dialout >/dev/null 2>/dev/null && adduser meshtasticd dialout >/dev/null 2>/dev/null getent group i2c >/dev/null 2>/dev/null && adduser meshtasticd i2c >/dev/null 2>/dev/null diff --git a/debian/meshtasticd.udev b/debian/meshtasticd.udev index 69a468d7a..1151efafd 100644 --- a/debian/meshtasticd.udev +++ b/debian/meshtasticd.udev @@ -1,4 +1,7 @@ -# Set spidev ownership to 'spi' group. +# Set spidev ownership to 'spi' group SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" # Allow access to USB CH341 devices SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" +# Set gpio ownership to 'gpio' group +SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660" +SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660" From 138dc89442cce81dc902fd057e2132be372206e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 06:19:35 -0500 Subject: [PATCH 212/238] Upgrade trunk (#6898) Co-authored-by: sachaw <11172820+sachaw@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 bcb75d550..91bdf11cb 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,12 +10,12 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.32 + - trufflehog@3.88.34 - yamllint@1.37.1 - bandit@1.8.3 - trivy@0.62.1 - taplo@0.9.3 - - ruff@0.11.10 + - ruff@0.11.11 - isort@6.0.1 - markdownlint@0.45.0 - oxipng@9.1.5 From 158c88ddef9382acd2cbf4089f18aecb79745f5b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 15:41:35 -0500 Subject: [PATCH 213/238] [create-pull-request] automated change (#6905) Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/admin.pb.cpp | 5 + src/mesh/generated/meshtastic/admin.pb.h | 53 +++++++ src/mesh/generated/meshtastic/config.pb.h | 14 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/mesh.pb.cpp | 12 ++ src/mesh/generated/meshtastic/mesh.pb.h | 129 +++++++++++++++++- src/mesh/generated/meshtastic/portnums.pb.h | 2 + 9 files changed, 209 insertions(+), 12 deletions(-) diff --git a/protobufs b/protobufs index 91484534a..022ea79ba 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 91484534a58cb4da8ab68ac046f1e76fd1936bf7 +Subproject commit 022ea79bad79b70d0bee286cd9184916ab47c1b1 diff --git a/src/mesh/generated/meshtastic/admin.pb.cpp b/src/mesh/generated/meshtastic/admin.pb.cpp index 9bf40870f..a9c82f7c0 100644 --- a/src/mesh/generated/meshtastic/admin.pb.cpp +++ b/src/mesh/generated/meshtastic/admin.pb.cpp @@ -18,6 +18,11 @@ PB_BIND(meshtastic_NodeRemoteHardwarePinsResponse, meshtastic_NodeRemoteHardware PB_BIND(meshtastic_SharedContact, meshtastic_SharedContact, AUTO) +PB_BIND(meshtastic_KeyVerificationAdmin, meshtastic_KeyVerificationAdmin, AUTO) + + + + diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 0a46e6275..2a5fd78b0 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -77,6 +77,19 @@ typedef enum _meshtastic_AdminMessage_BackupLocation { meshtastic_AdminMessage_BackupLocation_SD = 1 } meshtastic_AdminMessage_BackupLocation; +/* Three stages of this request. */ +typedef enum _meshtastic_KeyVerificationAdmin_MessageType { + /* This is the first stage, where a client initiates */ + meshtastic_KeyVerificationAdmin_MessageType_INITIATE_VERIFICATION = 0, + /* After the nonce has been returned over the mesh, the client prompts for the security number + And uses this message to provide it to the node. */ + meshtastic_KeyVerificationAdmin_MessageType_PROVIDE_SECURITY_NUMBER = 1, + /* Once the user has compared the verification message, this message notifies the node. */ + meshtastic_KeyVerificationAdmin_MessageType_DO_VERIFY = 2, + /* This is the cancel path, can be taken at any point */ + meshtastic_KeyVerificationAdmin_MessageType_DO_NOT_VERIFY = 3 +} meshtastic_KeyVerificationAdmin_MessageType; + /* Struct definitions */ /* Parameters for setting up Meshtastic for ameteur radio usage */ typedef struct _meshtastic_HamParameters { @@ -107,6 +120,18 @@ typedef struct _meshtastic_SharedContact { meshtastic_User user; } meshtastic_SharedContact; +/* This message is used by a client to initiate or complete a key verification */ +typedef struct _meshtastic_KeyVerificationAdmin { + meshtastic_KeyVerificationAdmin_MessageType message_type; + /* The nodenum we're requesting */ + uint32_t remote_nodenum; + /* The nonce is used to track the connection */ + uint64_t nonce; + /* The 4 digit code generated by the remote node, and communicated outside the mesh */ + bool has_security_number; + uint32_t security_number; +} meshtastic_KeyVerificationAdmin; + typedef PB_BYTES_ARRAY_T(8) meshtastic_AdminMessage_session_passkey_t; /* This message is handled by the Admin module and is responsible for all settings/channel read/write operations. This message is used to do settings operations to both remote AND local nodes. @@ -212,6 +237,8 @@ typedef struct _meshtastic_AdminMessage { bool commit_edit_settings; /* Add a contact (User) to the nodedb */ meshtastic_SharedContact add_contact; + /* Initiate or respond to a key verification request */ + meshtastic_KeyVerificationAdmin key_verification; /* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ int32_t factory_reset_device; /* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) @@ -253,6 +280,10 @@ extern "C" { #define _meshtastic_AdminMessage_BackupLocation_MAX meshtastic_AdminMessage_BackupLocation_SD #define _meshtastic_AdminMessage_BackupLocation_ARRAYSIZE ((meshtastic_AdminMessage_BackupLocation)(meshtastic_AdminMessage_BackupLocation_SD+1)) +#define _meshtastic_KeyVerificationAdmin_MessageType_MIN meshtastic_KeyVerificationAdmin_MessageType_INITIATE_VERIFICATION +#define _meshtastic_KeyVerificationAdmin_MessageType_MAX meshtastic_KeyVerificationAdmin_MessageType_DO_NOT_VERIFY +#define _meshtastic_KeyVerificationAdmin_MessageType_ARRAYSIZE ((meshtastic_KeyVerificationAdmin_MessageType)(meshtastic_KeyVerificationAdmin_MessageType_DO_NOT_VERIFY+1)) + #define meshtastic_AdminMessage_payload_variant_get_config_request_ENUMTYPE meshtastic_AdminMessage_ConfigType #define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType #define meshtastic_AdminMessage_payload_variant_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation @@ -262,16 +293,20 @@ extern "C" { +#define meshtastic_KeyVerificationAdmin_message_type_ENUMTYPE meshtastic_KeyVerificationAdmin_MessageType + /* Initializer values for message structs */ #define meshtastic_AdminMessage_init_default {0, {0}, {0, {0}}} #define meshtastic_HamParameters_init_default {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} #define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default} +#define meshtastic_KeyVerificationAdmin_init_default {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0} #define meshtastic_AdminMessage_init_zero {0, {0}, {0, {0}}} #define meshtastic_HamParameters_init_zero {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} #define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero} +#define meshtastic_KeyVerificationAdmin_init_zero {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_HamParameters_call_sign_tag 1 @@ -281,6 +316,10 @@ extern "C" { #define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag 1 #define meshtastic_SharedContact_node_num_tag 1 #define meshtastic_SharedContact_user_tag 2 +#define meshtastic_KeyVerificationAdmin_message_type_tag 1 +#define meshtastic_KeyVerificationAdmin_remote_nodenum_tag 2 +#define meshtastic_KeyVerificationAdmin_nonce_tag 3 +#define meshtastic_KeyVerificationAdmin_security_number_tag 4 #define meshtastic_AdminMessage_get_channel_request_tag 1 #define meshtastic_AdminMessage_get_channel_response_tag 2 #define meshtastic_AdminMessage_get_owner_request_tag 3 @@ -326,6 +365,7 @@ extern "C" { #define meshtastic_AdminMessage_begin_edit_settings_tag 64 #define meshtastic_AdminMessage_commit_edit_settings_tag 65 #define meshtastic_AdminMessage_add_contact_tag 66 +#define meshtastic_AdminMessage_key_verification_tag 67 #define meshtastic_AdminMessage_factory_reset_device_tag 94 #define meshtastic_AdminMessage_reboot_ota_seconds_tag 95 #define meshtastic_AdminMessage_exit_simulator_tag 96 @@ -382,6 +422,7 @@ X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_ignored_node,remove_i X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \ X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \ @@ -408,6 +449,7 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101) #define meshtastic_AdminMessage_payload_variant_get_ui_config_response_MSGTYPE meshtastic_DeviceUIConfig #define meshtastic_AdminMessage_payload_variant_store_ui_config_MSGTYPE meshtastic_DeviceUIConfig #define meshtastic_AdminMessage_payload_variant_add_contact_MSGTYPE meshtastic_SharedContact +#define meshtastic_AdminMessage_payload_variant_key_verification_MSGTYPE meshtastic_KeyVerificationAdmin #define meshtastic_HamParameters_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, call_sign, 1) \ @@ -430,21 +472,32 @@ X(a, STATIC, OPTIONAL, MESSAGE, user, 2) #define meshtastic_SharedContact_DEFAULT NULL #define meshtastic_SharedContact_user_MSGTYPE meshtastic_User +#define meshtastic_KeyVerificationAdmin_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, message_type, 1) \ +X(a, STATIC, SINGULAR, UINT32, remote_nodenum, 2) \ +X(a, STATIC, SINGULAR, UINT64, nonce, 3) \ +X(a, STATIC, OPTIONAL, UINT32, security_number, 4) +#define meshtastic_KeyVerificationAdmin_CALLBACK NULL +#define meshtastic_KeyVerificationAdmin_DEFAULT NULL + extern const pb_msgdesc_t meshtastic_AdminMessage_msg; extern const pb_msgdesc_t meshtastic_HamParameters_msg; extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg; extern const pb_msgdesc_t meshtastic_SharedContact_msg; +extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg #define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg #define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg #define meshtastic_SharedContact_fields &meshtastic_SharedContact_msg +#define meshtastic_KeyVerificationAdmin_fields &meshtastic_KeyVerificationAdmin_msg /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size #define meshtastic_AdminMessage_size 511 #define meshtastic_HamParameters_size 31 +#define meshtastic_KeyVerificationAdmin_size 25 #define meshtastic_NodeRemoteHardwarePinsResponse_size 496 #define meshtastic_SharedContact_size 123 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index edcd7b41c..9d7a96dc8 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -441,6 +441,8 @@ typedef struct _meshtastic_Config_NetworkConfig { char rsyslog_server[33]; /* Flags for enabling/disabling network protocols */ uint32_t enabled_protocols; + /* Enable/Disable ipv6 support */ + bool ipv6_enabled; } meshtastic_Config_NetworkConfig; /* Display Config */ @@ -693,7 +695,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 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, 0} -#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0} +#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} #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}, 0, 0} @@ -704,7 +706,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 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, 0} -#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0} +#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} #define meshtastic_Config_LoRaConfig_init_zero {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}, 0, 0} @@ -759,6 +761,7 @@ extern "C" { #define meshtastic_Config_NetworkConfig_ipv4_config_tag 8 #define meshtastic_Config_NetworkConfig_rsyslog_server_tag 9 #define meshtastic_Config_NetworkConfig_enabled_protocols_tag 10 +#define meshtastic_Config_NetworkConfig_ipv6_enabled_tag 11 #define meshtastic_Config_DisplayConfig_screen_on_secs_tag 1 #define meshtastic_Config_DisplayConfig_gps_format_tag 2 #define meshtastic_Config_DisplayConfig_auto_screen_carousel_secs_tag 3 @@ -889,7 +892,8 @@ X(a, STATIC, SINGULAR, BOOL, eth_enabled, 6) \ X(a, STATIC, SINGULAR, UENUM, address_mode, 7) \ X(a, STATIC, OPTIONAL, MESSAGE, ipv4_config, 8) \ X(a, STATIC, SINGULAR, STRING, rsyslog_server, 9) \ -X(a, STATIC, SINGULAR, UINT32, enabled_protocols, 10) +X(a, STATIC, SINGULAR, UINT32, enabled_protocols, 10) \ +X(a, STATIC, SINGULAR, BOOL, ipv6_enabled, 11) #define meshtastic_Config_NetworkConfig_CALLBACK NULL #define meshtastic_Config_NetworkConfig_DEFAULT NULL #define meshtastic_Config_NetworkConfig_ipv4_config_MSGTYPE meshtastic_Config_NetworkConfig_IpV4Config @@ -995,12 +999,12 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg; #define meshtastic_Config_DisplayConfig_size 32 #define meshtastic_Config_LoRaConfig_size 85 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 -#define meshtastic_Config_NetworkConfig_size 202 +#define meshtastic_Config_NetworkConfig_size 204 #define meshtastic_Config_PositionConfig_size 62 #define meshtastic_Config_PowerConfig_size 52 #define meshtastic_Config_SecurityConfig_size 178 #define meshtastic_Config_SessionkeyConfig_size 0 -#define meshtastic_Config_size 205 +#define meshtastic_Config_size 207 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 2436098da..37f99d8b5 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2267 +#define meshtastic_BackupPreferences_size 2269 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1722 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 53d8d7d80..bb2eefc04 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -187,7 +187,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_LocalConfig_size -#define meshtastic_LocalConfig_size 743 +#define meshtastic_LocalConfig_size 745 #define meshtastic_LocalModuleConfig_size 669 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index 6c5c7a4be..11875fadd 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -21,6 +21,9 @@ PB_BIND(meshtastic_Routing, meshtastic_Routing, AUTO) PB_BIND(meshtastic_Data, meshtastic_Data, 2) +PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO) + + PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO) @@ -48,6 +51,15 @@ PB_BIND(meshtastic_FromRadio, meshtastic_FromRadio, 2) PB_BIND(meshtastic_ClientNotification, meshtastic_ClientNotification, 2) +PB_BIND(meshtastic_KeyVerificationNumberInform, meshtastic_KeyVerificationNumberInform, AUTO) + + +PB_BIND(meshtastic_KeyVerificationNumberRequest, meshtastic_KeyVerificationNumberRequest, AUTO) + + +PB_BIND(meshtastic_KeyVerificationFinal, meshtastic_KeyVerificationFinal, AUTO) + + PB_BIND(meshtastic_FileInfo, meshtastic_FileInfo, AUTO) diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index d6816eeef..c1ec607d6 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -247,6 +247,17 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO = 96, /* Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin */ meshtastic_HardwareModel_CROWPANEL = 97, + /* * + Lilygo LINK32 board with sensors */ + meshtastic_HardwareModel_LINK_32 = 98, + /* * + Seeed Tracker L1 */ + meshtastic_HardwareModel_SEEED_TRACKER_L1 = 99, + /* * + Seeed Tracker L1 EINK driver */ + meshtastic_HardwareModel_SEEED_TRACKER_L1_EINK = 100, + /* Reserved ID for future and past use */ + meshtastic_HardwareModel_QWANTZ_TINY_ARMS = 101, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -680,6 +691,19 @@ typedef struct _meshtastic_Data { uint8_t bitfield; } meshtastic_Data; +typedef PB_BYTES_ARRAY_T(32) meshtastic_KeyVerification_hash1_t; +typedef PB_BYTES_ARRAY_T(32) meshtastic_KeyVerification_hash2_t; +/* The actual over-the-mesh message doing KeyVerification */ +typedef struct _meshtastic_KeyVerification { + /* random value Selected by the requesting node */ + uint64_t nonce; + /* The final authoritative hash, only to be sent by NodeA at the end of the handshake */ + meshtastic_KeyVerification_hash1_t hash1; + /* The intermediary hash (actually derived from hash1), + sent from NodeB to NodeA in response to the initial message. */ + meshtastic_KeyVerification_hash2_t hash2; +} meshtastic_KeyVerification; + /* Waypoint message, used to share arbitrary locations across the mesh */ typedef struct _meshtastic_Waypoint { /* Id of the waypoint */ @@ -907,6 +931,24 @@ typedef struct _meshtastic_QueueStatus { uint32_t mesh_packet_id; } meshtastic_QueueStatus; +typedef struct _meshtastic_KeyVerificationNumberInform { + uint64_t nonce; + char remote_longname[40]; + uint32_t security_number; +} meshtastic_KeyVerificationNumberInform; + +typedef struct _meshtastic_KeyVerificationNumberRequest { + uint64_t nonce; + char remote_longname[40]; +} meshtastic_KeyVerificationNumberRequest; + +typedef struct _meshtastic_KeyVerificationFinal { + uint64_t nonce; + char remote_longname[40]; + bool isSender; + char verification_characters[10]; +} meshtastic_KeyVerificationFinal; + /* A notification message from the device to the client To be used for important messages that should to be displayed to the user in the form of push notifications or validation messages when saving @@ -921,6 +963,12 @@ typedef struct _meshtastic_ClientNotification { meshtastic_LogRecord_Level level; /* The message body of the notification */ char message[400]; + pb_size_t which_payload_variant; + union { + meshtastic_KeyVerificationNumberInform key_verification_number_inform; + meshtastic_KeyVerificationNumberRequest key_verification_number_request; + meshtastic_KeyVerificationFinal key_verification_final; + } payload_variant; } meshtastic_ClientNotification; /* Individual File info for the device */ @@ -1183,6 +1231,7 @@ extern "C" { + #define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority #define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed @@ -1196,6 +1245,9 @@ extern "C" { + + + #define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum @@ -1215,6 +1267,7 @@ extern "C" { #define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} +#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} @@ -1223,7 +1276,10 @@ extern "C" { #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} -#define meshtastic_ClientNotification_init_default {false, 0, 0, _meshtastic_LogRecord_Level_MIN, ""} +#define meshtastic_ClientNotification_init_default {false, 0, 0, _meshtastic_LogRecord_Level_MIN, "", 0, {meshtastic_KeyVerificationNumberInform_init_default}} +#define meshtastic_KeyVerificationNumberInform_init_default {0, "", 0} +#define meshtastic_KeyVerificationNumberRequest_init_default {0, ""} +#define meshtastic_KeyVerificationFinal_init_default {0, "", 0, ""} #define meshtastic_FileInfo_init_default {"", 0} #define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}} #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} @@ -1240,6 +1296,7 @@ extern "C" { #define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} +#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} @@ -1248,7 +1305,10 @@ extern "C" { #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} -#define meshtastic_ClientNotification_init_zero {false, 0, 0, _meshtastic_LogRecord_Level_MIN, ""} +#define meshtastic_ClientNotification_init_zero {false, 0, 0, _meshtastic_LogRecord_Level_MIN, "", 0, {meshtastic_KeyVerificationNumberInform_init_zero}} +#define meshtastic_KeyVerificationNumberInform_init_zero {0, "", 0} +#define meshtastic_KeyVerificationNumberRequest_init_zero {0, ""} +#define meshtastic_KeyVerificationFinal_init_zero {0, "", 0, ""} #define meshtastic_FileInfo_init_zero {"", 0} #define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} @@ -1310,6 +1370,9 @@ extern "C" { #define meshtastic_Data_reply_id_tag 7 #define meshtastic_Data_emoji_tag 8 #define meshtastic_Data_bitfield_tag 9 +#define meshtastic_KeyVerification_nonce_tag 1 +#define meshtastic_KeyVerification_hash1_tag 2 +#define meshtastic_KeyVerification_hash2_tag 3 #define meshtastic_Waypoint_id_tag 1 #define meshtastic_Waypoint_latitude_i_tag 2 #define meshtastic_Waypoint_longitude_i_tag 3 @@ -1367,10 +1430,22 @@ extern "C" { #define meshtastic_QueueStatus_free_tag 2 #define meshtastic_QueueStatus_maxlen_tag 3 #define meshtastic_QueueStatus_mesh_packet_id_tag 4 +#define meshtastic_KeyVerificationNumberInform_nonce_tag 1 +#define meshtastic_KeyVerificationNumberInform_remote_longname_tag 2 +#define meshtastic_KeyVerificationNumberInform_security_number_tag 3 +#define meshtastic_KeyVerificationNumberRequest_nonce_tag 1 +#define meshtastic_KeyVerificationNumberRequest_remote_longname_tag 2 +#define meshtastic_KeyVerificationFinal_nonce_tag 1 +#define meshtastic_KeyVerificationFinal_remote_longname_tag 2 +#define meshtastic_KeyVerificationFinal_isSender_tag 3 +#define meshtastic_KeyVerificationFinal_verification_characters_tag 4 #define meshtastic_ClientNotification_reply_id_tag 1 #define meshtastic_ClientNotification_time_tag 2 #define meshtastic_ClientNotification_level_tag 3 #define meshtastic_ClientNotification_message_tag 4 +#define meshtastic_ClientNotification_key_verification_number_inform_tag 11 +#define meshtastic_ClientNotification_key_verification_number_request_tag 12 +#define meshtastic_ClientNotification_key_verification_final_tag 13 #define meshtastic_FileInfo_file_name_tag 1 #define meshtastic_FileInfo_size_bytes_tag 2 #define meshtastic_Compressed_portnum_tag 1 @@ -1501,6 +1576,13 @@ X(a, STATIC, OPTIONAL, UINT32, bitfield, 9) #define meshtastic_Data_CALLBACK NULL #define meshtastic_Data_DEFAULT NULL +#define meshtastic_KeyVerification_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT64, nonce, 1) \ +X(a, STATIC, SINGULAR, BYTES, hash1, 2) \ +X(a, STATIC, SINGULAR, BYTES, hash2, 3) +#define meshtastic_KeyVerification_CALLBACK NULL +#define meshtastic_KeyVerification_DEFAULT NULL + #define meshtastic_Waypoint_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, id, 1) \ X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \ @@ -1629,9 +1711,36 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,deviceuiConfig,deviceuiConfi X(a, STATIC, OPTIONAL, UINT32, reply_id, 1) \ X(a, STATIC, SINGULAR, FIXED32, time, 2) \ X(a, STATIC, SINGULAR, UENUM, level, 3) \ -X(a, STATIC, SINGULAR, STRING, message, 4) +X(a, STATIC, SINGULAR, STRING, message, 4) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_inform,payload_variant.key_verification_number_inform), 11) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_request,payload_variant.key_verification_number_request), 12) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_final,payload_variant.key_verification_final), 13) #define meshtastic_ClientNotification_CALLBACK NULL #define meshtastic_ClientNotification_DEFAULT NULL +#define meshtastic_ClientNotification_payload_variant_key_verification_number_inform_MSGTYPE meshtastic_KeyVerificationNumberInform +#define meshtastic_ClientNotification_payload_variant_key_verification_number_request_MSGTYPE meshtastic_KeyVerificationNumberRequest +#define meshtastic_ClientNotification_payload_variant_key_verification_final_MSGTYPE meshtastic_KeyVerificationFinal + +#define meshtastic_KeyVerificationNumberInform_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT64, nonce, 1) \ +X(a, STATIC, SINGULAR, STRING, remote_longname, 2) \ +X(a, STATIC, SINGULAR, UINT32, security_number, 3) +#define meshtastic_KeyVerificationNumberInform_CALLBACK NULL +#define meshtastic_KeyVerificationNumberInform_DEFAULT NULL + +#define meshtastic_KeyVerificationNumberRequest_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT64, nonce, 1) \ +X(a, STATIC, SINGULAR, STRING, remote_longname, 2) +#define meshtastic_KeyVerificationNumberRequest_CALLBACK NULL +#define meshtastic_KeyVerificationNumberRequest_DEFAULT NULL + +#define meshtastic_KeyVerificationFinal_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT64, nonce, 1) \ +X(a, STATIC, SINGULAR, STRING, remote_longname, 2) \ +X(a, STATIC, SINGULAR, BOOL, isSender, 3) \ +X(a, STATIC, SINGULAR, STRING, verification_characters, 4) +#define meshtastic_KeyVerificationFinal_CALLBACK NULL +#define meshtastic_KeyVerificationFinal_DEFAULT NULL #define meshtastic_FileInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, file_name, 1) \ @@ -1731,6 +1840,7 @@ extern const pb_msgdesc_t meshtastic_User_msg; extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg; extern const pb_msgdesc_t meshtastic_Routing_msg; extern const pb_msgdesc_t meshtastic_Data_msg; +extern const pb_msgdesc_t meshtastic_KeyVerification_msg; extern const pb_msgdesc_t meshtastic_Waypoint_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; extern const pb_msgdesc_t meshtastic_MeshPacket_msg; @@ -1740,6 +1850,9 @@ extern const pb_msgdesc_t meshtastic_LogRecord_msg; extern const pb_msgdesc_t meshtastic_QueueStatus_msg; extern const pb_msgdesc_t meshtastic_FromRadio_msg; extern const pb_msgdesc_t meshtastic_ClientNotification_msg; +extern const pb_msgdesc_t meshtastic_KeyVerificationNumberInform_msg; +extern const pb_msgdesc_t meshtastic_KeyVerificationNumberRequest_msg; +extern const pb_msgdesc_t meshtastic_KeyVerificationFinal_msg; extern const pb_msgdesc_t meshtastic_FileInfo_msg; extern const pb_msgdesc_t meshtastic_ToRadio_msg; extern const pb_msgdesc_t meshtastic_Compressed_msg; @@ -1758,6 +1871,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_RouteDiscovery_fields &meshtastic_RouteDiscovery_msg #define meshtastic_Routing_fields &meshtastic_Routing_msg #define meshtastic_Data_fields &meshtastic_Data_msg +#define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg #define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg #define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg @@ -1767,6 +1881,9 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_QueueStatus_fields &meshtastic_QueueStatus_msg #define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg #define meshtastic_ClientNotification_fields &meshtastic_ClientNotification_msg +#define meshtastic_KeyVerificationNumberInform_fields &meshtastic_KeyVerificationNumberInform_msg +#define meshtastic_KeyVerificationNumberRequest_fields &meshtastic_KeyVerificationNumberRequest_msg +#define meshtastic_KeyVerificationFinal_fields &meshtastic_KeyVerificationFinal_msg #define meshtastic_FileInfo_fields &meshtastic_FileInfo_msg #define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg #define meshtastic_Compressed_fields &meshtastic_Compressed_msg @@ -1784,13 +1901,17 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; /* meshtastic_ChunkedPayloadResponse_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_FromRadio_size #define meshtastic_ChunkedPayload_size 245 -#define meshtastic_ClientNotification_size 415 +#define meshtastic_ClientNotification_size 482 #define meshtastic_Compressed_size 239 #define meshtastic_Data_size 269 #define meshtastic_DeviceMetadata_size 54 #define meshtastic_FileInfo_size 236 #define meshtastic_FromRadio_size 510 #define meshtastic_Heartbeat_size 0 +#define meshtastic_KeyVerificationFinal_size 65 +#define meshtastic_KeyVerificationNumberInform_size 58 +#define meshtastic_KeyVerificationNumberRequest_size 52 +#define meshtastic_KeyVerification_size 79 #define meshtastic_LogRecord_size 426 #define meshtastic_MeshPacket_size 378 #define meshtastic_MqttClientProxyMessage_size 501 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 4e7c43e58..5bd27ef7d 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -74,6 +74,8 @@ typedef enum _meshtastic_PortNum { meshtastic_PortNum_DETECTION_SENSOR_APP = 10, /* Same as Text Message but used for critical alerts. */ meshtastic_PortNum_ALERT_APP = 11, + /* Module/port for handling key verification requests. */ + meshtastic_PortNum_KEY_VERIFICATION_APP = 12, /* Provides a 'ping' service that replies to any packet it receives. Also serves as a small example module. ENCODING: ASCII Plaintext */ From 8908805894b73ea70b9de46000e34f0378ec556d Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Wed, 28 May 2025 01:10:14 +0200 Subject: [PATCH 214/238] Don't cancel sending ReTx for relayer if we're ROUTER(_LATE)/REPEATER (#6904) Co-authored-by: Ben Meadors --- src/mesh/NextHopRouter.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index f21974a2e..860250f75 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -165,10 +165,15 @@ bool NextHopRouter::stopRetransmission(GlobalPacketId key) /* Only when we already transmitted a packet via LoRa, we will cancel the packet in the Tx queue to avoid canceling a transmission if it was ACKed super fast via MQTT */ if (old->numRetransmissions < NUM_RELIABLE_RETX - 1) { - // remove the 'original' (identified by originator and packet->id) from the txqueue and free it - cancelSending(getFrom(p), p->id); - // now free the pooled copy for retransmission too - packetPool.release(p); + // We only cancel it if we are the original sender or if we're not a router(_late)/repeater + if (isFromUs(p) || (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && + config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER && + config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)) { + // remove the 'original' (identified by originator and packet->id) from the txqueue and free it + cancelSending(getFrom(p), p->id); + // now free the pooled copy for retransmission too + packetPool.release(p); + } } auto numErased = pending.erase(key); assert(numErased == 1); From 96c18d990880b82fb9d391a558e50696a0c9001d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Wed, 28 May 2025 01:11:32 +0200 Subject: [PATCH 215/238] Add LINK32 (Lilygo) Board with Light+Environment sensors (#6899) * Add LINK32 (Lilygo) Board with Light+Environment sensors TODO: replace PRIVATE_HW with actual HWID * Add LINK32 (Lilygo) Board with Light+Environment sensors TODO: replace PRIVATE_HW with actual HWID * Update to real HWID and trunk fmt --- .trunk/trunk.yaml | 7 +++-- src/platform/esp32/architecture.h | 2 ++ variants/link32_s3_v1/pins_arduino.h | 19 +++++++++++++ variants/link32_s3_v1/platformio.ini | 11 ++++++++ variants/link32_s3_v1/variant.h | 42 ++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 variants/link32_s3_v1/pins_arduino.h create mode 100644 variants/link32_s3_v1/platformio.ini create mode 100644 variants/link32_s3_v1/variant.h diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 91bdf11cb..162fdfd2d 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -4,11 +4,12 @@ cli: plugins: sources: - id: trunk - ref: v1.6.8 + ref: v1.7.0 uri: https://github.com/trunk-io/plugins lint: enabled: - - renovate@40.0.6 + - checkov@3.2.435 + - renovate@40.32.7 - prettier@3.5.3 - trufflehog@3.88.34 - yamllint@1.37.1 @@ -37,7 +38,7 @@ runtimes: enabled: - python@3.10.8 - go@1.21.0 - - node@18.20.5 + - node@22.16.0 actions: disabled: - trunk-announce diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 68d06c6d7..3763bce1e 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -184,6 +184,8 @@ #define HW_VENDOR meshtastic_HardwareModel_HELTEC_SENSOR_HUB #elif defined(ELECROW_PANEL) #define HW_VENDOR meshtastic_HardwareModel_CROWPANEL +#elif defined(LINK_32) +#define HW_VENDOR meshtastic_HardwareModel_LINK_32 #endif // ----------------------------------------------------------------------------- diff --git a/variants/link32_s3_v1/pins_arduino.h b/variants/link32_s3_v1/pins_arduino.h new file mode 100644 index 000000000..010e5bf2e --- /dev/null +++ b/variants/link32_s3_v1/pins_arduino.h @@ -0,0 +1,19 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +// The default Wire will be mapped to PMU and RTC +static const uint8_t SDA = 47; +static const uint8_t SCL = 48; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 21; +static const uint8_t MOSI = 34; +static const uint8_t MISO = 33; +static const uint8_t SCK = 16; + +#endif /* Pins_Arduino_h */ diff --git a/variants/link32_s3_v1/platformio.ini b/variants/link32_s3_v1/platformio.ini new file mode 100644 index 000000000..5a614a7af --- /dev/null +++ b/variants/link32_s3_v1/platformio.ini @@ -0,0 +1,11 @@ +[env:link32-s3-v1] +extends = esp32s3_base +board = esp32-s3-devkitc-1 +build_flags = + ${esp32_base.build_flags} -D LINK_32 -I variants/link32_s3_v1 + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + -DARDUINO_USB_CDC_ON_BOOT + -DARDUINO_USB_MODE=1 + -DRADIOLIB_EXCLUDE_SX128X=1 + -DRADIOLIB_EXCLUDE_SX127X=1 + -DRADIOLIB_EXCLUDE_LR11X0=1 diff --git a/variants/link32_s3_v1/variant.h b/variants/link32_s3_v1/variant.h new file mode 100644 index 000000000..1f8a7435a --- /dev/null +++ b/variants/link32_s3_v1/variant.h @@ -0,0 +1,42 @@ +#define BATTERY_PIN 15 +#define ADC_CHANNEL ADC2_GPIO15_CHANNEL // ADC channel for battery voltage measurement +#define BATTERY_SENSE_SAMPLES 30 +#define BAT_MEASURE_ADC_UNIT 2 // Use ADC2 for battery measurement + +#define USE_SSD1306 + +#define BUTTON_PIN 0 // Button pin for this board +#define BUTTON_PIN_ALT 36 + +#define HAS_NEOPIXEL // If defined, we will use the neopixel library +#define NEOPIXEL_DATA 35 // Neopixel pin for this board +#define NEOPIXEL_COUNT 1 // Number of neopixels on this board +#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use + +#define ADC_MULTIPLIER 2 + +#define I2C_SDA 47 // I2C pins for this board +#define I2C_SCL 48 + +#define USE_SX1262 + +#define LORA_SCK 16 +#define LORA_MISO 33 +#define LORA_MOSI 34 +#define LORA_CS 21 +#define LORA_RESET 18 + +#define LORA_DIO0 12 // a No connect on the SX1262 module +#define LORA_DIO1 13 +#define LORA_DIO2 14 // Not really used + +#define LORA_TCXO_GPIO 17 + +#define TCXO_OPTIONAL + +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 From da69d8879045bde87dd1600510fea9726498a4c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 06:20:51 -0500 Subject: [PATCH 216/238] [create-pull-request] automated change (#6909) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/protobufs b/protobufs index 022ea79ba..24c7a3d28 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 022ea79bad79b70d0bee286cd9184916ab47c1b1 +Subproject commit 24c7a3d287a4bd269ce191827e5dabd8ce8f57a7 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index c1ec607d6..5fc1cc4f5 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -252,10 +252,10 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_LINK_32 = 98, /* * Seeed Tracker L1 */ - meshtastic_HardwareModel_SEEED_TRACKER_L1 = 99, + meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1 = 99, /* * Seeed Tracker L1 EINK driver */ - meshtastic_HardwareModel_SEEED_TRACKER_L1_EINK = 100, + meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK = 100, /* Reserved ID for future and past use */ meshtastic_HardwareModel_QWANTZ_TINY_ARMS = 101, /* ------------------------------------------------------------------------------------------------------------------------------------------ From 42a80d8aeda556df7f30ec67a612273e48241502 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 28 May 2025 11:30:59 -0500 Subject: [PATCH 217/238] Coerce user.id to always be derive from the nodenum (#6906) * Coerce user.id to always be derive from the nodenum * Additionally null it out on send * Revert "Additionally null it out on send" This reverts commit 22a2d687237d9f49024bfb8641043cc8e99b32f0. --- src/modules/NodeInfoModule.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index 5142f2db0..e072fcb0f 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -14,6 +14,9 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes { auto p = *pptr; + // Coerce user.id to be derived from the node number + snprintf(p.id, sizeof(p.id), "!%08x", getFrom(&mp)); + bool hasChanged = nodeDB->updateUser(getFrom(&mp), p, mp.channel); bool wasBroadcast = isBroadcast(mp.to); From 5195815df017e67ce6ee599367f2cd4ce52b5bed Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Thu, 29 May 2025 23:21:09 +1200 Subject: [PATCH 218/238] Parse own short name in LogoApplet (#6913) --- src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp index 89bdb0bc7..fa85deab3 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp @@ -111,9 +111,10 @@ void InkHUD::LogoApplet::onShutdown() // Prepare for the powered-off screen now // We can change these values because the initial "shutting down" screen has already rendered at this point + meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum()); textLeft = ""; textRight = ""; - textTitle = owner.short_name; + textTitle = parseShortName(ourNode); fontTitle = fontLarge; // This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update, after InkHUD's flash write is complete From e31cd0bc773901df844192d3edcdd42ce57f262e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 06:27:36 -0500 Subject: [PATCH 219/238] chore(deps): update meshtastic/device-ui digest to 3dfcc97 (#6912) 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 d7504e6c5..e5d36d862 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/e63b219e78e9655be10745b4037cefd2c608d258.zip + https://github.com/meshtastic/device-ui/archive/3dfcc973cdfec8b34719510952e160bbfb57d9df.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From c0c2ec195f53b3f2e51dc71df73957631af83a09 Mon Sep 17 00:00:00 2001 From: dylanli Date: Thu, 29 May 2025 19:33:22 +0800 Subject: [PATCH 220/238] add support for seeed wio tracker L1 (#6907) * add support for seeed wio tracker l1 * add support in nrf52 arch * fix ADC problem and comments incorrect * fix gps wakeup pin * fix gps pin --- boards/seeed_wio_tracker_L1.json | 54 ++++++ src/configuration.h | 6 +- src/platform/nrf52/architecture.h | 2 + variants/seeed_wio_tracker_L1/platformio.ini | 13 ++ variants/seeed_wio_tracker_L1/variant.cpp | 97 ++++++++++ variants/seeed_wio_tracker_L1/variant.h | 185 +++++++++++++++++++ 6 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 boards/seeed_wio_tracker_L1.json create mode 100644 variants/seeed_wio_tracker_L1/platformio.ini create mode 100644 variants/seeed_wio_tracker_L1/variant.cpp create mode 100644 variants/seeed_wio_tracker_L1/variant.h diff --git a/boards/seeed_wio_tracker_L1.json b/boards/seeed_wio_tracker_L1.json new file mode 100644 index 000000000..7c7bc62fa --- /dev/null +++ b/boards/seeed_wio_tracker_L1.json @@ -0,0 +1,54 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v7.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [["0x2886", "0x1668"]], + "usb_product": "TRACKER L1", + "mcu": "nrf52840", + "variant": "seeed_wio_tracker_L1", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "7.3.0", + "sd_fwid": "0x0123" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "seeed_wio_tracker_L1", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/Wio-Tracker-L1-p-6477.html", + "vendor": "Seeed Studio" +} diff --git a/src/configuration.h b/src/configuration.h index 0c23e677d..32d99295e 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -99,8 +99,12 @@ along with this program. If not, see . // ----------------------------------------------------------------------------- // OLED & Input // ----------------------------------------------------------------------------- - +#if defined(SEEED_WIO_TRACKER_L1) +#define SSD1306_ADDRESS 0x3D +#define USE_SH1106 +#else #define SSD1306_ADDRESS 0x3C +#endif #define ST7567_ADDRESS 0x3F // The SH1106 controller is almost, but not quite, the same as SSD1306 diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 9d1d48f1c..eea3aee45 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -85,6 +85,8 @@ #define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE #elif defined(HELTEC_MESH_POCKET) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET +#elif defined(SEEED_WIO_TRACKER_L1) +#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1 #else #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN #endif diff --git a/variants/seeed_wio_tracker_L1/platformio.ini b/variants/seeed_wio_tracker_L1/platformio.ini new file mode 100644 index 000000000..3c4653d7e --- /dev/null +++ b/variants/seeed_wio_tracker_L1/platformio.ini @@ -0,0 +1,13 @@ +[env:seeed_wio_tracker_L1] +board = seeed_wio_tracker_L1 +extends = nrf52840_base +;board_level = extra +build_flags = ${nrf52840_base.build_flags} + -I $PROJECT_DIR/variants/seeed_wio_tracker_L1 + -D SEEED_WIO_TRACKER_L1 + -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 +board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/seeed_wio_tracker_L1> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink diff --git a/variants/seeed_wio_tracker_L1/variant.cpp b/variants/seeed_wio_tracker_L1/variant.cpp new file mode 100644 index 000000000..3ff5688bb --- /dev/null +++ b/variants/seeed_wio_tracker_L1/variant.cpp @@ -0,0 +1,97 @@ +/* + * variant.cpp - Digital pin mapping for TRACKER L1 + * + * This file defines the pin mapping array that maps logical digital pins (D0-D17) + * to physical GPIO ports/pins on the Nordic nRF52 series microcontroller. + * + * Board: [Seeed Studio WIO TRACKER L1] + * Hardware Features: + * - LoRa module (CS/SCK/MISO/MOSI control pins) + * - GNSS module (TX/RX/Reset/Wakeup) + * - User LEDs (D11-D12) + * - User button (D13) + * - Grove/NFC interface (D14-D15) + * - Battery voltage monitoring (D16) + * + * Created [20250521] + * By [Dylan] + */ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +/** + * @brief Digital pin to GPIO port/pin mapping table + * + * Format: Logical Pin (Dx) -> nRF Port.Pin (Px.xx) + * + */ + +extern "C" { +const uint32_t g_ADigitalPinMap[] = { + // D0 .. D10 - Peripheral control pins + 41, // D0 P1.09 GNSS_WAKEUP + 7, // D1 P0.07 LORA_DIO1 + 39, // D2 P1,07 LORA_RESET + 42, // D3 P1.10 LORA_BUSY + 46, // D4 P1.14 (A4/SDA) LORA_CS + 40, // D5 P1.08 (A5/SCL) LORA_SW + 27, // D6 P0.27 (UART_TX) GNSS_TX + 26, // D7 P0.26 (UART_RX) GNSS_RX + 30, // D8 P0.30 (SPI_SCK) LORA_SCK + 3, // D9 P0.3 (SPI_MISO) LORA_MISO + 28, // D10 P0.28 (SPI_MOSI) LORA_MOSI + + // D11-D12 - LED outputs + 33, // D11 P1.1 User LED + // Buzzzer + 32, // D12 P1.0 Buzzer + + // D13 - User input + 8, // D13 P0.08 User Button + + // D14-D15 - Grove interface + 6, // D14 P0.06 OLED SDA + 5, // D15 P0.05 OLED SCL + + // D16 - Battery voltage ADC input + 31, // D16 P0.31 VBAT_ADC + // GROVE + 0, // D17 P0.00 GROVESDA + 1, // D18 P0.01 GROVESCL + + // FLASH + 21, // D19 P0.21 (QSPI_SCK) + 25, // D20 P0.25 (QSPI_CSN) + 20, // D21 P0.20 (QSPI_SIO_0 DI) + 24, // D22 P0.24 (QSPI_SIO_1 DO) + 22, // D23 P0.22 (QSPI_SIO_2 WP) + 23, // D24 P0.23 (QSPI_SIO_3 HOLD) + + + 36, // D25 TB_UP + 12, // D26 TB_DOWN + 11, // D27 TB_LEFT + 35, // D28 TB_RIGHT + 37, // D29 TB_PRESS + 4, // D30 BAT_CTL +}; +} + +void initVariant() +{ + pinMode(PIN_QSPI_CS, OUTPUT); + digitalWrite(PIN_QSPI_CS, HIGH); + // This setup is crucial for ensuring low power consumption and proper initialization of the hardware components. + // VBAT_ENABLE + pinMode(BAT_READ, OUTPUT); + digitalWrite(BAT_READ, HIGH); + + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, LOW); + pinMode(PIN_LED2, OUTPUT); + digitalWrite(PIN_LED2, LOW); + pinMode(PIN_LED2, OUTPUT); +} \ No newline at end of file diff --git a/variants/seeed_wio_tracker_L1/variant.h b/variants/seeed_wio_tracker_L1/variant.h new file mode 100644 index 000000000..23c788480 --- /dev/null +++ b/variants/seeed_wio_tracker_L1/variant.h @@ -0,0 +1,185 @@ +#ifndef _SEEED_TRACKER_L1_H_ +#define _SEEED_TRACKER_L1_H_ +#include "WVariant.h" +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Clock Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define VARIANT_MCK (64000000ul) // Master clock frequency +#define USE_LFXO // 32.768kHz crystal for LFCLK + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Pin Capacity Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PINS_COUNT (33u) // Total GPIO pins +#define NUM_DIGITAL_PINS (33u) // Digital I/O pins +#define NUM_ANALOG_INPUTS (8u) // Analog inputs (A0-A5 + VBAT + AREF) +#define NUM_ANALOG_OUTPUTS (0u) + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LED Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LEDs +// LEDs +#define PIN_LED1 (11) // LED P1.15 +#define PIN_LED2 (12) // + +#define LED_BUILTIN PIN_LED1 +#define LED_CONN PIN_LED2 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 +// #define LED_PIN PIN_LED2 +#define LED_STATE_ON 1 // State when LED is litted +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Button Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define BUTTON_PIN D13 // This is the Program Button +// #define BUTTON_NEED_PULLUP 1 +#define BUTTON_ACTIVE_LOW true +#define BUTTON_ACTIVE_PULLUP false + +#define BUTTON_PIN_TOUCH 13 // Touch button +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Digital Pin Mapping (D0-D10) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define D0 0 // P1.06 GNSS_WAKEUP/IO0 +#define D1 1 // P0.07 LORA_DIO1 +#define D2 2 // P1.07 LORA_RESET +#define D3 3 // P1.10 LORA_BUSY +#define D4 4 // P1.14 LORA_CS +#define D5 5 // P1.08 LORA_SW +#define D6 6 // P0.27 GNSS_TX +#define D7 7 // P0.26 GNSS_RX +#define D8 8 // P0.30 SPI_SCK +#define D9 9 // P0.03 SPI_MISO +#define D10 10 // P0.28 SPI_MOSI +#define D12 12 // P1.00 Buzzer +#define D13 13 // P0.08 User Button +#define D14 14 // P0.05 OLED SCL +#define D15 15 // P0.06 OLED SDA +#define D16 16 // P0.31 VBAT_ADC +#define D17 17 // P0.00 GROVE SDA +#define D18 18 // P0.01 GROVE_SCL +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Analog Pin Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PIN_A0 0 // P0.02 Analog Input 0 +#define PIN_A1 1 // P0.03 Analog Input 1 +#define PIN_A2 2 // P0.28 Analog Input 2 +#define PIN_A3 3 // P0.29 Analog Input 3 +#define PIN_A4 4 // P0.04 Analog Input 4 +#define PIN_A5 5 // P0.05 Analog Input 5 +#define PIN_VBAT D16 // P0.31 Battery voltage sense +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Communication Interfaces +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// I2C Configuration +#define HAS_WIRE 1 +#define PIN_WIRE_SDA D14 // P0.09 +#define PIN_WIRE_SCL D15 // P0.10 +#define WIRE_INTERFACES_COUNT 1 +#define I2C_NO_RESCAN + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +#define HAS_SCREEN 1 +#define USE_SSD1306 1 + +// SPI Configuration (SX1262) + +#define SPI_INTERFACES_COUNT 1 +#define PIN_SPI_MISO 9 // P0.03 (D9) +#define PIN_SPI_MOSI 10 // P0.28 (D10) +#define PIN_SPI_SCK 8 // P0.30 (D8) + +// SX1262 LoRa Module Pins +#define USE_SX1262 +#define SX126X_CS D4 // Chip select +#define SX126X_DIO1 D1 // Digital IO 1 (Interrupt) +#define SX126X_BUSY D3 // Busy status +#define SX126X_RESET D2 // Reset control +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // TCXO supply voltage +#define SX126X_RXEN D5 // RX enable control +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_DIO2_AS_RF_SWITCH // This Line is really necessary for SX1262 to work with RF switch or will loss TX power +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Power Management +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +#define BAT_READ \ + 30 // D30 = P0.04 Reads battery voltage from divider on signal board. +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define ADC_MULTIPLIER 2.0 +#define BATTERY_PIN PIN_VBAT // PIN_A7 +#define AREF_VOLTAGE 3.6 +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// GPS L76KB +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define GPS_L76K +#ifdef GPS_L76K +#define PIN_GPS_RX D6 // P0.26 +#define PIN_GPS_TX D7 +#define HAS_GPS 1 +#define GPS_BAUDRATE 9600 +#define GPS_THREAD_INTERVAL 50 +#define PIN_SERIAL1_RX PIN_GPS_TX +#define PIN_SERIAL1_TX PIN_GPS_RX + +#define GPS_RX_PIN PIN_GPS_TX +#define GPS_TX_PIN PIN_GPS_RX +#define PIN_GPS_STANDBY D0 + +// #define GPS_DEBUG +// #define GPS_EN D18 // P1.05 +#endif + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +#define PIN_QSPI_SCK (21) +#define PIN_QSPI_CS (22) +#define PIN_QSPI_IO0 (23) +#define PIN_QSPI_IO1 (24) +#define PIN_QSPI_IO2 (25) +#define PIN_QSPI_IO3 (26) + +#define EXTERNAL_FLASH_DEVICES P25Q16H +#define EXTERNAL_FLASH_USE_QSPI + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Buzzer +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Buzzer + +#define PIN_BUZZER D12 // P1.00, pwm output + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// joystick +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +#define CANNED_MESSAGE_MODULE_ENABLE 1 + +// trackball +#define HAS_TRACKBALL 1 +#define TB_UP 25 +#define TB_DOWN 26 +#define TB_LEFT 27 +#define TB_RIGHT 28 +#define TB_PRESS 29 +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Compatibility Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#ifdef __cplusplus +extern "C" { +#endif +// Serial port placeholders + +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) +#ifdef __cplusplus +} +#endif + +#endif // _SEEED_SOLAR_NODE_H_ \ No newline at end of file From 7849a3d29119be7abef060bc99d7048997f13d03 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 29 May 2025 06:35:18 -0500 Subject: [PATCH 221/238] Trunk --- variants/seeed_wio_tracker_L1/variant.cpp | 3 +-- variants/seeed_wio_tracker_L1/variant.h | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/variants/seeed_wio_tracker_L1/variant.cpp b/variants/seeed_wio_tracker_L1/variant.cpp index 3ff5688bb..6c34d63e6 100644 --- a/variants/seeed_wio_tracker_L1/variant.cpp +++ b/variants/seeed_wio_tracker_L1/variant.cpp @@ -70,13 +70,12 @@ const uint32_t g_ADigitalPinMap[] = { 22, // D23 P0.22 (QSPI_SIO_2 WP) 23, // D24 P0.23 (QSPI_SIO_3 HOLD) - 36, // D25 TB_UP 12, // D26 TB_DOWN 11, // D27 TB_LEFT 35, // D28 TB_RIGHT 37, // D29 TB_PRESS - 4, // D30 BAT_CTL + 4, // D30 BAT_CTL }; } diff --git a/variants/seeed_wio_tracker_L1/variant.h b/variants/seeed_wio_tracker_L1/variant.h index 23c788480..b257fd9b6 100644 --- a/variants/seeed_wio_tracker_L1/variant.h +++ b/variants/seeed_wio_tracker_L1/variant.h @@ -107,10 +107,9 @@ static const uint8_t SCL = PIN_WIRE_SCL; // Power Management // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -#define BAT_READ \ - 30 // D30 = P0.04 Reads battery voltage from divider on signal board. +#define BAT_READ 30 // D30 = P0.04 Reads battery voltage from divider on signal board. #define BATTERY_SENSE_RESOLUTION_BITS 12 -#define ADC_MULTIPLIER 2.0 +#define ADC_MULTIPLIER 2.0 #define BATTERY_PIN PIN_VBAT // PIN_A7 #define AREF_VOLTAGE 3.6 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ From f972b62d89420abdac781113747b2c40ac873b41 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 09:06:52 -0500 Subject: [PATCH 222/238] Upgrade trunk to 1.24.0 (#6915) Co-authored-by: sachaw <11172820+sachaw@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 162fdfd2d..3a02034a6 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,6 +1,6 @@ version: 0.1 cli: - version: 1.22.15 + version: 1.24.0 plugins: sources: - id: trunk @@ -9,7 +9,7 @@ plugins: lint: enabled: - checkov@3.2.435 - - renovate@40.32.7 + - renovate@40.33.8 - prettier@3.5.3 - trufflehog@3.88.34 - yamllint@1.37.1 From cb9429e83e06b29679b5c85272b62615ce583bed Mon Sep 17 00:00:00 2001 From: dmarman Date: Thu, 29 May 2025 16:09:33 +0200 Subject: [PATCH 223/238] Added full support for LTR390UV readings of UV and Lux (#6872) * Added full support for LTR390UV readings of UV and Lux * Trunk formatting * Added full support for LTR390UV readings of UV and Lux * Trunk formatting * fix library check and unnecessary bit resolution change * fixed log info messages and removed unused dependency * Hopefully fixes git mess * fix variable scope and getMetrics returns * set metrics flags bavk to false in case something wrong happens while reading LTR390UV mode --------- Co-authored-by: Domingo Co-authored-by: Ben Meadors --- platformio.ini | 4 +- .../Telemetry/EnvironmentTelemetry.cpp | 18 +++++ .../Telemetry/Sensor/LTR390UVSensor.cpp | 73 +++++++++++++++++++ src/modules/Telemetry/Sensor/LTR390UVSensor.h | 25 +++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/modules/Telemetry/Sensor/LTR390UVSensor.cpp create mode 100644 src/modules/Telemetry/Sensor/LTR390UVSensor.h diff --git a/platformio.ini b/platformio.ini index e5d36d862..125dfb573 100644 --- a/platformio.ini +++ b/platformio.ini @@ -161,6 +161,8 @@ lib_deps = sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 + # renovate: datasource=custom.pio depName=Adafruit LTR390 Library packageName=adafruit/library/Adafruit LTR390 Library + adafruit/Adafruit LTR390 Library@1.1.2 # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/Adafruit PCT2075 adafruit/Adafruit PCT2075@1.0.5 @@ -190,4 +192,4 @@ lib_deps = # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library boschsensortec/BME68x Sensor Library@1.3.40408 # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master - https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip + https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip \ No newline at end of file diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 51f076552..6d29fecb2 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -52,6 +52,13 @@ BMP280Sensor bmp280Sensor; NullSensor bme280Sensor; #endif +#if __has_include() +#include "Sensor/LTR390UVSensor.h" +LTR390UVSensor ltr390uvSensor; +#else +NullSensor ltr390uvSensor; +#endif + #if __has_include() #include "Sensor/BME680Sensor.h" BME680Sensor bme680Sensor; @@ -231,6 +238,8 @@ int32_t EnvironmentTelemetryModule::runOnce() #endif if (bme280Sensor.hasSensor()) result = bme280Sensor.runOnce(); + if (ltr390uvSensor.hasSensor()) + result = ltr390uvSensor.runOnce(); if (bmp3xxSensor.hasSensor()) result = bmp3xxSensor.runOnce(); if (bme680Sensor.hasSensor()) @@ -524,6 +533,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && bme280Sensor.getMetrics(m); hasSensor = true; } + if (ltr390uvSensor.hasSensor()) { + valid = valid && ltr390uvSensor.getMetrics(m); + hasSensor = true; + } if (bmp3xxSensor.hasSensor()) { valid = valid && bmp3xxSensor.getMetrics(m); hasSensor = true; @@ -752,6 +765,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule if (result != AdminMessageHandleResult::NOT_HANDLED) return result; } + if (ltr390uvSensor.hasSensor()) { + result = ltr390uvSensor.handleAdminMessage(mp, request, response); + if (result != AdminMessageHandleResult::NOT_HANDLED) + return result; + } if (bmp3xxSensor.hasSensor()) { result = bmp3xxSensor.handleAdminMessage(mp, request, response); if (result != AdminMessageHandleResult::NOT_HANDLED) diff --git a/src/modules/Telemetry/Sensor/LTR390UVSensor.cpp b/src/modules/Telemetry/Sensor/LTR390UVSensor.cpp new file mode 100644 index 000000000..fb84700c4 --- /dev/null +++ b/src/modules/Telemetry/Sensor/LTR390UVSensor.cpp @@ -0,0 +1,73 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "LTR390UVSensor.h" +#include "TelemetrySensor.h" +#include + +LTR390UVSensor::LTR390UVSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_LTR390UV, "LTR390UV") {} + +int32_t LTR390UVSensor::runOnce() +{ + LOG_INFO("Init sensor: %s", sensorName); + if (!hasSensor()) { + return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; + } + + status = ltr390uv.begin(nodeTelemetrySensorsMap[sensorType].second); + ltr390uv.setMode(LTR390_MODE_UVS); + ltr390uv.setGain(LTR390_GAIN_18); // Datasheet default + ltr390uv.setResolution(LTR390_RESOLUTION_20BIT); // Datasheet default + + return initI2CSensor(); +} + +void LTR390UVSensor::setup() {} + +bool LTR390UVSensor::getMetrics(meshtastic_Telemetry *measurement) +{ + LOG_DEBUG("LTR390UV getMetrics"); + + // Because the sensor does not measure Lux and UV at the same time, we need to read them in two passes. + if (ltr390uv.newDataAvailable()) { + measurement->variant.environment_metrics.has_lux = true; + measurement->variant.environment_metrics.has_uv_lux = true; + + if (ltr390uv.getMode() == LTR390_MODE_ALS) { + lastLuxReading = 0.6 * ltr390uv.readALS() / (1 * 4); // Datasheet page 23 for gain x1 and 20bit resolution + LOG_DEBUG("LTR390UV Lux reading: %f", lastLuxReading); + + measurement->variant.environment_metrics.lux = lastLuxReading; + measurement->variant.environment_metrics.uv_lux = lastUVReading; + + ltr390uv.setGain( + LTR390_GAIN_18); // Recommended for UVI - x18. Do not change, 2300 UV Sensitivity only specified for x18 gain + ltr390uv.setMode(LTR390_MODE_UVS); + + return true; + + } else if (ltr390uv.getMode() == LTR390_MODE_UVS) { + lastUVReading = ltr390uv.readUVS() / + 2300.f; // Datasheet page 23 and page 6, only characterisation for gain x18 and 20bit resolution + LOG_DEBUG("LTR390UV UV reading: %f", lastUVReading); + + measurement->variant.environment_metrics.lux = lastLuxReading; + measurement->variant.environment_metrics.uv_lux = lastUVReading; + + ltr390uv.setGain( + LTR390_GAIN_1); // x1 gain will already max out the sensor at direct sunlight, so no need to increase it + ltr390uv.setMode(LTR390_MODE_ALS); + + return true; + } + } + + // In case we fail to read the sensor mode, set the has_lux and has_uv_lux back to false + measurement->variant.environment_metrics.has_lux = false; + measurement->variant.environment_metrics.has_uv_lux = false; + + return false; +} +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/LTR390UVSensor.h b/src/modules/Telemetry/Sensor/LTR390UVSensor.h new file mode 100644 index 000000000..40206bce8 --- /dev/null +++ b/src/modules/Telemetry/Sensor/LTR390UVSensor.h @@ -0,0 +1,25 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include + +class LTR390UVSensor : public TelemetrySensor +{ + private: + Adafruit_LTR390 ltr390uv = Adafruit_LTR390(); + float lastLuxReading = 0; + float lastUVReading = 0; + + protected: + virtual void setup() override; + + public: + LTR390UVSensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; +}; + +#endif \ No newline at end of file From ba535433543f40b0e15280c7beb9e0afabe56142 Mon Sep 17 00:00:00 2001 From: Quency-D <55523105+Quency-D@users.noreply.github.com> Date: Thu, 29 May 2025 22:10:25 +0800 Subject: [PATCH 224/238] Add a new screen for heltec_wireless_paper. (#6894) Co-authored-by: Ben Meadors --- src/graphics/EInkDisplay2.cpp | 64 +++- src/graphics/EInkDisplay2.h | 6 +- src/graphics/EInkMultiWrapper.h | 327 ++++++++++++++++++ src/graphics/niche/Drivers/EInk/E0213A367.cpp | 126 +++++++ src/graphics/niche/Drivers/EInk/E0213A367.h | 44 +++ .../heltec_wireless_paper/nicheGraphics.h | 57 ++- variants/heltec_wireless_paper/platformio.ini | 6 +- 7 files changed, 624 insertions(+), 6 deletions(-) create mode 100644 src/graphics/EInkMultiWrapper.h create mode 100644 src/graphics/niche/Drivers/EInk/E0213A367.cpp create mode 100644 src/graphics/niche/Drivers/EInk/E0213A367.h diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 5a2749482..b518299f7 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -174,7 +174,7 @@ bool EInkDisplay::connect() } } -#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_VISION_MASTER_E213) || \ +#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \ defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \ defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) { @@ -228,6 +228,68 @@ bool EInkDisplay::connect() auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *spi1); adafruitDisplay = new GxEPD2_BW(*lowLevel); + // Init GxEPD2 + adafruitDisplay->init(); + adafruitDisplay->setRotation(3); + } +#elif defined(HELTEC_WIRELESS_PAPER) + { + uint8_t model; + pinMode(PIN_EINK_SCLK, OUTPUT); + pinMode(PIN_EINK_DC, OUTPUT); + pinMode(PIN_EINK_CS, OUTPUT); + pinMode(PIN_EINK_RES, OUTPUT); + + //rest e-ink + digitalWrite(PIN_EINK_RES, LOW); + delay(20); + digitalWrite(PIN_EINK_RES, HIGH); + delay(20); + + digitalWrite(PIN_EINK_DC, LOW); + digitalWrite(PIN_EINK_CS, LOW); + + // write cmd + uint8_t cmd = 0x2F; + pinMode(PIN_EINK_MOSI, OUTPUT); + digitalWrite(PIN_EINK_SCLK, LOW); + for (int i = 0; i < 8; i++) + { + digitalWrite(PIN_EINK_MOSI, (cmd & 0x80) ? HIGH : LOW); + cmd <<= 1; + digitalWrite(PIN_EINK_SCLK, HIGH); + delayMicroseconds(1); + digitalWrite(PIN_EINK_SCLK, LOW); + delayMicroseconds(1); + } + delay(10); + + digitalWrite(PIN_EINK_DC, HIGH); + pinMode(PIN_EINK_MOSI, INPUT_PULLUP); + + // read chip ID + uint8_t chipId = 0; + for (int8_t b = 7; b >= 0; b--) + { + digitalWrite(PIN_EINK_SCLK, LOW); + delayMicroseconds(1); + digitalWrite(PIN_EINK_SCLK, HIGH); + delayMicroseconds(1); + if (digitalRead(PIN_EINK_MOSI)) chipId |= (1 << b); + } + digitalWrite(PIN_EINK_CS, HIGH); + LOG_INFO("eink chipId: %02X", chipId); + model = ((chipId&0x03) !=0x01) ? 1 : 2; + + // Start HSPI + hspi = new SPIClass(HSPI); + hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS + // VExt already enabled in setup() + // RTC GPIO hold disabled in setup() + + // Create GxEPD2 objects + adafruitDisplay = new EInkMultiWrapper(model, PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi); + // Init GxEPD2 adafruitDisplay->init(); adafruitDisplay->setRotation(3); diff --git a/src/graphics/EInkDisplay2.h b/src/graphics/EInkDisplay2.h index 93be197b0..965a3307a 100644 --- a/src/graphics/EInkDisplay2.h +++ b/src/graphics/EInkDisplay2.h @@ -4,6 +4,7 @@ #include "GxEPD2_BW.h" #include +#include "EinkMultiWrapper.h" /** * An adapter class that allows using the GxEPD2 library as if it was an OLEDDisplay implementation. @@ -64,8 +65,11 @@ class EInkDisplay : public OLEDDisplay virtual bool connect() override; // AdafruitGFX display object - instantiated in connect(), variant specific +#if defined(HELTEC_WIRELESS_PAPER) + EInkMultiWrapper *adafruitDisplay; +#else GxEPD2_BW *adafruitDisplay = NULL; - +#endif // If display uses HSPI #if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \ defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \ diff --git a/src/graphics/EInkMultiWrapper.h b/src/graphics/EInkMultiWrapper.h new file mode 100644 index 000000000..3ac0b194d --- /dev/null +++ b/src/graphics/EInkMultiWrapper.h @@ -0,0 +1,327 @@ +// Wrapper class for GxEPD2_BW + +// Generic signature at build time, allowing display model to be detected at run-time +// Workaround for issue of GxEPD2_BW objects not having a shared base class +// Only exposes methods which we are actually using +#ifndef _EINKMULTIWRAPPER_H_ +#define _EINKMULTIWRAPPER_H_ + +#include "GxEPD2_BW.h" +#include "GxEPD2_EPD.h" + +template +class EInkMultiWrapper +{ +public: + void drawPixel(int16_t x, int16_t y, uint16_t color) + { + if (model == 1) + model1->drawPixel(x, y, color); + else + model2->drawPixel(x, y, color); + } + void init(uint32_t serial_diag_bitrate = 0) // = 0 : disabled + { + if (model == 1) + model1->init(serial_diag_bitrate); + else + model2->init(serial_diag_bitrate); + } + + void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 20, bool pulldown_rst_mode = false) + { + if (model == 1) + model1->init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode); + else + model2->init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode); + } + void fillScreen(uint16_t color) // 0x0 black, >0x0 white, to buffer + { + if (model == 1) + model1->fillScreen(color); + else + model2->fillScreen(color); + } + void display(bool partial_update_mode = false) + { + if (model == 1) + model1->display(partial_update_mode); + else + model2->display(partial_update_mode); + } + void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) + { + if (model == 1) + model1->displayWindow(x, y, w, h); + else + model2->displayWindow(x, y, w, h); + } + + void setFullWindow() + { + if (model == 1) + model1->setFullWindow(); + else + model2->setFullWindow(); + } + + void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) + { + if (model == 1) + model1->setPartialWindow(x, y, w, h); + else + model2->setPartialWindow(x, y, w, h); + } + + void firstPage() + { + if (model == 1) + model1->firstPage(); + else + model2->firstPage(); + } + void endAsyncFull() + { + if (model == 1) + model1->endAsyncFull(); + else + model2->endAsyncFull(); + } + + bool nextPage() + { + if (model == 1) + return model1->nextPage(); + else + return model2->nextPage(); + } + void drawPaged(void (*drawCallback)(const void*), const void* pv) + { + if (model == 1) + model1->drawPaged(drawCallback, pv); + else + model2->drawPaged(drawCallback, pv); + } + + void drawInvertedBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) + { + if (model == 1) + model1->drawInvertedBitmap(x, y, bitmap, w, h, color); + else + model2->drawInvertedBitmap(x, y, bitmap, w, h, color); + } + + void clearScreen(uint8_t value = 0xFF) // init controller memory and screen (default white) + { + if (model == 1) + model1->clearScreen(value); + else + model2->clearScreen(value); + } + void writeScreenBuffer(uint8_t value = 0xFF) // init controller memory (default white) + { + if (model == 1) + model1->writeScreenBuffer(value); + else + model2->writeScreenBuffer(value); + } + // write to controller memory, without screen refresh; x and w should be multiple of 8 + void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) + { + if (model == 1) + model1->writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm); + else + model2->writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm); + } + void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) + { + if (model == 1) + model1->writeImagePart(x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + else + model2->writeImagePart(x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + } + void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->writeImage(black, color, x, y, w, h, invert, mirror_y, pgm); + else + model2->writeImage(black, color, x, y, w, h, invert, mirror_y, pgm); + } + void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h) + { + if (model == 1) + model1->writeImage(black, color, x, y, w, h); + else + model2->writeImage(black, color, x, y, w, h); + } + void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->writeImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h, invert, mirror_y, pgm); + else + model2->writeImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h, invert, mirror_y, pgm); + } + + void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h) + { + if (model == 1) + model1->writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); + else + model2->writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); + } + // write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8 + void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); + else + model2->writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); + } + // write to controller memory, with screen refresh; x and w should be multiple of 8 + void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) + { + if (model == 1) + model1->drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm); + else + model2->drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm); + } + void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) + { + if (model == 1) + model1->drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + else + model2->drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + } + void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->drawImage(black, color, x, y, w, h, invert, mirror_y, pgm); + else + model2->drawImage(black, color, x, y, w, h, invert, mirror_y, pgm); + } + void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h) + { + if (model == 1) + model1->drawImage(black, color, x, y, w, h); + else + model2->drawImage(black, color, x, y, w, h); + } + void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + else + model2->drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); + } + void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, + int16_t x, int16_t y, int16_t w, int16_t h) + { + if (model == 1) + model1->drawImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); + else + model2->drawImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); + } + // write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8 + void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) + { + if (model == 1) + model1->drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); + else + model2->drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); + } + void refresh(bool partial_update_mode = false) // screen refresh from controller memory to full screen + { + if (model == 1) + model1->refresh(partial_update_mode); + else + model2->refresh(partial_update_mode); + } + void refresh(int16_t x, int16_t y, int16_t w, int16_t h) // screen refresh from controller memory, partial screen + { + if (model == 1) + model1->refresh(x, y, w, h); + else + model2->refresh(x, y, w, h); + } + // turns off generation of panel driving voltages, avoids screen fading over time + void powerOff() + { + if (model == 1) + model1->powerOff(); + else + model2->powerOff(); + } + // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0) + void hibernate() + { + if (model == 1) + model1->hibernate(); + else + model2->hibernate(); + } + + void setRotation(uint8_t x) + { + if (model == 1) + model1->setRotation(x); + else + model2->setRotation(x); + } + + int16_t width() + { + if (model == 1) + return model1->width(); + else + return model2->width(); + } + + int16_t height() + { + if (model == 1) + return model1->height(); + else + return model2->height(); + } + + + // Exposes methods of the GxEPD2_EPD object which is usually available as GxEPD2_BW::epd + class Epd2Wrapper + { + public: + bool isBusy() { return m_epd2->isBusy(); } + GxEPD2_EPD *m_epd2; + } epd2; + + // Constructor + // Select driver by passing whichModel as 1 or 2 + EInkMultiWrapper(uint8_t whichModel, int16_t cs, int16_t dc, int16_t rst, int16_t busy, SPIClass &spi) + { + assert(whichModel == 1 || whichModel == 2); + model = whichModel; + // LOG_DEBUG("GxEPD2_BW_MultiWrapper using driver %d", model); + + if (model == 1) + { + model1 = new GxEPD2_BW(DISPLAY_MODEL_1(cs, dc, rst, busy, spi)); + epd2.m_epd2 = &(model1->epd2); + } + else if (model == 2) + { + model2 = new GxEPD2_BW(DISPLAY_MODEL_2(cs, dc, rst, busy, spi)); + epd2.m_epd2 = &(model2->epd2); + } + } + +private: + uint8_t model; + GxEPD2_BW *model1; + GxEPD2_BW *model2; +}; + +#endif \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/E0213A367.cpp b/src/graphics/niche/Drivers/EInk/E0213A367.cpp new file mode 100644 index 000000000..4f2a50ba7 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/E0213A367.cpp @@ -0,0 +1,126 @@ +#include "./E0213A367.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +using namespace NicheGraphics::Drivers; + +// Map the display controller IC's output to the connected panel +void E0213A367::configScanning() +{ + // "Driver output control" + sendCommand(0x01); + sendData(0xF9); + sendData(0x00); + // Values set here might be redundant: F9, 00 seems to be default +} + +// Specify which information is used to control the sequence of voltages applied to move the pixels +// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from +// the controller IC's OTP memory, when the update procedure begins. +void E0213A367::configWaveform() +{ + sendCommand(0x37); // Waveform ID register + sendData(0x40); // ByteA + sendData(0x80); // ByteB DM[7:0] + sendData(0x03); // ByteC DM[[15:8] + sendData(0x0E); // ByteD DM[[23:16] + + switch (updateType) { + case FAST: + sendCommand(0x3C); // Border waveform: + sendData(0x81); + break; + case FULL: + sendCommand(0x3C); // Border waveform: + sendData(0x01); + default: + // From OTP memory + break; + } +} + +void E0213A367::configUpdateSequence() +{ + switch (updateType) { + case FAST: + sendCommand(0x22); + sendData(0xFF); + break; + case FULL: + default: + sendCommand(0x22); // Set "update sequence" + sendData(0xF7); + break; + } +} + +// Once the refresh operation has been started, +// begin periodically polling the display to check for completion, using the normal Meshtastic threading code +// Only used when refresh is "async" +void E0213A367::detachFromUpdate() +{ + switch (updateType) { + case FAST: + return beginPolling(50, 500); // At least 500ms for fast refresh + case FULL: + default: + return beginPolling(100, 2000); // At least 2 seconds for full refresh + } +} +void E0213A367::configFullscreen() +{ + // Placing this code in a separate method because it's probably pretty consistent between displays + // Should make it tidier to override SSD16XX::configure + + // Define the boundaries of the "fullscreen" region, for the controller IC + static const uint16_t sx = bufferOffsetX; // Notice the offset + static const uint16_t sy = 0; + static const uint16_t ex = bufferRowSize + bufferOffsetX - 1; // End is "max index", not "count". Minus 1 handles this + static const uint16_t ey = height; + + // Split into bytes + static const uint8_t sy1 = sy & 0xFF; + static const uint8_t ey1 = ey & 0xFF; + + // Data entry mode - Left to Right, Top to Bottom + sendCommand(0x11); + sendData(0x03); + + // Select controller IC memory region to display a fullscreen image + sendCommand(0x44); // Memory X start - end + sendData(sx); + sendData(ex); + sendCommand(0x45); // Memory Y start - end + sendData(sy1); + sendData(ey1); + + // Place the cursor at the start of this memory region, ready to send image data x=0 y=0 + sendCommand(0x4E); // Memory cursor X + sendData(sx); + sendCommand(0x4F); // Memory cursor y + sendData(sy1); +} +void E0213A367::finalizeUpdate() +{ + // Put a copy of the image into the "old memory". + // Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place + // We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc. + if (updateType != FULL) { + writeNewImage(); // Only required by some controller variants. Todo: Override just for GDEY0154D678? + writeOldImage(); + sendCommand(0x7F); // Terminate image write without update + wait(); + } + + //After waking up from sleep mode, the local refresh is abnormal, which may be due to the loss of data in RAM. + // if ((pin_rst != 0xFF) && (updateType ==FULL)) + // deepSleep(); +} + +void E0213A367::deepSleep() +{ + sendCommand(0x10); // Enter deep sleep + sendData(0x03); // Will not retain image RAM +} + +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/E0213A367.h b/src/graphics/niche/Drivers/EInk/E0213A367.h new file mode 100644 index 000000000..c00d73378 --- /dev/null +++ b/src/graphics/niche/Drivers/EInk/E0213A367.h @@ -0,0 +1,44 @@ +/* + +E-Ink display driver + - SSD1682 + - Manufacturer: WISEVAST + - Size: 2.13 inch + - Resolution: 122px x 255px + - Flex connector marking: HINK-E0213A162-FPC-A0 (Hidden, printed on back-side) + +*/ + +#pragma once + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +#include "configuration.h" + +#include "./SSD16XX.h" + +namespace NicheGraphics::Drivers +{ +class E0213A367 : public SSD16XX +{ + // Display properties + private: + static constexpr uint32_t width = 122; + static constexpr uint32_t height = 250; + static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); + + public: + E0213A367() : SSD16XX(width, height, supported, 0) {} + + protected: + virtual void configScanning() override; + virtual void configWaveform() override; + virtual void configUpdateSequence() override; + virtual void detachFromUpdate() override; + virtual void configFullscreen() override; + virtual void deepSleep() override; + virtual void finalizeUpdate() override; +}; + +} // namespace NicheGraphics::Drivers +#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/variants/heltec_wireless_paper/nicheGraphics.h b/variants/heltec_wireless_paper/nicheGraphics.h index c8994b7f1..e42a4df85 100644 --- a/variants/heltec_wireless_paper/nicheGraphics.h +++ b/variants/heltec_wireless_paper/nicheGraphics.h @@ -19,12 +19,58 @@ // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/LCMEN2R13EFC1.h" +#include "graphics/niche/Drivers/EInk/E0213A367.h" #include "graphics/niche/Inputs/TwoButton.h" void setupNicheGraphics() { using namespace NicheGraphics; + pinMode(PIN_EINK_SCLK, OUTPUT); + pinMode(PIN_EINK_DC, OUTPUT); + pinMode(PIN_EINK_CS, OUTPUT); + pinMode(PIN_EINK_RES, OUTPUT); + + //rest e-ink + digitalWrite(PIN_EINK_RES, LOW); + delay(20); + digitalWrite(PIN_EINK_RES, HIGH); + delay(20); + + digitalWrite(PIN_EINK_DC, LOW); + digitalWrite(PIN_EINK_CS, LOW); + + // write cmd + uint8_t cmd = 0x2F; + pinMode(PIN_EINK_MOSI, OUTPUT); + digitalWrite(PIN_EINK_SCLK, LOW); + for (int i = 0; i < 8; i++) + { + digitalWrite(PIN_EINK_MOSI, (cmd & 0x80) ? HIGH : LOW); + cmd <<= 1; + digitalWrite(PIN_EINK_SCLK, HIGH); + delayMicroseconds(1); + digitalWrite(PIN_EINK_SCLK, LOW); + delayMicroseconds(1); + } + delay(10); + + digitalWrite(PIN_EINK_DC, HIGH); + pinMode(PIN_EINK_MOSI, INPUT_PULLUP); + + // read chip ID + uint8_t chipId = 0; + for (int8_t b = 7; b >= 0; b--) + { + digitalWrite(PIN_EINK_SCLK, LOW); + delayMicroseconds(1); + digitalWrite(PIN_EINK_SCLK, HIGH); + delayMicroseconds(1); + if (digitalRead(PIN_EINK_MOSI)) chipId |= (1 << b); + } + digitalWrite(PIN_EINK_CS, HIGH); + LOG_INFO("eink chipId: %02X", chipId); + // SPI // ----------------------------- @@ -34,8 +80,15 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - - Drivers::EInk *driver = new Drivers::LCMEN213EFC1; + Drivers::EInk *driver; + if((chipId &0x03) !=0x01) + { + driver = new Drivers::LCMEN213EFC1; + } + else + { + driver = new Drivers::E0213A367; + } driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); // InkHUD diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 51430ebff..762b793cc 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -8,6 +8,8 @@ build_flags = -I variants/heltec_wireless_paper -D HELTEC_WIRELESS_PAPER -D EINK_DISPLAY_MODEL=GxEPD2_213_FC1 + -D EINK_DISPLAY_MODEL1=GxEPD2_213_FC1 + -D EINK_DISPLAY_MODEL2=GxEPD2_213_E0213A367 -D EINK_WIDTH=250 -D EINK_HEIGHT=122 -D USE_EINK @@ -17,9 +19,9 @@ build_flags = -D EINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" lib_deps = ${esp32s3_base.lib_deps} - https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip + https://github.com/Quency-D/GxEPD2/archive/0513405847b281d9dea400488714643ef84507ec.zip lewisxhe/PCF8563_Library@^1.0.1 -upload_speed = 115200 +upload_speed = 921600 [env:heltec-wireless-paper-inkhud] extends = esp32s3_base, inkhud From 7a7166d57555f42156eb15a8923667e63fdb6a95 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 29 May 2025 10:17:20 -0500 Subject: [PATCH 225/238] Revert "Add a new screen for heltec_wireless_paper. (#6894)" (#6918) This reverts commit ba535433543f40b0e15280c7beb9e0afabe56142. --- src/graphics/EInkDisplay2.cpp | 64 +--- src/graphics/EInkDisplay2.h | 6 +- src/graphics/EInkMultiWrapper.h | 327 ------------------ src/graphics/niche/Drivers/EInk/E0213A367.cpp | 126 ------- src/graphics/niche/Drivers/EInk/E0213A367.h | 44 --- .../heltec_wireless_paper/nicheGraphics.h | 57 +-- variants/heltec_wireless_paper/platformio.ini | 6 +- 7 files changed, 6 insertions(+), 624 deletions(-) delete mode 100644 src/graphics/EInkMultiWrapper.h delete mode 100644 src/graphics/niche/Drivers/EInk/E0213A367.cpp delete mode 100644 src/graphics/niche/Drivers/EInk/E0213A367.h diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index b518299f7..5a2749482 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -174,7 +174,7 @@ bool EInkDisplay::connect() } } -#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \ +#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_VISION_MASTER_E213) || \ defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \ defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) { @@ -228,68 +228,6 @@ bool EInkDisplay::connect() auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *spi1); adafruitDisplay = new GxEPD2_BW(*lowLevel); - // Init GxEPD2 - adafruitDisplay->init(); - adafruitDisplay->setRotation(3); - } -#elif defined(HELTEC_WIRELESS_PAPER) - { - uint8_t model; - pinMode(PIN_EINK_SCLK, OUTPUT); - pinMode(PIN_EINK_DC, OUTPUT); - pinMode(PIN_EINK_CS, OUTPUT); - pinMode(PIN_EINK_RES, OUTPUT); - - //rest e-ink - digitalWrite(PIN_EINK_RES, LOW); - delay(20); - digitalWrite(PIN_EINK_RES, HIGH); - delay(20); - - digitalWrite(PIN_EINK_DC, LOW); - digitalWrite(PIN_EINK_CS, LOW); - - // write cmd - uint8_t cmd = 0x2F; - pinMode(PIN_EINK_MOSI, OUTPUT); - digitalWrite(PIN_EINK_SCLK, LOW); - for (int i = 0; i < 8; i++) - { - digitalWrite(PIN_EINK_MOSI, (cmd & 0x80) ? HIGH : LOW); - cmd <<= 1; - digitalWrite(PIN_EINK_SCLK, HIGH); - delayMicroseconds(1); - digitalWrite(PIN_EINK_SCLK, LOW); - delayMicroseconds(1); - } - delay(10); - - digitalWrite(PIN_EINK_DC, HIGH); - pinMode(PIN_EINK_MOSI, INPUT_PULLUP); - - // read chip ID - uint8_t chipId = 0; - for (int8_t b = 7; b >= 0; b--) - { - digitalWrite(PIN_EINK_SCLK, LOW); - delayMicroseconds(1); - digitalWrite(PIN_EINK_SCLK, HIGH); - delayMicroseconds(1); - if (digitalRead(PIN_EINK_MOSI)) chipId |= (1 << b); - } - digitalWrite(PIN_EINK_CS, HIGH); - LOG_INFO("eink chipId: %02X", chipId); - model = ((chipId&0x03) !=0x01) ? 1 : 2; - - // Start HSPI - hspi = new SPIClass(HSPI); - hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS - // VExt already enabled in setup() - // RTC GPIO hold disabled in setup() - - // Create GxEPD2 objects - adafruitDisplay = new EInkMultiWrapper(model, PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi); - // Init GxEPD2 adafruitDisplay->init(); adafruitDisplay->setRotation(3); diff --git a/src/graphics/EInkDisplay2.h b/src/graphics/EInkDisplay2.h index 965a3307a..93be197b0 100644 --- a/src/graphics/EInkDisplay2.h +++ b/src/graphics/EInkDisplay2.h @@ -4,7 +4,6 @@ #include "GxEPD2_BW.h" #include -#include "EinkMultiWrapper.h" /** * An adapter class that allows using the GxEPD2 library as if it was an OLEDDisplay implementation. @@ -65,11 +64,8 @@ class EInkDisplay : public OLEDDisplay virtual bool connect() override; // AdafruitGFX display object - instantiated in connect(), variant specific -#if defined(HELTEC_WIRELESS_PAPER) - EInkMultiWrapper *adafruitDisplay; -#else GxEPD2_BW *adafruitDisplay = NULL; -#endif + // If display uses HSPI #if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \ defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \ diff --git a/src/graphics/EInkMultiWrapper.h b/src/graphics/EInkMultiWrapper.h deleted file mode 100644 index 3ac0b194d..000000000 --- a/src/graphics/EInkMultiWrapper.h +++ /dev/null @@ -1,327 +0,0 @@ -// Wrapper class for GxEPD2_BW - -// Generic signature at build time, allowing display model to be detected at run-time -// Workaround for issue of GxEPD2_BW objects not having a shared base class -// Only exposes methods which we are actually using -#ifndef _EINKMULTIWRAPPER_H_ -#define _EINKMULTIWRAPPER_H_ - -#include "GxEPD2_BW.h" -#include "GxEPD2_EPD.h" - -template -class EInkMultiWrapper -{ -public: - void drawPixel(int16_t x, int16_t y, uint16_t color) - { - if (model == 1) - model1->drawPixel(x, y, color); - else - model2->drawPixel(x, y, color); - } - void init(uint32_t serial_diag_bitrate = 0) // = 0 : disabled - { - if (model == 1) - model1->init(serial_diag_bitrate); - else - model2->init(serial_diag_bitrate); - } - - void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 20, bool pulldown_rst_mode = false) - { - if (model == 1) - model1->init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode); - else - model2->init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode); - } - void fillScreen(uint16_t color) // 0x0 black, >0x0 white, to buffer - { - if (model == 1) - model1->fillScreen(color); - else - model2->fillScreen(color); - } - void display(bool partial_update_mode = false) - { - if (model == 1) - model1->display(partial_update_mode); - else - model2->display(partial_update_mode); - } - void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) - { - if (model == 1) - model1->displayWindow(x, y, w, h); - else - model2->displayWindow(x, y, w, h); - } - - void setFullWindow() - { - if (model == 1) - model1->setFullWindow(); - else - model2->setFullWindow(); - } - - void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) - { - if (model == 1) - model1->setPartialWindow(x, y, w, h); - else - model2->setPartialWindow(x, y, w, h); - } - - void firstPage() - { - if (model == 1) - model1->firstPage(); - else - model2->firstPage(); - } - void endAsyncFull() - { - if (model == 1) - model1->endAsyncFull(); - else - model2->endAsyncFull(); - } - - bool nextPage() - { - if (model == 1) - return model1->nextPage(); - else - return model2->nextPage(); - } - void drawPaged(void (*drawCallback)(const void*), const void* pv) - { - if (model == 1) - model1->drawPaged(drawCallback, pv); - else - model2->drawPaged(drawCallback, pv); - } - - void drawInvertedBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) - { - if (model == 1) - model1->drawInvertedBitmap(x, y, bitmap, w, h, color); - else - model2->drawInvertedBitmap(x, y, bitmap, w, h, color); - } - - void clearScreen(uint8_t value = 0xFF) // init controller memory and screen (default white) - { - if (model == 1) - model1->clearScreen(value); - else - model2->clearScreen(value); - } - void writeScreenBuffer(uint8_t value = 0xFF) // init controller memory (default white) - { - if (model == 1) - model1->writeScreenBuffer(value); - else - model2->writeScreenBuffer(value); - } - // write to controller memory, without screen refresh; x and w should be multiple of 8 - void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) - { - if (model == 1) - model1->writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm); - else - model2->writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm); - } - void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) - { - if (model == 1) - model1->writeImagePart(x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - else - model2->writeImagePart(x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - } - void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->writeImage(black, color, x, y, w, h, invert, mirror_y, pgm); - else - model2->writeImage(black, color, x, y, w, h, invert, mirror_y, pgm); - } - void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h) - { - if (model == 1) - model1->writeImage(black, color, x, y, w, h); - else - model2->writeImage(black, color, x, y, w, h); - } - void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->writeImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h, invert, mirror_y, pgm); - else - model2->writeImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h, invert, mirror_y, pgm); - } - - void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h) - { - if (model == 1) - model1->writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); - else - model2->writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); - } - // write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8 - void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); - else - model2->writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); - } - // write to controller memory, with screen refresh; x and w should be multiple of 8 - void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) - { - if (model == 1) - model1->drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm); - else - model2->drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm); - } - void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) - { - if (model == 1) - model1->drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - else - model2->drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - } - void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->drawImage(black, color, x, y, w, h, invert, mirror_y, pgm); - else - model2->drawImage(black, color, x, y, w, h, invert, mirror_y, pgm); - } - void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h) - { - if (model == 1) - model1->drawImage(black, color, x, y, w, h); - else - model2->drawImage(black, color, x, y, w, h); - } - void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - else - model2->drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); - } - void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, - int16_t x, int16_t y, int16_t w, int16_t h) - { - if (model == 1) - model1->drawImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); - else - model2->drawImagePart( black, color, x_part, y_part, w_bitmap, h_bitmap,x, y, w, h); - } - // write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8 - void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) - { - if (model == 1) - model1->drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); - else - model2->drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm); - } - void refresh(bool partial_update_mode = false) // screen refresh from controller memory to full screen - { - if (model == 1) - model1->refresh(partial_update_mode); - else - model2->refresh(partial_update_mode); - } - void refresh(int16_t x, int16_t y, int16_t w, int16_t h) // screen refresh from controller memory, partial screen - { - if (model == 1) - model1->refresh(x, y, w, h); - else - model2->refresh(x, y, w, h); - } - // turns off generation of panel driving voltages, avoids screen fading over time - void powerOff() - { - if (model == 1) - model1->powerOff(); - else - model2->powerOff(); - } - // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0) - void hibernate() - { - if (model == 1) - model1->hibernate(); - else - model2->hibernate(); - } - - void setRotation(uint8_t x) - { - if (model == 1) - model1->setRotation(x); - else - model2->setRotation(x); - } - - int16_t width() - { - if (model == 1) - return model1->width(); - else - return model2->width(); - } - - int16_t height() - { - if (model == 1) - return model1->height(); - else - return model2->height(); - } - - - // Exposes methods of the GxEPD2_EPD object which is usually available as GxEPD2_BW::epd - class Epd2Wrapper - { - public: - bool isBusy() { return m_epd2->isBusy(); } - GxEPD2_EPD *m_epd2; - } epd2; - - // Constructor - // Select driver by passing whichModel as 1 or 2 - EInkMultiWrapper(uint8_t whichModel, int16_t cs, int16_t dc, int16_t rst, int16_t busy, SPIClass &spi) - { - assert(whichModel == 1 || whichModel == 2); - model = whichModel; - // LOG_DEBUG("GxEPD2_BW_MultiWrapper using driver %d", model); - - if (model == 1) - { - model1 = new GxEPD2_BW(DISPLAY_MODEL_1(cs, dc, rst, busy, spi)); - epd2.m_epd2 = &(model1->epd2); - } - else if (model == 2) - { - model2 = new GxEPD2_BW(DISPLAY_MODEL_2(cs, dc, rst, busy, spi)); - epd2.m_epd2 = &(model2->epd2); - } - } - -private: - uint8_t model; - GxEPD2_BW *model1; - GxEPD2_BW *model2; -}; - -#endif \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/E0213A367.cpp b/src/graphics/niche/Drivers/EInk/E0213A367.cpp deleted file mode 100644 index 4f2a50ba7..000000000 --- a/src/graphics/niche/Drivers/EInk/E0213A367.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "./E0213A367.h" - -#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS - -using namespace NicheGraphics::Drivers; - -// Map the display controller IC's output to the connected panel -void E0213A367::configScanning() -{ - // "Driver output control" - sendCommand(0x01); - sendData(0xF9); - sendData(0x00); - // Values set here might be redundant: F9, 00 seems to be default -} - -// Specify which information is used to control the sequence of voltages applied to move the pixels -// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from -// the controller IC's OTP memory, when the update procedure begins. -void E0213A367::configWaveform() -{ - sendCommand(0x37); // Waveform ID register - sendData(0x40); // ByteA - sendData(0x80); // ByteB DM[7:0] - sendData(0x03); // ByteC DM[[15:8] - sendData(0x0E); // ByteD DM[[23:16] - - switch (updateType) { - case FAST: - sendCommand(0x3C); // Border waveform: - sendData(0x81); - break; - case FULL: - sendCommand(0x3C); // Border waveform: - sendData(0x01); - default: - // From OTP memory - break; - } -} - -void E0213A367::configUpdateSequence() -{ - switch (updateType) { - case FAST: - sendCommand(0x22); - sendData(0xFF); - break; - case FULL: - default: - sendCommand(0x22); // Set "update sequence" - sendData(0xF7); - break; - } -} - -// Once the refresh operation has been started, -// begin periodically polling the display to check for completion, using the normal Meshtastic threading code -// Only used when refresh is "async" -void E0213A367::detachFromUpdate() -{ - switch (updateType) { - case FAST: - return beginPolling(50, 500); // At least 500ms for fast refresh - case FULL: - default: - return beginPolling(100, 2000); // At least 2 seconds for full refresh - } -} -void E0213A367::configFullscreen() -{ - // Placing this code in a separate method because it's probably pretty consistent between displays - // Should make it tidier to override SSD16XX::configure - - // Define the boundaries of the "fullscreen" region, for the controller IC - static const uint16_t sx = bufferOffsetX; // Notice the offset - static const uint16_t sy = 0; - static const uint16_t ex = bufferRowSize + bufferOffsetX - 1; // End is "max index", not "count". Minus 1 handles this - static const uint16_t ey = height; - - // Split into bytes - static const uint8_t sy1 = sy & 0xFF; - static const uint8_t ey1 = ey & 0xFF; - - // Data entry mode - Left to Right, Top to Bottom - sendCommand(0x11); - sendData(0x03); - - // Select controller IC memory region to display a fullscreen image - sendCommand(0x44); // Memory X start - end - sendData(sx); - sendData(ex); - sendCommand(0x45); // Memory Y start - end - sendData(sy1); - sendData(ey1); - - // Place the cursor at the start of this memory region, ready to send image data x=0 y=0 - sendCommand(0x4E); // Memory cursor X - sendData(sx); - sendCommand(0x4F); // Memory cursor y - sendData(sy1); -} -void E0213A367::finalizeUpdate() -{ - // Put a copy of the image into the "old memory". - // Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place - // We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc. - if (updateType != FULL) { - writeNewImage(); // Only required by some controller variants. Todo: Override just for GDEY0154D678? - writeOldImage(); - sendCommand(0x7F); // Terminate image write without update - wait(); - } - - //After waking up from sleep mode, the local refresh is abnormal, which may be due to the loss of data in RAM. - // if ((pin_rst != 0xFF) && (updateType ==FULL)) - // deepSleep(); -} - -void E0213A367::deepSleep() -{ - sendCommand(0x10); // Enter deep sleep - sendData(0x03); // Will not retain image RAM -} - -#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/src/graphics/niche/Drivers/EInk/E0213A367.h b/src/graphics/niche/Drivers/EInk/E0213A367.h deleted file mode 100644 index c00d73378..000000000 --- a/src/graphics/niche/Drivers/EInk/E0213A367.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - -E-Ink display driver - - SSD1682 - - Manufacturer: WISEVAST - - Size: 2.13 inch - - Resolution: 122px x 255px - - Flex connector marking: HINK-E0213A162-FPC-A0 (Hidden, printed on back-side) - -*/ - -#pragma once - -#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS - -#include "configuration.h" - -#include "./SSD16XX.h" - -namespace NicheGraphics::Drivers -{ -class E0213A367 : public SSD16XX -{ - // Display properties - private: - static constexpr uint32_t width = 122; - static constexpr uint32_t height = 250; - static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST); - - public: - E0213A367() : SSD16XX(width, height, supported, 0) {} - - protected: - virtual void configScanning() override; - virtual void configWaveform() override; - virtual void configUpdateSequence() override; - virtual void detachFromUpdate() override; - virtual void configFullscreen() override; - virtual void deepSleep() override; - virtual void finalizeUpdate() override; -}; - -} // namespace NicheGraphics::Drivers -#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS \ No newline at end of file diff --git a/variants/heltec_wireless_paper/nicheGraphics.h b/variants/heltec_wireless_paper/nicheGraphics.h index e42a4df85..c8994b7f1 100644 --- a/variants/heltec_wireless_paper/nicheGraphics.h +++ b/variants/heltec_wireless_paper/nicheGraphics.h @@ -19,58 +19,12 @@ // Shared NicheGraphics components // -------------------------------- #include "graphics/niche/Drivers/EInk/LCMEN2R13EFC1.h" -#include "graphics/niche/Drivers/EInk/E0213A367.h" #include "graphics/niche/Inputs/TwoButton.h" void setupNicheGraphics() { using namespace NicheGraphics; - pinMode(PIN_EINK_SCLK, OUTPUT); - pinMode(PIN_EINK_DC, OUTPUT); - pinMode(PIN_EINK_CS, OUTPUT); - pinMode(PIN_EINK_RES, OUTPUT); - - //rest e-ink - digitalWrite(PIN_EINK_RES, LOW); - delay(20); - digitalWrite(PIN_EINK_RES, HIGH); - delay(20); - - digitalWrite(PIN_EINK_DC, LOW); - digitalWrite(PIN_EINK_CS, LOW); - - // write cmd - uint8_t cmd = 0x2F; - pinMode(PIN_EINK_MOSI, OUTPUT); - digitalWrite(PIN_EINK_SCLK, LOW); - for (int i = 0; i < 8; i++) - { - digitalWrite(PIN_EINK_MOSI, (cmd & 0x80) ? HIGH : LOW); - cmd <<= 1; - digitalWrite(PIN_EINK_SCLK, HIGH); - delayMicroseconds(1); - digitalWrite(PIN_EINK_SCLK, LOW); - delayMicroseconds(1); - } - delay(10); - - digitalWrite(PIN_EINK_DC, HIGH); - pinMode(PIN_EINK_MOSI, INPUT_PULLUP); - - // read chip ID - uint8_t chipId = 0; - for (int8_t b = 7; b >= 0; b--) - { - digitalWrite(PIN_EINK_SCLK, LOW); - delayMicroseconds(1); - digitalWrite(PIN_EINK_SCLK, HIGH); - delayMicroseconds(1); - if (digitalRead(PIN_EINK_MOSI)) chipId |= (1 << b); - } - digitalWrite(PIN_EINK_CS, HIGH); - LOG_INFO("eink chipId: %02X", chipId); - // SPI // ----------------------------- @@ -80,15 +34,8 @@ void setupNicheGraphics() // E-Ink Driver // ----------------------------- - Drivers::EInk *driver; - if((chipId &0x03) !=0x01) - { - driver = new Drivers::LCMEN213EFC1; - } - else - { - driver = new Drivers::E0213A367; - } + + Drivers::EInk *driver = new Drivers::LCMEN213EFC1; driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES); // InkHUD diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 762b793cc..51430ebff 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -8,8 +8,6 @@ build_flags = -I variants/heltec_wireless_paper -D HELTEC_WIRELESS_PAPER -D EINK_DISPLAY_MODEL=GxEPD2_213_FC1 - -D EINK_DISPLAY_MODEL1=GxEPD2_213_FC1 - -D EINK_DISPLAY_MODEL2=GxEPD2_213_E0213A367 -D EINK_WIDTH=250 -D EINK_HEIGHT=122 -D USE_EINK @@ -19,9 +17,9 @@ build_flags = -D EINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" lib_deps = ${esp32s3_base.lib_deps} - https://github.com/Quency-D/GxEPD2/archive/0513405847b281d9dea400488714643ef84507ec.zip + https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip lewisxhe/PCF8563_Library@^1.0.1 -upload_speed = 921600 +upload_speed = 115200 [env:heltec-wireless-paper-inkhud] extends = esp32s3_base, inkhud From b6cb0b148cdf2ed01f1a1dfd4f17ddb4e1838ece Mon Sep 17 00:00:00 2001 From: Austin Date: Thu, 29 May 2025 17:33:10 -0400 Subject: [PATCH 226/238] Fix renovate for Adafruit PCT2075 (#6919) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 125dfb573..ac74a352a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -163,7 +163,7 @@ lib_deps = sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 # renovate: datasource=custom.pio depName=Adafruit LTR390 Library packageName=adafruit/library/Adafruit LTR390 Library adafruit/Adafruit LTR390 Library@1.1.2 - # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/Adafruit PCT2075 + # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/library/Adafruit PCT2075 adafruit/Adafruit PCT2075@1.0.5 ; (not included in native / portduino) From f9d4fdbb52440ee35fb597c2dc7695b6d1cada75 Mon Sep 17 00:00:00 2001 From: ArgoNavi <63644530+ArgoNavi@users.noreply.github.com> Date: Fri, 30 May 2025 07:00:20 -0400 Subject: [PATCH 227/238] Update TSL2591Sensor.cpp (#6921) Lower gain and timing to avoid saturation in bright light --- src/modules/Telemetry/Sensor/TSL2591Sensor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp index beec3c70b..04443ebec 100644 --- a/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp +++ b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp @@ -23,8 +23,8 @@ int32_t TSL2591Sensor::runOnce() void TSL2591Sensor::setup() { - tsl.setGain(TSL2591_GAIN_MED); // 25x gain - tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); + tsl.setGain(TSL2591_GAIN_LOW); // 1x gain + tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); } bool TSL2591Sensor::getMetrics(meshtastic_Telemetry *measurement) @@ -41,4 +41,4 @@ bool TSL2591Sensor::getMetrics(meshtastic_Telemetry *measurement) return true; } -#endif \ No newline at end of file +#endif From 9799f10e6363703bf64490044dbac813f0ddf2ea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 08:38:13 -0500 Subject: [PATCH 228/238] Upgrade trunk (#6922) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 3a02034a6..f45bba826 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,7 +9,7 @@ plugins: lint: enabled: - checkov@3.2.435 - - renovate@40.33.8 + - renovate@40.34.4 - prettier@3.5.3 - trufflehog@3.88.34 - yamllint@1.37.1 From 284b8bcff283b05d320c81c4dcc64a6fe6e47104 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 31 May 2025 06:15:37 -0500 Subject: [PATCH 229/238] chore(deps): update meshtastic/device-ui digest to 37e2fb8 (#6925) 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 ac74a352a..40517eea0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/3dfcc973cdfec8b34719510952e160bbfb57d9df.zip + https://github.com/meshtastic/device-ui/archive/37e2fb84a8d1b7d8cc1e2ed00d34cfb1f284bd59.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 5cd74f4b53a70ce18303ccdee75260be2e689ea7 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 1 Jun 2025 21:03:38 -0500 Subject: [PATCH 230/238] Don't give LOG_INFO a null --- src/modules/Telemetry/HostMetrics.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp index dc4315efa..9a9d8fecc 100644 --- a/src/modules/Telemetry/HostMetrics.cpp +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -34,7 +34,8 @@ bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, sender, t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes, t->variant.host_metrics.freemem_bytes, static_cast(t->variant.host_metrics.load1) / 100, static_cast(t->variant.host_metrics.load5) / 100, - static_cast(t->variant.host_metrics.load15) / 100, t->variant.host_metrics.user_string); + static_cast(t->variant.host_metrics.load15) / 100, + t->variant.host_metrics.has_user_string ? t->variant.host_metrics.user_string : ""); #endif } return false; // Let others look at this message also if they want @@ -124,7 +125,8 @@ bool HostMetricsModule::sendMetrics() telemetry.variant.host_metrics.uptime_seconds, telemetry.variant.host_metrics.diskfree1_bytes, telemetry.variant.host_metrics.freemem_bytes, static_cast(telemetry.variant.host_metrics.load1) / 100, static_cast(telemetry.variant.host_metrics.load5) / 100, - static_cast(telemetry.variant.host_metrics.load15) / 100, telemetry.variant.host_metrics.user_string); + static_cast(telemetry.variant.host_metrics.load15) / 100, + telemetry.variant.host_metrics.has_user_string ? telemetry.variant.host_metrics.user_string : ""); meshtastic_MeshPacket *p = allocDataProtobuf(telemetry); p->to = NODENUM_BROADCAST; From d833a9ea61fcad0999944ff8879204fb8611e123 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:16:01 -0500 Subject: [PATCH 231/238] chore(deps): update meshtastic/device-ui digest to 04e3a07 (#6942) 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 40517eea0..095cf3b9d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/37e2fb84a8d1b7d8cc1e2ed00d34cfb1f284bd59.zip + https://github.com/meshtastic/device-ui/archive/04e3a075dc848f49e1344c5404ccce03a1876017.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From be0c7d73a34c73b68ee1277bb17f17af970493bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:16:24 -0500 Subject: [PATCH 232/238] Upgrade trunk (#6941) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> Co-authored-by: Ben Meadors --- .trunk/trunk.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index f45bba826..fd827e229 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,14 +9,14 @@ plugins: lint: enabled: - checkov@3.2.435 - - renovate@40.34.4 + - renovate@40.36.2 - prettier@3.5.3 - - trufflehog@3.88.34 + - trufflehog@3.88.35 - yamllint@1.37.1 - bandit@1.8.3 - - trivy@0.62.1 + - trivy@0.63.0 - taplo@0.9.3 - - ruff@0.11.11 + - ruff@0.11.12 - isort@6.0.1 - markdownlint@0.45.0 - oxipng@9.1.5 From 9ce44556ceaabaf1c6cd689d6390651dcc29d3de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:29:41 -0500 Subject: [PATCH 233/238] chore(deps): update meshtastic/device-ui digest to 649e095 (#6943) 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 095cf3b9d..ecde59de2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,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/04e3a075dc848f49e1344c5404ccce03a1876017.zip + https://github.com/meshtastic/device-ui/archive/649e0953508ee4aabf1171519ee2eb69fb125647.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 4d81280ac25a006fb66e2e954577e607de5b7e51 Mon Sep 17 00:00:00 2001 From: Kalle Lilja <15094562+ThatKalle@users.noreply.github.com> Date: Tue, 3 Jun 2025 03:35:26 +0200 Subject: [PATCH 234/238] Add --1200bps-reset param to device-install/update scripts (#6752) * add change-mode support * add change-mode support * tab to space * fix if check * change param name to 1200bps-reset * update help section * missed one in help seciton --------- Co-authored-by: Ben Meadors --- bin/device-install.bat | 21 +++++++++++++++++++-- bin/device-install.sh | 12 +++++++++++- bin/device-update.bat | 21 +++++++++++++++++++-- bin/device-update.sh | 16 +++++++++++++--- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/bin/device-install.bat b/bin/device-install.bat index 3ffca0b63..816d2fbba 100755 --- a/bin/device-install.bat +++ b/bin/device-install.bat @@ -12,6 +12,7 @@ SET "BIGDB16=0" SET "ESPTOOL_BAUD=115200" SET "ESPTOOL_CMD=" SET "LOGCOUNTER=0" +SET "BPS_RESET=0" @REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable. SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone" @@ -24,7 +25,7 @@ GOTO getopts :help ECHO Flash image file to device, but first erasing and writing system information. ECHO. -ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web) +ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web) [--1200bps-reset] ECHO. ECHO Options: ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required) @@ -35,13 +36,16 @@ ECHO -P python Specify alternate python interpreter to use to invoke ECHO If supplied the script will use python. ECHO If not supplied the script will try to find esptool in Path. ECHO --web Enable WebUI. (default: false) +ECHO --1200bps-reset Attempt to place the device in correct mode. (1200bps Reset) +ECHO Some hardware requires this twice. ECHO. +ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11 ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 --web GOTO eof :version -ECHO %SCRIPT_NAME% [Version 2.6.1] +ECHO %SCRIPT_NAME% [Version 2.6.2] ECHO Meshtastic GOTO eof @@ -58,10 +62,13 @@ IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT IF /I "%~1"=="--web" SET "WEB_APP=1" +IF /I "%~1"=="--1200bps-reset" SET "BPS_RESET=1" SHIFT GOTO getopts :endopts +IF %BPS_RESET% EQU 1 GOTO skip-filename + CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..." IF "__!FILENAME!__"=="____" ( CALL :LOG_MESSAGE DEBUG "Missing -f filename input." @@ -95,6 +102,9 @@ IF NOT "!FILENAME:update=!"=="!FILENAME!" ( CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!" ) +:skip-filename +SET "ESPTOOL_BAUD=1200" + CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..." IF NOT "__%PYTHON%__"=="____" ( SET "ESPTOOL_CMD=!PYTHON! -m esptool" @@ -133,6 +143,12 @@ IF "__!ESPTOOL_PORT!__" == "____" ( ) CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!." +IF %BPS_RESET% EQU 1 ( + @REM Attempt to change mode via 1200bps Reset. + CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status + GOTO eof +) + @REM Check if FILENAME contains "-tft-" and set target partitionScheme accordingly. @REM https://github.com/meshtastic/web-flasher/blob/main/types/resources.ts#L3 IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" ( @@ -254,6 +270,7 @@ EXIT /B %ERRORLEVEL% IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" CALL :RESET_ERROR !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4 +IF %BPS_RESET% EQU 1 GOTO :eof IF %ERRORLEVEL% NEQ 0 ( CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" EXIT /B %ERRORLEVEL% diff --git a/bin/device-install.sh b/bin/device-install.sh index 7fa5ffdbb..76765bb5f 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -2,6 +2,7 @@ PYTHON=${PYTHON:-$(which python3 python | head -n 1)} WEB_APP=false +BPS_RESET=false TFT_BUILD=false MCU="" @@ -72,7 +73,7 @@ set -e # Usage info show_help() { cat </dev/null 2>&1; then @@ -17,14 +18,15 @@ fi # Usage info show_help() { cat << EOF -Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] -Flash image file to device, leave existing system intact." +Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode] +Flash image file to device, leave existing system intact. -h Display this help and exit -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous). -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON") -f FILENAME The *update.bin file to flash. Custom to your device type. - + --change-mode Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset) + EOF } @@ -41,6 +43,9 @@ while getopts ":hp:P:f:" opt; do ;; f) FILENAME=${OPTARG} ;; + --change-mode) + CHANGE_MODE=true + ;; *) echo "Invalid flag." show_help >&2 @@ -50,6 +55,11 @@ while getopts ":hp:P:f:" opt; do done shift "$((OPTIND-1))" +if [[ $CHANGE_MODE == true ]]; then + $ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status + exit 0 +fi + [ -z "$FILENAME" -a -n "$1" ] && { FILENAME=$1 shift From a5716cf25c6ad17a1473306fac5656669c351ad5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 07:08:46 -0500 Subject: [PATCH 235/238] automated bumps (#6944) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ debian/changelog | 7 +++++-- version.properties | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 30f684fef..40f86fb0b 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.11 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.10 diff --git a/debian/changelog b/debian/changelog index 87e3aea9b..4b67eecd4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -meshtasticd (2.6.10.0) UNRELEASED; urgency=medium +meshtasticd (2.6.11.0) UNRELEASED; urgency=medium [ Austin Lane ] * Initial packaging @@ -16,4 +16,7 @@ meshtasticd (2.6.10.0) UNRELEASED; urgency=medium [ ] * GitHub Actions Automatic version bump - -- Sun, 25 May 2025 20:46:49 +0000 + [ ] + * GitHub Actions Automatic version bump + + -- Mon, 02 Jun 2025 20:00:55 +0000 diff --git a/version.properties b/version.properties index 71de951f1..e13094769 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 10 +build = 11 From 55b2bbf93756fc7bbbfdbc7cbf29f88e6b637f22 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 4 Jun 2025 12:16:37 -0500 Subject: [PATCH 236/238] Generate keys when Lora Region is set (#6951) * Generate keys when Lora Region changes * Nest the ifs * Even more entropy * Namespacing --- src/mesh/CryptoEngine.cpp | 13 +++++++++++++ src/mesh/NodeDB.cpp | 2 +- src/modules/AdminModule.cpp | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/mesh/CryptoEngine.cpp b/src/mesh/CryptoEngine.cpp index d32b73855..82d0a9f57 100644 --- a/src/mesh/CryptoEngine.cpp +++ b/src/mesh/CryptoEngine.cpp @@ -3,12 +3,17 @@ #include "architecture.h" #if !(MESHTASTIC_EXCLUDE_PKI) +#include "NodeDB.h" #include "aes-ccm.h" #include "meshUtils.h" #include #include +#include #include #if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN) +#if !defined(ARCH_STM32WL) +#define CryptRNG RNG +#endif /** * Create a public/private key pair with Curve25519. @@ -18,6 +23,14 @@ */ void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey) { + // Mix in any randomness we can, to make key generation stronger. + CryptRNG.begin(optstr(APP_VERSION)); + if (myNodeInfo.device_id.size == 16) { + CryptRNG.stir(myNodeInfo.device_id.bytes, myNodeInfo.device_id.size); + } + auto noise = random(); + CryptRNG.stir((uint8_t *)&noise, sizeof(noise)); + LOG_DEBUG("Generate Curve25519 keypair"); Curve25519::dh1(public_key, private_key); memcpy(pubKey, public_key, sizeof(public_key)); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 28af7d308..0a79f94a8 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -261,7 +261,7 @@ NodeDB::NodeDB() #if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN || MESHTASTIC_EXCLUDE_PKI) - if (!owner.is_licensed) { + if (!owner.is_licensed && config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET) { bool keygenSuccess = false; if (config.security.private_key.size == 32) { if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) { diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 3ff4fa74d..4005222dc 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -661,6 +661,24 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) 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) { + if (!owner.is_licensed) { + bool keygenSuccess = false; + if (config.security.private_key.size == 32) { + if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) { + keygenSuccess = true; + } + } else { + LOG_INFO("Generate new PKI keys"); + crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes); + keygenSuccess = true; + } + if (keygenSuccess) { + config.security.public_key.size = 32; + config.security.private_key.size = 32; + owner.public_key.size = 32; + memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32); + } + } config.lora.tx_enabled = true; initRegion(); if (myRegion->dutyCycle < 100) { From 76f72074632e0709c5f4f88c372c09129403e3f6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:15:51 -0500 Subject: [PATCH 237/238] chore(deps): update meshtastic/web to v2.6.4 (#6950) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- bin/web.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/web.version b/bin/web.version index a4db534a2..e46a05b19 100644 --- a/bin/web.version +++ b/bin/web.version @@ -1 +1 @@ -2.5.3 \ No newline at end of file +2.6.4 \ No newline at end of file From 070deb290f56735da581fb3d2225cde63d611f8d Mon Sep 17 00:00:00 2001 From: Andrew Yong Date: Thu, 5 Jun 2025 19:45:43 +0800 Subject: [PATCH 238/238] seeed_xiao_nrf52840_kit improvements (#6930) * feat: seeed_xiao_nrf52840_kit improvements - LEDs: - Change RGB LED to be active low as it is common anode - Remove re-definition of LED_PIN - Use red LED to indicate flash writes - Use blue LED as user LED (External Notification module) - GPIO: Re-word unused BUTTON_PIN comment - Wire: Set I2C pins to match XIAO nRF52840 Sense's LSM6DS3TR IMU - Battery: - Use charge LED to detect charging state - Move voltage divider boilerplate out of src/main.cpp and into initVariant() - Fix dependencies for above in related XIAO BLE DIY variants Build tested variants: - seeed_xiao_nrf52840_kit - xiao_ble - seeed-xiao-nrf52840-wio-sx1262 Flashed to and tested on hardware: - seeed_xiao_nrf52840_kit Signed-off-by: Andrew Yong * chore(seeed_xiao_nrf52840_kit): Re-order generic GPIO definitions Signed-off-by: Andrew Yong * chore: Use ADC_CTRL for XIAO nRF52840 Signed-off-by: Andrew Yong --------- Signed-off-by: Andrew Yong --- src/main.cpp | 13 --- .../variant.cpp | 9 +- .../seeed-xiao-nrf52840-wio-sx1262/variant.h | 3 +- variants/seeed_xiao_nrf52840_kit/variant.cpp | 28 ++--- variants/seeed_xiao_nrf52840_kit/variant.h | 101 +++++++++--------- variants/xiao_ble/variant.cpp | 9 +- variants/xiao_ble/variant.h | 5 +- 7 files changed, 88 insertions(+), 80 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7a11ca2e0..2d49b2fbe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -482,19 +482,6 @@ void setup() fsInit(); -#if defined(_SEEED_XIAO_NRF52840_SENSE_H_) - - pinMode(CHARGE_LED, INPUT); // sets to detect if charge LED is on or off to see if USB is plugged in - - pinMode(HICHG, OUTPUT); - digitalWrite(HICHG, LOW); // 100 mA charging current if set to LOW and 50mA (actually about 20mA) if set to HIGH - - pinMode(BAT_READ, OUTPUT); - digitalWrite(BAT_READ, LOW); // This is pin P0_14 = 14 and by pullling low to GND it provices path to read on pin 32 (P0,31) - // PIN_VBAT the voltage from divider on XIAO board - -#endif - #if !MESHTASTIC_EXCLUDE_I2C #if defined(I2C_SDA1) && defined(ARCH_RP2040) Wire1.setSDA(I2C_SDA1); diff --git a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp index 2c6c3e539..300f69d0b 100644 --- a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp @@ -52,4 +52,11 @@ const uint32_t g_ADigitalPinMap[] = { // VBAT 31, // D32 is P0.10 (VBAT) -}; \ No newline at end of file +}; + +void initVariant() +{ + // Set BQ25101 ISET to 100mA instead of 50mA + pinMode(HICHG, OUTPUT); + digitalWrite(HICHG, LOW); +} diff --git a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h index 7a76727f2..277377d71 100644 --- a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h @@ -164,7 +164,8 @@ static const uint8_t SCK = PIN_SPI_SCK; // ------- // P0_14 = 14 Reads battery voltage from divider on signal board. // PIN_VBAT is reading voltage divider on XIAO and is program pin 32 / or P0.31 -#define BAT_READ 14 +#define ADC_CTRL VBAT_ENABLE +#define ADC_CTRL_ENABLED LOW #define BATTERY_SENSE_RESOLUTION_BITS 10 #define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED #define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge diff --git a/variants/seeed_xiao_nrf52840_kit/variant.cpp b/variants/seeed_xiao_nrf52840_kit/variant.cpp index 22072312a..70cadf5db 100644 --- a/variants/seeed_xiao_nrf52840_kit/variant.cpp +++ b/variants/seeed_xiao_nrf52840_kit/variant.cpp @@ -34,9 +34,9 @@ const uint32_t g_ADigitalPinMap[] = { 11, // D18 is P0.11 (6D_INT1) // MIC - 42, // 17,//42, // D19 is P1.10 (MIC_PWR) - 32, // 26,//32, // D20 is P1.00 (PDM_CLK) - 16, // 25,//16, // D21 is P0.16 (PDM_DATA) + 42, // D19 is P1.10 (MIC_PWR) + 32, // D20 is P1.00 (PDM_CLK) + 16, // D21 is P0.16 (PDM_DATA) // BQ25100 13, // D22 is P0.13 (HICHG) @@ -80,13 +80,17 @@ const uint32_t g_ADigitalPinMap[] = { void initVariant() { - // LED1 & LED2 - pinMode(21, OUTPUT); - digitalWrite(21, LOW); - // LED1 & LED2 - pinMode(22, OUTPUT); - digitalWrite(22, LOW); + // Set BQ25101 ISET to 100mA instead of 50mA + pinMode(HICHG, OUTPUT); + digitalWrite(HICHG, LOW); - pinMode(PIN_WIRE_SDA, INPUT_PULLUP); - pinMode(PIN_WIRE_SCL, INPUT_PULLUP); -} \ No newline at end of file + // LEDs + 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/seeed_xiao_nrf52840_kit/variant.h b/variants/seeed_xiao_nrf52840_kit/variant.h index 869c3d405..e6ef74e2e 100644 --- a/variants/seeed_xiao_nrf52840_kit/variant.h +++ b/variants/seeed_xiao_nrf52840_kit/variant.h @@ -19,31 +19,12 @@ extern "C" { #define PINS_COUNT (33) #define NUM_DIGITAL_PINS (33) -#define NUM_ANALOG_INPUTS (8) // A6 is used for battery, A7 is analog reference +#define NUM_ANALOG_INPUTS (8) #define NUM_ANALOG_OUTPUTS (0) -// LEDs - -#define LED_RED 11 -#define LED_BLUE 12 -#define LED_GREEN 13 - -#define PIN_LED1 LED_GREEN -#define PIN_LED2 LED_BLUE -#define PIN_LED3 LED_RED - -#define PIN_LED PIN_LED1 -#define LED_PWR (PINS_COUNT) - -#define LED_BUILTIN PIN_LED - -#define LED_STATE_ON 1 // State when LED is lit - /* - * Buttons + * Digital Pins */ - -// Digital PINs #define D0 (0ul) #define D1 (1ul) #define D2 (2ul) @@ -56,15 +37,6 @@ extern "C" { #define D9 (9ul) #define D10 (10ul) -/*Due to the lack of pins,and have to make sure gps standby work well we have temporarily removed the button. -There are some technical solutions that can solve this problem, -and we are currently exploring and researching them*/ - -// #define BUTTON_PIN D0 // This is the Program Button -// // #define BUTTON_NEED_PULLUP 1 -// #define BUTTON_ACTIVE_LOW true -// #define BUTTON_ACTIVE_PULLUP false - /* * Analog pins */ @@ -85,6 +57,38 @@ static const uint8_t A4 = PIN_A4; static const uint8_t A5 = PIN_A5; #define ADC_RESOLUTION 12 +/* + * LEDs + */ +#define LED_STATE_ON (0) // RGB LED is common anode +#define LED_RED (11) +#define LED_GREEN (13) +#define LED_BLUE (12) + +#define PIN_LED1 LED_GREEN // PIN_LED1 is used in src/platform/nrf52/architecture.h to define LED_PIN +#define PIN_LED2 LED_BLUE +#define PIN_LED3 LED_RED + +#define LED_BUILTIN LED_RED // LED_BUILTIN is used by framework-arduinoadafruitnrf52 to indicate flash writes + +#define LED_PWR LED_RED +#define USER_LED LED_BLUE + +/* + * Buttons + */ + +/* + * D0 is shared with PIN_GPS_STANDBY on the L76K GNSS Module. + * There are some technical solutions that can solve this problem, and we are + * currently exploring and researching them. + */ + +// #define BUTTON_PIN D0 + +/* + * Serial Interfaces + */ #define PIN_SERIAL2_RX (-1) #define PIN_SERIAL2_TX (-1) @@ -102,11 +106,9 @@ static const uint8_t MOSI = PIN_SPI_MOSI; static const uint8_t MISO = PIN_SPI_MISO; static const uint8_t SCK = PIN_SPI_SCK; -// supported modules list #define USE_SX1262 -// common pinouts for SX126X modules - +// Pinout for SX126X #define SX126X_CS D4 #define SX126X_DIO1 D1 #define SX126X_BUSY D3 @@ -121,16 +123,19 @@ static const uint8_t SCK = PIN_SPI_SCK; /* * Wire Interfaces */ - #define I2C_NO_RESCAN // I2C is a bit finicky, don't scan too much #define WIRE_INTERFACES_COUNT 1 // 2 -#define PIN_WIRE_SDA (24) // change to use the correct pins if needed -#define PIN_WIRE_SCL (25) // change to use the correct pins if needed +// LSM6DS3TR on XIAO nRF52840 Series +#define PIN_WIRE_SDA (17) +#define PIN_WIRE_SCL (16) static const uint8_t SDA = PIN_WIRE_SDA; static const uint8_t SCL = PIN_WIRE_SCL; +/* + * GPS + */ // GPS L76KB #define GPS_L76K #ifdef GPS_L76K @@ -144,20 +149,18 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define PIN_GPS_STANDBY D0 #endif -// Battery +/* + * Battery + */ +#define BATTERY_PIN PIN_VBAT // P0.31: VBAT voltage divider +#define ADC_MULTIPLIER (3) // ... R17=1M, R18=510k +#define ADC_CTRL VBAT_ENABLE // P0.14: VBAT voltage divider +#define ADC_CTRL_ENABLED LOW // ... sink +#define EXT_CHRG_DETECT (23) // P0.17: Charge LED +#define EXT_CHRG_DETECT_VALUE LOW // ... BQ25101 ~CHG indicates charging +#define HICHG (22) // P0.13: BQ25101 ISET 100mA instead of 50mA -#define BAT_READ \ - 14 // P0_14 = 14 Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is - // program pin 32 / or P0.31) -#define BATTERY_SENSE_RESOLUTION_BITS 10 -#define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED -#define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge - -// The battery sense is hooked to pin A0 (5) -#define BATTERY_PIN PIN_VBAT // PIN_A0 - -// ratio of voltage divider = 3.0 (R17=1M, R18=510k) -#define ADC_MULTIPLIER 3 // 3.0 + a bit for being optimistic +#define BATTERY_SENSE_RESOLUTION_BITS (10) #ifdef __cplusplus } diff --git a/variants/xiao_ble/variant.cpp b/variants/xiao_ble/variant.cpp index 2c6c3e539..300f69d0b 100644 --- a/variants/xiao_ble/variant.cpp +++ b/variants/xiao_ble/variant.cpp @@ -52,4 +52,11 @@ const uint32_t g_ADigitalPinMap[] = { // VBAT 31, // D32 is P0.10 (VBAT) -}; \ No newline at end of file +}; + +void initVariant() +{ + // Set BQ25101 ISET to 100mA instead of 50mA + pinMode(HICHG, OUTPUT); + digitalWrite(HICHG, LOW); +} diff --git a/variants/xiao_ble/variant.h b/variants/xiao_ble/variant.h index b46aa96ae..e511c6869 100644 --- a/variants/xiao_ble/variant.h +++ b/variants/xiao_ble/variant.h @@ -189,9 +189,8 @@ static const uint8_t SCL = PIN_WIRE_SCL; // Battery -#define BAT_READ \ - 14 // P0_14 = 14 Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is - // program pin 32 / or P0.31) +#define ADC_CTRL VBAT_ENABLE // P0.14: VBAT voltage divider +#define ADC_CTRL_ENABLED LOW // ... sink #define BATTERY_SENSE_RESOLUTION_BITS 10 #define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED #define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge