mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-28 13:40:32 +00:00
* TwoButtonExtened mirrors TwoButton but added joystick functionality * basic ui navigation with a joystick settings->joystick.enabled setting added and SETTINGS_VERSION incremented by one in InkHUD/Persistence.h in seeed_wio_tracker_L1_eink/nicheGraphics.h enable joystick and disable "Next Tile" menu item in implement prevTile and prevApplet functions in InkHUD/WindowManager.h,cpp and InkHUD/InkHUD.h,cpp onStickCenterShort, onStickCenterLong, onStickUp, onStickDown, onStickLeft, and onStickRight functions added to: - InkHUD/InkHUD.h,cpp - InkHUD/Events.h,cpp - InkHUD/Applet.h change navigation actions in InkHUD/Events.cpp events based on whether the joystick is enabled or not in seeed_wio_tracker_L1_eink/nicheGraphics.h connect joystick events to the new joystick handler functions * handle joystick input in NotificationApplet and TipsApplet Both the joystick center short press and the user button short press can be used to advance through the Tips applet. dismiss notifications with any joystick input * MenuApplet controls allows menu navigation including a back button * add AlignStickApplet for aligning the joystick with the screen add joystick.aligned and joystick.alignment to InkHUD/Persistence.h for storing alignment status and relative angle create AlignStick applet that prompts the user for a joystick input and rotates the controls to align with the screen AlignStick applet is run after the tips applet if the joystick is enabled and not aligned add menu item for opening the AlignStick applet * update tips applet with joystick controls * format InkHUD additions * fix stroke consistency when resizing joystick graphic * tweak button tips for order consistency * increase joystick debounce * fix comments * remove unnecessary '+' * remap joystick controls to match standard inkHUD behavior Input with a joystick now behaves as follows User Button (joystick center): - short press in applet -> opens menu - long press in applet -> opens menu - short press in menu -> selects - long press in menu -> selects Exit Button: - short press in applet -> switches tile - long press in applet -> nothing for now - short press in menu -> closes menu - long press in menu -> nothing for now --------- Co-authored-by: scobert <scobert57@gmail.com> Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
137 lines
4.6 KiB
C++
137 lines
4.6 KiB
C++
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
|
|
|
/*
|
|
|
|
Re-usable NicheGraphics input source
|
|
|
|
Short and Long press for up to two buttons
|
|
Interrupt driven
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
This expansion adds support for four more buttons
|
|
These buttons are single-action only, no long press
|
|
Interrupt driven
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "configuration.h"
|
|
|
|
#include "assert.h"
|
|
#include "functional"
|
|
|
|
#ifdef ARCH_ESP32
|
|
#include "esp_sleep.h" // For light-sleep handling
|
|
#endif
|
|
|
|
#include "Observer.h"
|
|
|
|
namespace NicheGraphics::Inputs
|
|
{
|
|
|
|
class TwoButtonExtended : protected concurrency::OSThread
|
|
{
|
|
public:
|
|
typedef std::function<void()> Callback;
|
|
|
|
static uint8_t getUserButtonPin(); // Resolve the GPIO, considering the various possible source of definition
|
|
|
|
static TwoButtonExtended *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 internalPullup = false);
|
|
void setJoystickWiring(uint8_t uPin, uint8_t dPin, uint8_t lPin, uint8_t rPin, bool internalPullup = false);
|
|
void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs);
|
|
void setJoystickDebounce(uint32_t debounceMs);
|
|
void setHandlerDown(uint8_t whichButton, Callback onDown);
|
|
void setHandlerUp(uint8_t whichButton, Callback onUp);
|
|
void setHandlerShortPress(uint8_t whichButton, Callback onShortPress);
|
|
void setHandlerLongPress(uint8_t whichButton, Callback onLongPress);
|
|
void setJoystickDownHandlers(Callback uDown, Callback dDown, Callback ldown, Callback rDown);
|
|
void setJoystickUpHandlers(Callback uUp, Callback dUp, Callback lUp, Callback rUp);
|
|
void setJoystickPressHandlers(Callback uPress, Callback dPress, Callback lPress, Callback rPress);
|
|
|
|
// Disconnect and reconnect interrupts for light sleep
|
|
#ifdef ARCH_ESP32
|
|
int beforeLightSleep(void *unused);
|
|
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
|
|
#endif
|
|
|
|
private:
|
|
// Internal state of a specific button
|
|
enum State {
|
|
REST, // Up, no activity
|
|
IRQ, // Down detected, not yet handled
|
|
POLLING_UNFIRED, // Down handled, polling for release
|
|
POLLING_FIRED, // Longpress fired, button still held
|
|
};
|
|
|
|
// Joystick Directions
|
|
enum Direction { UP = 0, DOWN, LEFT, RIGHT };
|
|
|
|
// Data used for direction (single-action) buttons
|
|
class SimpleButton
|
|
{
|
|
public:
|
|
// Per-button config
|
|
uint8_t pin = 0xFF; // 0xFF: unset
|
|
volatile State state = State::REST; // Internal state
|
|
volatile uint32_t irqAtMillis; // millis() when button went down
|
|
|
|
// Per-button event callbacks
|
|
static void noop(){};
|
|
std::function<void()> onDown = noop;
|
|
std::function<void()> onUp = noop;
|
|
std::function<void()> onPress = noop;
|
|
};
|
|
|
|
// Data used for double-action buttons
|
|
class Button : public SimpleButton
|
|
{
|
|
public:
|
|
// Per-button extended config
|
|
bool activeLogic = LOW; // Active LOW by default.
|
|
uint32_t debounceLength = 50; // Minimum length for shortpress in ms
|
|
uint32_t longpressLength = 500; // Time until longpress in ms
|
|
|
|
// Per-button event callbacks
|
|
std::function<void()> onLongPress = noop;
|
|
};
|
|
|
|
#ifdef ARCH_ESP32
|
|
// Get notified when lightsleep begins and ends
|
|
CallbackObserver<TwoButtonExtended, void *> lsObserver =
|
|
CallbackObserver<TwoButtonExtended, void *>(this, &TwoButtonExtended::beforeLightSleep);
|
|
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t> lsEndObserver =
|
|
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t>(this, &TwoButtonExtended::afterLightSleep);
|
|
#endif
|
|
|
|
int32_t runOnce() override; // Timer method. Polls for button release
|
|
|
|
void startThread(); // Start polling for release
|
|
void stopThread(); // Stop polling for release
|
|
|
|
static void isrPrimary(); // User Button ISR
|
|
static void isrSecondary(); // optional aux button or joystick center
|
|
static void isrJoystickUp();
|
|
static void isrJoystickDown();
|
|
static void isrJoystickLeft();
|
|
static void isrJoystickRight();
|
|
|
|
TwoButtonExtended(); // Constructor made private: force use of Button::instance()
|
|
|
|
// Info about both buttons
|
|
Button buttons[2];
|
|
bool joystickActiveLogic = LOW; // Active LOW by default
|
|
uint32_t joystickDebounceLength = 50; // time until press in ms
|
|
SimpleButton joystick[4];
|
|
};
|
|
|
|
}; // namespace NicheGraphics::Inputs
|
|
|
|
#endif
|