diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 429e010f5..874f0c868 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -30,6 +30,8 @@ lib_deps = 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/af9bc27c9c30fa90772279925b7c5913dff789b4.zip + # renovate: datasource=custom.pio depName=adafruit/Adafruit seesaw Library packageName=adafruit/library/Adafruit seesaw Library + adafruit/Adafruit seesaw Library@1.7.9 build_flags = ${arduino_base.build_flags} @@ -48,4 +50,7 @@ build_flags = -std=gnu17 -std=c++17 -lib_ignore = Adafruit NeoPixel +lib_ignore = + Adafruit NeoPixel + Adafruit ST7735 and ST7789 Library + SD diff --git a/src/input/SeesawRotary.cpp b/src/input/SeesawRotary.cpp new file mode 100644 index 000000000..c212773c4 --- /dev/null +++ b/src/input/SeesawRotary.cpp @@ -0,0 +1,83 @@ +#ifdef ARCH_PORTDUINO +#include "SeesawRotary.h" +#include "input/InputBroker.h" + +using namespace concurrency; + +SeesawRotary *seesawRotary; + +SeesawRotary::SeesawRotary(const char *name) : OSThread(name) +{ + _originName = name; +} + +bool SeesawRotary::init() +{ + if (inputBroker) + inputBroker->registerSource(this); + + if (!ss.begin(SEESAW_ADDR)) { + return false; + } + // attachButtonInterrupts(); + + uint32_t version = ((ss.getVersion() >> 16) & 0xFFFF); + if (version != 4991) { + LOG_WARN("Wrong firmware loaded? %u", version); + } else { + LOG_INFO("Found Product 4991"); + } + /* + #ifdef ARCH_ESP32 + // Register callbacks for before and after lightsleep + // Used to detach and reattach interrupts + lsObserver.observe(¬ifyLightSleep); + lsEndObserver.observe(¬ifyLightSleepEnd); + #endif + */ + ss.pinMode(SS_SWITCH, INPUT_PULLUP); + + // get starting position + encoder_position = ss.getEncoderPosition(); + + ss.setGPIOInterrupts((uint32_t)1 << SS_SWITCH, 1); + ss.enableEncoderInterrupt(); + canSleep = true; // Assume we should not keep the board awake + + return true; +} + +int32_t SeesawRotary::runOnce() +{ + InputEvent e; + e.inputEvent = INPUT_BROKER_NONE; + bool currentlyPressed = !ss.digitalRead(SS_SWITCH); + + if (currentlyPressed && !wasPressed) { + e.inputEvent = INPUT_BROKER_SELECT; + } + wasPressed = currentlyPressed; + + int32_t new_position = ss.getEncoderPosition(); + // did we move arounde? + if (encoder_position != new_position) { + if (encoder_position == 0 && new_position != 1) { + e.inputEvent = INPUT_BROKER_ALT_PRESS; + } else if (new_position == 0 && encoder_position != 1) { + e.inputEvent = INPUT_BROKER_USER_PRESS; + } else if (new_position > encoder_position) { + e.inputEvent = INPUT_BROKER_USER_PRESS; + } else { + e.inputEvent = INPUT_BROKER_ALT_PRESS; + } + encoder_position = new_position; + } + if (e.inputEvent != INPUT_BROKER_NONE) { + e.source = this->_originName; + e.kbchar = 0x00; + this->notifyObservers(&e); + } + + return 50; +} +#endif \ No newline at end of file diff --git a/src/input/SeesawRotary.h b/src/input/SeesawRotary.h new file mode 100644 index 000000000..3812b130a --- /dev/null +++ b/src/input/SeesawRotary.h @@ -0,0 +1,29 @@ +#pragma once +#ifdef ARCH_PORTDUINO + +#include "Adafruit_seesaw.h" +#include "InputBroker.h" +#include "concurrency/OSThread.h" +#include "configuration.h" + +#define SS_SWITCH 24 +#define SS_NEOPIX 6 + +#define SEESAW_ADDR 0x36 + +class SeesawRotary : public Observable, public concurrency::OSThread +{ + public: + const char *_originName; + bool init(); + SeesawRotary(const char *name); + int32_t runOnce() override; + + private: + Adafruit_seesaw ss; + int32_t encoder_position; + bool wasPressed = false; +}; + +extern SeesawRotary *seesawRotary; +#endif \ No newline at end of file diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 403f36a04..3528f57f5 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -53,6 +53,7 @@ #endif #if ARCH_PORTDUINO #include "input/LinuxInputImpl.h" +#include "input/SeesawRotary.h" #include "modules/Telemetry/HostMetrics.h" #if !MESHTASTIC_EXCLUDE_STOREFORWARD #include "modules/StoreForwardModule.h" @@ -163,7 +164,6 @@ void setupModules() // Example: Put your module here // new ReplyModule(); #if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1(); if (!rotaryEncoderInterruptImpl1->init()) { @@ -189,6 +189,11 @@ void setupModules() #endif // HAS_BUTTON #if ARCH_PORTDUINO if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + seesawRotary = new SeesawRotary("SeesawRotary"); + if (!seesawRotary->init()) { + delete seesawRotary; + seesawRotary = nullptr; + } aLinuxInputImpl = new LinuxInputImpl(); aLinuxInputImpl->init(); }