From 59e0897b725c30b3e24046620683a1c857d42d63 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 16 Dec 2025 18:59:38 -0500 Subject: [PATCH] Added support for other GPIO providers such as Adafruit_MCP23XXX --- .gitignore | 1 + platformio.ini | 10 ++++++++++ src/RotaryEncoder.cpp | 45 ++++++++++++++++++++++++++++++++++++------- src/RotaryEncoder.h | 28 +++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 platformio.ini diff --git a/.gitignore b/.gitignore index 7461aa1..88761ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/* _* +.pio \ No newline at end of file diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..d394733 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,10 @@ +[platformio] +default_envs = uno + +[env:uno] +platform = atmelavr +board = uno +framework = arduino + +lib_deps = + adafruit/Adafruit MCP23017 Arduino Library@^2.3.2 \ No newline at end of file diff --git a/src/RotaryEncoder.cpp b/src/RotaryEncoder.cpp index 6a3dd9c..6463f4f 100644 --- a/src/RotaryEncoder.cpp +++ b/src/RotaryEncoder.cpp @@ -15,6 +15,31 @@ #include "RotaryEncoder.h" #include "Arduino.h" +void BuiltInInputProvider::pinMode(uint8_t pin, uint8_t mode) +{ + pinMode(pin, mode); +} + +int BuiltInInputProvider::digitalRead(uint8_t pin) +{ + return digitalRead(pin); +} + +MCP23XXXInputProvider::MCP23XXXInputProvider(Adafruit_MCP23XXX *mcp) +{ + this->mcp = mcp; +} + +void MCP23XXXInputProvider::pinMode(uint8_t pin, uint8_t mode) +{ + this->mcp->pinMode(pin, mode); +} + +int MCP23XXXInputProvider::digitalRead(uint8_t pin) +{ + return this->mcp->digitalRead(pin); +} + #define LATCH0 0 // input state at position 0 #define LATCH3 3 // input state at position 3 @@ -38,8 +63,10 @@ const int8_t KNOBDIR[] = { // ----- Initialization and Default Values ----- -RotaryEncoder::RotaryEncoder(int pin1, int pin2, LatchMode mode) +RotaryEncoder::RotaryEncoder(InputProvider *provider, int pin1, int pin2, LatchMode mode = LatchMode::FOUR0) { + this->provider = provider; + int sig1 = 0; int sig2 = 0; @@ -50,11 +77,11 @@ RotaryEncoder::RotaryEncoder(int pin1, int pin2, LatchMode mode) // Setup the input pins and turn on pullup resistor if ((pin1 >= 0) && (pin2 >= 0)) { - pinMode(pin1, INPUT_PULLUP); - pinMode(pin2, INPUT_PULLUP); + this->provider->pinMode(pin1, INPUT_PULLUP); + this->provider->pinMode(pin2, INPUT_PULLUP); // when not started in motion, the current state of the encoder should be 3 - sig1 = digitalRead(_pin1); - sig2 = digitalRead(_pin2); + sig1 = this->provider->digitalRead(_pin1); + sig2 = this->provider->digitalRead(_pin2); } _oldState = sig1 | (sig2 << 1); @@ -66,6 +93,10 @@ RotaryEncoder::RotaryEncoder(int pin1, int pin2, LatchMode mode) } // RotaryEncoder() +RotaryEncoder::RotaryEncoder(int pin1, int pin2, LatchMode mode = LatchMode::FOUR0) : RotaryEncoder(new BuiltInInputProvider(), pin1, pin2, mode) {} + +RotaryEncoder::RotaryEncoder(Adafruit_MCP23XXX *mcp, int pin1, int pin2, LatchMode mode = LatchMode::FOUR0) : RotaryEncoder(new MCP23XXXInputProvider(mcp), pin1, pin2, mode) {} + long RotaryEncoder::getPosition() { return _positionExt; @@ -116,8 +147,8 @@ void RotaryEncoder::setPosition(long newPosition) // Slow, but Simple Variant by directly Read-Out of the Digital State within loop-call void RotaryEncoder::tick(void) { - int sig1 = digitalRead(_pin1); - int sig2 = digitalRead(_pin2); + int sig1 = this->provider->digitalRead(_pin1); + int sig2 = this->provider->digitalRead(_pin2); tick(sig1, sig2); } // tick() diff --git a/src/RotaryEncoder.h b/src/RotaryEncoder.h index 324bf4d..e198f45 100644 --- a/src/RotaryEncoder.h +++ b/src/RotaryEncoder.h @@ -20,6 +20,30 @@ #define RotaryEncoder_h #include "Arduino.h" +#include + +class InputProvider +{ +public: + virtual void pinMode(uint8_t pin, uint8_t mode) = 0; + virtual int digitalRead(uint8_t pin) = 0; +}; + +class BuiltInInputProvider : public InputProvider +{ +public: + void pinMode(uint8_t pin, uint8_t mode); + int digitalRead(uint8_t pin); +}; + +class MCP23XXXInputProvider : public InputProvider +{ +public: + MCP23XXXInputProvider(Adafruit_MCP23XXX *mcp); + Adafruit_MCP23XXX *mcp; + void pinMode(uint8_t pin, uint8_t mode); + int digitalRead(uint8_t pin); +}; class RotaryEncoder { @@ -37,6 +61,8 @@ class RotaryEncoder }; // ----- Constructor ----- + RotaryEncoder(InputProvider *provider, int pin1, int pin2, LatchMode mode = LatchMode::FOUR0); + RotaryEncoder(Adafruit_MCP23XXX *mcp, int pin1, int pin2, LatchMode mode = LatchMode::FOUR0); RotaryEncoder(int pin1, int pin2, LatchMode mode = LatchMode::FOUR0); // retrieve the current position @@ -75,6 +101,8 @@ class RotaryEncoder unsigned long _positionExtTime; // The time the last position change was detected. unsigned long _positionExtTimePrev; // The time the previous position change was detected. + + InputProvider *provider; }; #endif