From 772dfe39dc3b9679d6a4a3e87e4d183e4b72cbe0 Mon Sep 17 00:00:00 2001 From: Balazs Kelemen <10376327+prampec@users.noreply.github.com> Date: Sun, 9 Jan 2022 10:08:31 +0100 Subject: [PATCH] Combine rotary with canned messages. --- src/plugins/CannedMessagePlugin.cpp | 168 +++++++----------- src/plugins/CannedMessagePlugin.h | 88 +++------ src/plugins/Plugins.cpp | 7 +- .../input/RotaryEncoderInterruptBase.cpp | 67 ++++--- .../input/RotaryEncoderInterruptBase.h | 26 +-- .../input/RotaryEncoderInterruptImpl1.cpp | 30 ++++ .../input/RotaryEncoderInterruptImpl1.h | 16 ++ 7 files changed, 184 insertions(+), 218 deletions(-) create mode 100644 src/plugins/input/RotaryEncoderInterruptImpl1.cpp create mode 100644 src/plugins/input/RotaryEncoderInterruptImpl1.h diff --git a/src/plugins/CannedMessagePlugin.cpp b/src/plugins/CannedMessagePlugin.cpp index e69b742c8..a6ebf3bae 100644 --- a/src/plugins/CannedMessagePlugin.cpp +++ b/src/plugins/CannedMessagePlugin.cpp @@ -5,44 +5,43 @@ #include -#define PIN_PUSH 21 -#define PIN_A 22 -#define PIN_B 23 - -// TODO: add UP-DOWN mode -#define ROTARY_MODE - CannedMessagePlugin *cannedMessagePlugin; -void IRAM_ATTR EXT_INT_PUSH() +CannedMessagePlugin::CannedMessagePlugin( + Observable *input) + : SinglePortPlugin("canned", PortNum_TEXT_MESSAGE_APP), + concurrency::OSThread("CannedMessagePlugin") { - cannedMessagePlugin->select(); + this->inputObserver.observe(input); } -void IRAM_ATTR EXT_INT_DIRECTION_A() +int CannedMessagePlugin::handleInputEvent(const InputEvent *event) { - cannedMessagePlugin->directionA(); -} + bool validEvent = false; + if (event->inputEvent == INPUT_EVENT_UP) + { + this->action = CANNED_MESSAGE_ACTION_UP; + validEvent = true; + } + if (event->inputEvent == INPUT_EVENT_DOWN) + { + this->action = CANNED_MESSAGE_ACTION_DOWN; + validEvent = true; + } + if (event->inputEvent == INPUT_EVENT_SELECT) + { + this->action = CANNED_MESSAGE_ACTION_SELECT; + validEvent = true; + } -void IRAM_ATTR EXT_INT_DIRECTION_B() -{ - cannedMessagePlugin->directionB(); -} + if (validEvent) + { + // Let runOnce to be called immediately. + runned(millis()); + setInterval(0); + } -CannedMessagePlugin::CannedMessagePlugin() - : SinglePortPlugin("canned", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessagePlugin") -{ - // TODO: make pins configurable - pinMode(PIN_PUSH, INPUT_PULLUP); - pinMode(PIN_A, INPUT_PULLUP); - pinMode(PIN_B, INPUT_PULLUP); - attachInterrupt(PIN_PUSH, EXT_INT_PUSH, RISING); -#ifdef ROTARY_MODE - attachInterrupt(PIN_A, EXT_INT_DIRECTION_A, CHANGE); - attachInterrupt(PIN_B, EXT_INT_DIRECTION_B, CHANGE); - this->rotaryLevelA = digitalRead(PIN_A); - this->rotaryLevelB = digitalRead(PIN_B); -#endif + return 0; } void CannedMessagePlugin::sendText(NodeNum dest, @@ -70,13 +69,13 @@ int32_t CannedMessagePlugin::runOnce() this->sendingState = SENDING_STATE_NONE; this->notifyObservers(NULL); } - else if ((this->action != ACTION_NONE) + else if ((this->action != CANNED_MESSAGE_ACTION_NONE) && (this->currentMessageIndex == -1)) { this->currentMessageIndex = 0; DEBUG_MSG("First touch.\n"); } - else if (this->action == ACTION_PRESSED) + else if (this->action == CANNED_MESSAGE_ACTION_SELECT) { sendText( NODENUM_BROADCAST, @@ -86,105 +85,70 @@ int32_t CannedMessagePlugin::runOnce() this->currentMessageIndex = -1; return 2000; } - else if (this->action == ACTION_UP) + else if (this->action == CANNED_MESSAGE_ACTION_UP) { this->currentMessageIndex = getPrevIndex(); DEBUG_MSG("MOVE UP. Current message:%ld\n", millis()); } - else if (this->action == ACTION_DOWN) + else if (this->action == CANNED_MESSAGE_ACTION_DOWN) { this->currentMessageIndex = this->getNextIndex(); DEBUG_MSG("MOVE DOWN. Current message:%ld\n", millis()); } - if (this->action != ACTION_NONE) + if (this->action != CANNED_MESSAGE_ACTION_NONE) { - this->action = ACTION_NONE; + this->action = CANNED_MESSAGE_ACTION_NONE; this->notifyObservers(NULL); } return 30000; } -void CannedMessagePlugin::select() +String CannedMessagePlugin::getCurrentMessage() { - this->action = ACTION_PRESSED; - runned(millis()); - setInterval(20); + return cannedMessagePluginMessages[this->currentMessageIndex]; +} +String CannedMessagePlugin::getPrevMessage() +{ + return cannedMessagePluginMessages[this->getPrevIndex()]; +} +String CannedMessagePlugin::getNextMessage() +{ + return cannedMessagePluginMessages[this->getNextIndex()]; +} +bool CannedMessagePlugin::shouldDraw() +{ + return (currentMessageIndex != -1) || (this->sendingState != SENDING_STATE_NONE); +} +cannedMessagePluginSendigState CannedMessagePlugin::getSendingState() +{ + return this->sendingState; } -/** - * @brief Rotary action implementation. - * We assume, the following pin setup: - * A --|| - * GND --||]======== - * B --|| - * - * @return The new level of the actual pin (that is actualPinCurrentLevel). - */ -void CannedMessagePlugin::directionA() +int CannedMessagePlugin::getNextIndex() { -#ifdef ROTARY_MODE - // CW rotation (at least on most common rotary encoders) - int currentLevelA = digitalRead(PIN_A); - if (this->rotaryLevelA == currentLevelA) + if (this->currentMessageIndex >= + (sizeof(cannedMessagePluginMessages) / CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_LEN) - 1) { - return; + return 0; } - this->rotaryLevelA = currentLevelA; - bool pinARaising = currentLevelA == HIGH; - if (pinARaising && (this->rotaryLevelB == LOW)) + else { - if (this->rotaryStateCCW == EVENT_CLEARED) - { - this->rotaryStateCCW = EVENT_OCCURRED; - if ((this->action == ACTION_NONE) - || (this->action == (cwRotationMeaning == ACTION_UP ? ACTION_UP : ACTION_DOWN))) - { - this->action = cwRotationMeaning == ACTION_UP ? ACTION_DOWN : ACTION_UP; - } - } + return this->currentMessageIndex + 1; } - else if (!pinARaising && (this->rotaryLevelB == HIGH)) - { - // Logic to prevent bouncing. - this->rotaryStateCCW = EVENT_CLEARED; - } -#endif - runned(millis()); - setInterval(50); } -void CannedMessagePlugin::directionB() +int CannedMessagePlugin::getPrevIndex() { -#ifdef ROTARY_MODE - // CW rotation (at least on most common rotary encoders) - int currentLevelB = digitalRead(PIN_B); - if (this->rotaryLevelB == currentLevelB) + if (this->currentMessageIndex <= 0) { - return; + return + sizeof(cannedMessagePluginMessages) / CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_LEN - 1; } - this->rotaryLevelB = currentLevelB; - bool pinBRaising = currentLevelB == HIGH; - if (pinBRaising && (this->rotaryLevelA == LOW)) + else { - if (this->rotaryStateCW == EVENT_CLEARED) - { - this->rotaryStateCW = EVENT_OCCURRED; - if ((this->action == ACTION_NONE) - || (this->action == (cwRotationMeaning == ACTION_UP ? ACTION_DOWN : ACTION_UP))) - { - this->action = cwRotationMeaning == ACTION_UP ? ACTION_UP : ACTION_DOWN; - } - } + return this->currentMessageIndex - 1; } - else if (!pinBRaising && (this->rotaryLevelA == HIGH)) - { - // Logic to prevent bouncing. - this->rotaryStateCW = EVENT_CLEARED; - } -#endif - runned(millis()); - setInterval(50); -} +} \ No newline at end of file diff --git a/src/plugins/CannedMessagePlugin.h b/src/plugins/CannedMessagePlugin.h index 0b22ccc13..588716bf8 100644 --- a/src/plugins/CannedMessagePlugin.h +++ b/src/plugins/CannedMessagePlugin.h @@ -1,18 +1,13 @@ #pragma once #include "SinglePortPlugin.h" - -enum cannedMessagePluginRotaryStateType -{ - EVENT_OCCURRED, - EVENT_CLEARED -}; +#include "input/HardwareInput.h" enum cannedMessagePluginActionType { - ACTION_NONE, - ACTION_PRESSED, - ACTION_UP, - ACTION_DOWN + CANNED_MESSAGE_ACTION_NONE, + CANNED_MESSAGE_ACTION_SELECT, + CANNED_MESSAGE_ACTION_UP, + CANNED_MESSAGE_ACTION_DOWN }; enum cannedMessagePluginSendigState @@ -41,31 +36,20 @@ class CannedMessagePlugin : public Observable, private concurrency::OSThread { + CallbackObserver inputObserver = + CallbackObserver( + this, &CannedMessagePlugin::handleInputEvent); public: - CannedMessagePlugin(); - void select(); - void directionA(); - void directionB(); - String getCurrentMessage() - { - return cannedMessagePluginMessages[this->currentMessageIndex]; - } - String getPrevMessage() - { - return cannedMessagePluginMessages[this->getPrevIndex()]; - } - String getNextMessage() - { - return cannedMessagePluginMessages[this->getNextIndex()]; - } - bool shouldDraw() - { - return (currentMessageIndex != -1) || (this->sendingState != SENDING_STATE_NONE); - } - cannedMessagePluginSendigState getSendingState() - { - return this->sendingState; - } + CannedMessagePlugin( + Observable *input); + String getCurrentMessage(); + String getPrevMessage(); + String getNextMessage(); + bool shouldDraw(); + cannedMessagePluginSendigState getSendingState(); + void eventUp(); + void eventDown(); + void eventSelect(); protected: @@ -76,40 +60,12 @@ class CannedMessagePlugin : const char* message, bool wantReplies); - int getNextIndex() - { - if (this->currentMessageIndex >= - (sizeof(cannedMessagePluginMessages) / CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_LEN) - 1) - { - return 0; - } - else - { - return this->currentMessageIndex + 1; - } - } + int getNextIndex(); + int getPrevIndex(); - int getPrevIndex() - { - if (this->currentMessageIndex <= 0) - { - return - sizeof(cannedMessagePluginMessages) / CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_LEN - 1; - } - else - { - return this->currentMessageIndex - 1; - } - } + int handleInputEvent(const InputEvent *event); - // TODO: make this configurable - volatile cannedMessagePluginActionType cwRotationMeaning = ACTION_UP; - - volatile cannedMessagePluginActionType action = ACTION_NONE; - volatile cannedMessagePluginRotaryStateType rotaryStateCW = EVENT_CLEARED; - volatile cannedMessagePluginRotaryStateType rotaryStateCCW = EVENT_CLEARED; - volatile int rotaryLevelA = LOW; - volatile int rotaryLevelB = LOW; + volatile cannedMessagePluginActionType action = CANNED_MESSAGE_ACTION_NONE; int currentMessageIndex = -1; cannedMessagePluginSendigState sendingState = SENDING_STATE_NONE; }; diff --git a/src/plugins/Plugins.cpp b/src/plugins/Plugins.cpp index 36eddf5fd..32b67998d 100644 --- a/src/plugins/Plugins.cpp +++ b/src/plugins/Plugins.cpp @@ -9,6 +9,7 @@ #include "plugins/RoutingPlugin.h" #include "plugins/AdminPlugin.h" #include "plugins/CannedMessagePlugin.h" +#include "plugins/input/RotaryEncoderInterruptImpl1.h" #ifndef NO_ESP32 #include "plugins/esp32/SerialPlugin.h" #include "plugins/esp32/EnvironmentalMeasurementPlugin.h" @@ -31,7 +32,11 @@ void setupPlugins() new RemoteHardwarePlugin(); new ReplyPlugin(); - cannedMessagePlugin = new CannedMessagePlugin(); + rotaryEncoderInterruptImpl1 = + new RotaryEncoderInterruptImpl1( + 22, 23, 21, + INPUT_EVENT_UP, INPUT_EVENT_DOWN, INPUT_EVENT_SELECT); + cannedMessagePlugin = new CannedMessagePlugin(rotaryEncoderInterruptImpl1); #ifndef NO_ESP32 // Only run on an esp32 based device. diff --git a/src/plugins/input/RotaryEncoderInterruptBase.cpp b/src/plugins/input/RotaryEncoderInterruptBase.cpp index 9bee8cae3..2d6236e69 100644 --- a/src/plugins/input/RotaryEncoderInterruptBase.cpp +++ b/src/plugins/input/RotaryEncoderInterruptBase.cpp @@ -6,32 +6,13 @@ #define PIN_B 23 */ -/* -RotaryEncoderInterruptBase *cannedMessagePlugin; - -void IRAM_ATTR EXT_INT_PUSH() -{ - cannedMessagePlugin->pressed(); -} - -void IRAM_ATTR EXT_INT_DIRECTION_A() -{ - cannedMessagePlugin->directionA(); -} - -void IRAM_ATTR EXT_INT_DIRECTION_B() -{ - cannedMessagePlugin->directionB(); -} -*/ - RotaryEncoderInterruptBase::RotaryEncoderInterruptBase( + const char *name, uint8_t pinA, uint8_t pinB, uint8_t pinPress, char eventCw, char eventCcw, char eventPressed, // std::function onIntA, std::function onIntB, std::function onIntPress) : void (*onIntA)(), void (*onIntB)(), void (*onIntPress)()) : - SinglePortPlugin("rotaryi", PortNum_TEXT_MESSAGE_APP), - concurrency::OSThread("RotaryEncoderInterruptBase") + concurrency::OSThread(name) { this->_pinA = pinA; this->_pinB = pinB; @@ -53,19 +34,33 @@ RotaryEncoderInterruptBase::RotaryEncoderInterruptBase( int32_t RotaryEncoderInterruptBase::runOnce() { - if (this->action == ACTION_PRESSED) + if (this->action == ROTARY_ACTION_PRESSED) { InputEvent e; - e.inputEvent = INPUT_EVENT_SELECT; + e.inputEvent = this->_eventPressed; this->notifyObservers(&e); } + else if (this->action == ROTARY_ACTION_CW) + { + InputEvent e; + e.inputEvent = this->_eventCw; + this->notifyObservers(&e); + } + else if (this->action == ROTARY_ACTION_CCW) + { + InputEvent e; + e.inputEvent = this->_eventCcw; + this->notifyObservers(&e); + } + this->action = ROTARY_ACTION_NONE; + return 30000; } void RotaryEncoderInterruptBase::intPressHandler() { - this->action = ACTION_PRESSED; + this->action = ROTARY_ACTION_PRESSED; runned(millis()); setInterval(20); } @@ -91,20 +86,20 @@ void RotaryEncoderInterruptBase::intAHandler() bool pinARaising = currentLevelA == HIGH; if (pinARaising && (this->rotaryLevelB == LOW)) { - if (this->rotaryStateCCW == EVENT_CLEARED) + if (this->rotaryStateCCW == ROTARY_EVENT_CLEARED) { - this->rotaryStateCCW = EVENT_OCCURRED; - if ((this->action == ACTION_NONE) - || (this->action == ACTION_CCW)) + this->rotaryStateCCW = ROTARY_EVENT_OCCURRED; + if ((this->action == ROTARY_ACTION_NONE) + || (this->action == ROTARY_ACTION_CCW)) { - this->action = ACTION_CW; + this->action = ROTARY_ACTION_CW; } } } else if (!pinARaising && (this->rotaryLevelB == HIGH)) { // Logic to prevent bouncing. - this->rotaryStateCCW = EVENT_CLEARED; + this->rotaryStateCCW = ROTARY_EVENT_CLEARED; } runned(millis()); setInterval(50); @@ -122,20 +117,20 @@ void RotaryEncoderInterruptBase::intBHandler() bool pinBRaising = currentLevelB == HIGH; if (pinBRaising && (this->rotaryLevelA == LOW)) { - if (this->rotaryStateCW == EVENT_CLEARED) + if (this->rotaryStateCW == ROTARY_EVENT_CLEARED) { - this->rotaryStateCW = EVENT_OCCURRED; - if ((this->action == ACTION_NONE) - || (this->action == ACTION_CCW)) + this->rotaryStateCW = ROTARY_EVENT_OCCURRED; + if ((this->action == ROTARY_ACTION_NONE) + || (this->action == ROTARY_ACTION_CCW)) { - this->action = ACTION_CW; + this->action = ROTARY_ACTION_CW; } } } else if (!pinBRaising && (this->rotaryLevelA == HIGH)) { // Logic to prevent bouncing. - this->rotaryStateCW = EVENT_CLEARED; + this->rotaryStateCW = ROTARY_EVENT_CLEARED; } runned(millis()); setInterval(50); diff --git a/src/plugins/input/RotaryEncoderInterruptBase.h b/src/plugins/input/RotaryEncoderInterruptBase.h index 09d00bcb2..110596cce 100644 --- a/src/plugins/input/RotaryEncoderInterruptBase.h +++ b/src/plugins/input/RotaryEncoderInterruptBase.h @@ -1,28 +1,30 @@ #pragma once +//#include +//#include "Observer.h" #include "SinglePortPlugin.h" #include "HardwareInput.h" enum RotaryEncoderInterruptBaseStateType { - EVENT_OCCURRED, - EVENT_CLEARED + ROTARY_EVENT_OCCURRED, + ROTARY_EVENT_CLEARED }; enum RotaryEncoderInterruptBaseActionType { - ACTION_NONE, - ACTION_PRESSED, - ACTION_CW, - ACTION_CCW + ROTARY_ACTION_NONE, + ROTARY_ACTION_PRESSED, + ROTARY_ACTION_CW, + ROTARY_ACTION_CCW }; class RotaryEncoderInterruptBase : - public SinglePortPlugin, public Observable, private concurrency::OSThread { public: RotaryEncoderInterruptBase( + const char *name, uint8_t pinA, uint8_t pinB, uint8_t pinPress, char eventCw, char eventCcw, char eventPressed, // std::function onIntA, std::function onIntB, std::function onIntPress); @@ -33,11 +35,11 @@ class RotaryEncoderInterruptBase : protected: virtual int32_t runOnce(); - volatile RotaryEncoderInterruptBaseStateType rotaryStateCW = EVENT_CLEARED; - volatile RotaryEncoderInterruptBaseStateType rotaryStateCCW = EVENT_CLEARED; + volatile RotaryEncoderInterruptBaseStateType rotaryStateCW = ROTARY_EVENT_CLEARED; + volatile RotaryEncoderInterruptBaseStateType rotaryStateCCW = ROTARY_EVENT_CLEARED; volatile int rotaryLevelA = LOW; volatile int rotaryLevelB = LOW; - volatile RotaryEncoderInterruptBaseActionType action = ACTION_NONE; + volatile RotaryEncoderInterruptBaseActionType action = ROTARY_ACTION_NONE; private: uint8_t _pinA; @@ -45,6 +47,4 @@ class RotaryEncoderInterruptBase : char _eventCw; char _eventCcw; char _eventPressed; -}; - -RotaryEncoderInterruptBase *RotaryEncoderInterruptBase; \ No newline at end of file +}; \ No newline at end of file diff --git a/src/plugins/input/RotaryEncoderInterruptImpl1.cpp b/src/plugins/input/RotaryEncoderInterruptImpl1.cpp new file mode 100644 index 000000000..6c90b18da --- /dev/null +++ b/src/plugins/input/RotaryEncoderInterruptImpl1.cpp @@ -0,0 +1,30 @@ +#include "RotaryEncoderInterruptImpl1.h" + +RotaryEncoderInterruptImpl1 *rotaryEncoderInterruptImpl1; + +RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1( + uint8_t pinA, uint8_t pinB, uint8_t pinPress, + char eventCw, char eventCcw, char eventPressed) : + RotaryEncoderInterruptBase( + "rotEnc1", + pinA, pinB, pinPress, + eventCw, eventCcw, eventPressed, + RotaryEncoderInterruptImpl1::handleIntA, + RotaryEncoderInterruptImpl1::handleIntB, + RotaryEncoderInterruptImpl1::handleIntPressed) +{ + +} + +void RotaryEncoderInterruptImpl1::handleIntA() +{ + +} +void RotaryEncoderInterruptImpl1::handleIntB() +{ + +} +void RotaryEncoderInterruptImpl1::handleIntPressed() +{ + +} diff --git a/src/plugins/input/RotaryEncoderInterruptImpl1.h b/src/plugins/input/RotaryEncoderInterruptImpl1.h new file mode 100644 index 000000000..17613e8e3 --- /dev/null +++ b/src/plugins/input/RotaryEncoderInterruptImpl1.h @@ -0,0 +1,16 @@ +#pragma once +#include "RotaryEncoderInterruptBase.h" + +class RotaryEncoderInterruptImpl1 : + public RotaryEncoderInterruptBase +{ + public: + RotaryEncoderInterruptImpl1( + uint8_t pinA, uint8_t pinB, uint8_t pinPress, + char eventCw, char eventCcw, char eventPressed); + static void handleIntA(); + static void handleIntB(); + static void handleIntPressed(); +}; + +extern RotaryEncoderInterruptImpl1 *rotaryEncoderInterruptImpl1; \ No newline at end of file