From ae887590594de8e573ca2ce16334f5534ce34155 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Tue, 1 Apr 2025 13:08:23 +1300 Subject: [PATCH] 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