Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions generated/ui_480x222
6 changes: 6 additions & 0 deletions include/graphics/driver/DisplayDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class DisplayDriver
virtual void printConfig(void) {}
virtual ~DisplayDriver() {}

// Request display wake from any context (thread-safe)
static void requestWake(void) { wakeRequested = true; }
static bool isWakeRequested(void) { return wakeRequested; }
static void clearWakeRequest(void) { wakeRequested = false; }

virtual uint8_t getBrightness() { return 255; }
virtual void setBrightness(uint8_t timeout) {}

Expand All @@ -42,4 +47,5 @@ class DisplayDriver
DeviceGUI *view;
uint16_t screenWidth;
uint16_t screenHeight;
static volatile bool wakeRequested;
};
12 changes: 8 additions & 4 deletions include/graphics/driver/LGFXDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,15 @@ template <class LGFX> void LGFXDriver<LGFX>::task_handler(void)
pin_int = BUTTON_PIN;
#endif
}
// Check wake conditions: GPIO interrupt, activity timeout, or explicit wake request
if ((pin_int >= 0 && DisplayDriver::view->sleep(pin_int)) ||
(screenTimeout + 50 > lv_display_get_inactive_time(NULL) && !DisplayDriver::view->isScreenLocked())) {
(screenTimeout + 50 > lv_display_get_inactive_time(NULL) && !DisplayDriver::view->isScreenLocked()) ||
DisplayDriver::isWakeRequested()) {
delay(2); // let the CPU finish to restore all register in case of light sleep
// woke up by touch or button
// woke up by touch, button, or external wake request
ILOG_INFO("leaving powersave");
powerSaving = false;
DisplayDriver::clearWakeRequest();
DisplayDriver::view->triggerHeartbeat();
lgfx->powerSaveOff();
lgfx->wakeup();
Expand All @@ -152,12 +155,13 @@ template <class LGFX> void LGFXDriver<LGFX>::task_handler(void)
lgfx->powerSaveOn();
powerSaving = true;
}
if (screenTimeout > lv_display_get_inactive_time(NULL)) {
if (screenTimeout > lv_display_get_inactive_time(NULL) || DisplayDriver::isWakeRequested()) {
DisplayDriver::view->blankScreen(false);
lgfx->powerSaveOff();
lgfx->wakeup();
powerSaving = false;
lv_disp_trig_activity(NULL);
DisplayDriver::clearWakeRequest();
lv_display_trigger_activity(NULL);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions include/graphics/view/TFT/TFTView_320x240.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ class TFTView_320x240 : public MeshtasticView
static void ui_event_BluetoothButton(lv_event_t *e);

// static void ui_event_HomeButton(lv_event_t * e);
static void ui_event_MainButtonFocus(lv_event_t *e);
static void ui_event_GlobalKeyHandler(lv_event_t *e);
static void ui_event_NodesButton(lv_event_t *e);
static void ui_event_GroupsButton(lv_event_t *e);
static void ui_event_MessagesButton(lv_event_t *e);
Expand Down
431 changes: 421 additions & 10 deletions include/graphics/view/TFT/TFTView_480x222.h

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions include/input/I2CKeyboardInputDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
#include <memory>
#include <string>

// Callback type for navigation events (e.g., backspace -> focus home button)
typedef void (*NavigationCallback)(void);

// Callback type for scroll events (direction: +1 = down, -1 = up)
typedef void (*ScrollCallback)(int direction);

// Callback type for alt/sym indicator updates
typedef void (*AltIndicatorCallback)(bool active);

// Callback type for input events (to wake screen on keypress)
typedef void (*InputEventCallback)(void);

class I2CKeyboardInputDriver : public InputDriver
{
public:
Expand All @@ -23,7 +35,31 @@ class I2CKeyboardInputDriver : public InputDriver
using KeyboardList = std::list<std::unique_ptr<KeyboardDefinition>>;
static KeyboardList &getI2CKeyboardList(void) { return i2cKeyboardList; }

// Navigation callback for backspace when not in text field
static void setNavigateHomeCallback(NavigationCallback cb) { navigateHomeCallback = cb; }
static NavigationCallback getNavigateHomeCallback(void) { return navigateHomeCallback; }

// ALT modifier state for scroll-while-typing feature
static bool isAltModifierHeld(void) { return altModifierHeld; }
static void setAltModifierHeld(bool held);

// Scroll callback for alt+encoder scrolling
static void setScrollCallback(ScrollCallback cb) { scrollCallback = cb; }
static ScrollCallback getScrollCallback(void) { return scrollCallback; }

// Alt/Sym indicator callback for UI updates
static void setAltIndicatorCallback(AltIndicatorCallback cb) { altIndicatorCallback = cb; }

// Input event callback to wake screen on keypress
static void setInputEventCallback(InputEventCallback cb) { inputEventCallback = cb; }
static InputEventCallback getInputEventCallback(void) { return inputEventCallback; }

protected:
static NavigationCallback navigateHomeCallback;
static bool altModifierHeld;
static ScrollCallback scrollCallback;
static AltIndicatorCallback altIndicatorCallback;
static InputEventCallback inputEventCallback;
bool registerI2CKeyboard(I2CKeyboardInputDriver *driver, std::string name, uint8_t address);

private:
Expand Down
26 changes: 26 additions & 0 deletions include/input/RotaryEncoderInputDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "input/InputDriver.h"

class RotaryEncoder;

/**
* @brief Input driver for quadrature rotary encoders with push button.
* Uses the RotaryEncoder library for proper quadrature decoding.
* Designed for devices like T-Lora-Pager that have a scroll wheel.
*/
class RotaryEncoderInputDriver : public InputDriver
{
public:
RotaryEncoderInputDriver(void);
virtual void init(void) override;
virtual void task_handler(void) override;
virtual ~RotaryEncoderInputDriver(void);

protected:
static void encoder_read(lv_indev_t *indev, lv_indev_data_t *data);

private:
static RotaryEncoder *rotary;
static volatile int16_t encoderDiff;
};
3 changes: 2 additions & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"ArduinoThread": "https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip",
"lvgl/lvgl": "9.3.0",
"greiman/SdFat": "https://github.com/mverch67/SdFat/archive/152a52251fc5e1d581303b42378ea712ab229246.zip",
"nanopb/Nanopb": "0.4.91"
"nanopb/Nanopb": "0.4.91",
"RotaryEncoder": "https://github.com/mverch67/RotaryEncoder/archive/da958a21389cbcd485989705df602a33e092dd88.zip"
},
"build": {
"libArchive": true,
Expand Down
18 changes: 15 additions & 3 deletions source/graphics/DeviceGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ static I2CKeyboardInputDriver *keyboardDriver = nullptr;
#include "input/LinuxInputDriver.h"
static LinuxInputDriver *linuxInputDriver = nullptr;
#else
#if defined(INPUTDRIVER_ENCODER_TYPE)
#if defined(INPUTDRIVER_ROTARY_TYPE)
#include "input/RotaryEncoderInputDriver.h"
static RotaryEncoderInputDriver *rotaryEncoderDriver = nullptr;
#elif defined(INPUTDRIVER_ENCODER_TYPE)
#include "input/EncoderInputDriver.h"
static EncoderInputDriver *encoderDriver = nullptr;
#endif
Expand All @@ -38,7 +41,9 @@ DeviceGUI::DeviceGUI(const DisplayDriverConfig *cfg, DisplayDriver *driver) : di
// else
// linuxInputDriver = InputDriver::instance();
#else
#if defined(INPUTDRIVER_ENCODER_TYPE)
#if defined(INPUTDRIVER_ROTARY_TYPE)
rotaryEncoderDriver = new RotaryEncoderInputDriver;
#elif defined(INPUTDRIVER_ENCODER_TYPE)
encoderDriver = new EncoderInputDriver;
#endif
#if defined(INPUTDRIVER_MATRIX_TYPE)
Expand Down Expand Up @@ -66,7 +71,10 @@ void DeviceGUI::init(IClientBase *client)
if (linuxInputDriver)
linuxInputDriver->init();
#endif
#if defined(INPUTDRIVER_ENCODER_TYPE)
#if defined(INPUTDRIVER_ROTARY_TYPE)
if (rotaryEncoderDriver)
rotaryEncoderDriver->init();
#elif defined(INPUTDRIVER_ENCODER_TYPE)
if (encoderDriver)
encoderDriver->init();
#endif
Expand Down Expand Up @@ -105,6 +113,10 @@ void DeviceGUI::task_handler(void)
}
#else
displaydriver->task_handler();
#if defined(INPUTDRIVER_ROTARY_TYPE)
if (rotaryEncoderDriver)
rotaryEncoderDriver->task_handler();
#endif
#endif
};

Expand Down
Loading