2022-01-08 12:13:29 +00:00
|
|
|
#include "configuration.h"
|
|
|
|
#include "RotaryEncoderInterruptBase.h"
|
|
|
|
|
|
|
|
/*#define PIN_PUSH 21
|
|
|
|
#define PIN_A 22
|
|
|
|
#define PIN_B 23
|
|
|
|
*/
|
|
|
|
|
|
|
|
RotaryEncoderInterruptBase::RotaryEncoderInterruptBase(
|
2022-01-11 12:12:04 +00:00
|
|
|
const char *name) :
|
|
|
|
concurrency::OSThread(name)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void RotaryEncoderInterruptBase::init(
|
2022-01-08 12:13:29 +00:00
|
|
|
uint8_t pinA, uint8_t pinB, uint8_t pinPress,
|
|
|
|
char eventCw, char eventCcw, char eventPressed,
|
2022-01-11 12:12:04 +00:00
|
|
|
// std::function<void(void)> onIntA, std::function<void(void)> onIntB, std::function<void(void)> onIntPress) :
|
|
|
|
void (*onIntA)(), void (*onIntB)(), void (*onIntPress)())
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
|
|
|
this->_pinA = pinA;
|
|
|
|
this->_pinB = pinB;
|
|
|
|
this->_eventCw = eventCw;
|
|
|
|
this->_eventCcw = eventCcw;
|
|
|
|
this->_eventPressed = eventPressed;
|
|
|
|
|
|
|
|
pinMode(pinPress, INPUT_PULLUP);
|
|
|
|
pinMode(this->_pinA, INPUT_PULLUP);
|
|
|
|
pinMode(this->_pinB, INPUT_PULLUP);
|
2022-01-11 12:12:04 +00:00
|
|
|
|
2022-01-08 12:13:29 +00:00
|
|
|
// attachInterrupt(pinPress, onIntPress, RISING);
|
|
|
|
attachInterrupt(pinPress, onIntPress, RISING);
|
|
|
|
attachInterrupt(this->_pinA, onIntA, CHANGE);
|
|
|
|
attachInterrupt(this->_pinB, onIntB, CHANGE);
|
2022-01-11 12:12:04 +00:00
|
|
|
|
2022-01-08 12:13:29 +00:00
|
|
|
this->rotaryLevelA = digitalRead(this->_pinA);
|
|
|
|
this->rotaryLevelB = digitalRead(this->_pinB);
|
2022-01-09 20:14:23 +00:00
|
|
|
DEBUG_MSG("Rotary initialized (%d, %d, %d)\n",
|
|
|
|
this->_pinA, this->_pinB, pinPress);
|
2022-01-08 12:13:29 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 12:12:04 +00:00
|
|
|
|
2022-01-08 12:13:29 +00:00
|
|
|
int32_t RotaryEncoderInterruptBase::runOnce()
|
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
if (this->action == ROTARY_ACTION_PRESSED)
|
|
|
|
{
|
|
|
|
InputEvent e;
|
|
|
|
e.inputEvent = this->_eventPressed;
|
|
|
|
this->notifyObservers(&e);
|
|
|
|
}
|
|
|
|
else if (this->action == ROTARY_ACTION_CW)
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
2022-01-09 20:14:23 +00:00
|
|
|
DEBUG_MSG("Rotary event CW\n");
|
2022-01-08 12:13:29 +00:00
|
|
|
InputEvent e;
|
2022-01-09 09:08:31 +00:00
|
|
|
e.inputEvent = this->_eventCw;
|
2022-01-08 12:13:29 +00:00
|
|
|
this->notifyObservers(&e);
|
|
|
|
}
|
2022-01-09 09:08:31 +00:00
|
|
|
else if (this->action == ROTARY_ACTION_CCW)
|
|
|
|
{
|
2022-01-09 20:14:23 +00:00
|
|
|
DEBUG_MSG("Rotary event CW\n");
|
2022-01-09 09:08:31 +00:00
|
|
|
InputEvent e;
|
|
|
|
e.inputEvent = this->_eventCcw;
|
|
|
|
this->notifyObservers(&e);
|
|
|
|
}
|
|
|
|
this->action = ROTARY_ACTION_NONE;
|
|
|
|
|
2022-01-08 12:13:29 +00:00
|
|
|
return 30000;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RotaryEncoderInterruptBase::intPressHandler()
|
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
this->action = ROTARY_ACTION_PRESSED;
|
2022-01-08 12:13:29 +00:00
|
|
|
runned(millis());
|
|
|
|
setInterval(20);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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 RotaryEncoderInterruptBase::intAHandler()
|
|
|
|
{
|
|
|
|
// CW rotation (at least on most common rotary encoders)
|
|
|
|
int currentLevelA = digitalRead(this->_pinA);
|
|
|
|
if (this->rotaryLevelA == currentLevelA)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->rotaryLevelA = currentLevelA;
|
|
|
|
bool pinARaising = currentLevelA == HIGH;
|
|
|
|
if (pinARaising && (this->rotaryLevelB == LOW))
|
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
if (this->rotaryStateCCW == ROTARY_EVENT_CLEARED)
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
this->rotaryStateCCW = ROTARY_EVENT_OCCURRED;
|
|
|
|
if ((this->action == ROTARY_ACTION_NONE)
|
2022-01-09 20:14:23 +00:00
|
|
|
|| (this->action == ROTARY_ACTION_CW))
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
2022-01-09 20:14:23 +00:00
|
|
|
this->action = ROTARY_ACTION_CCW;
|
|
|
|
DEBUG_MSG("Rotary action CCW\n");
|
2022-01-08 12:13:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!pinARaising && (this->rotaryLevelB == HIGH))
|
|
|
|
{
|
|
|
|
// Logic to prevent bouncing.
|
2022-01-09 09:08:31 +00:00
|
|
|
this->rotaryStateCCW = ROTARY_EVENT_CLEARED;
|
2022-01-08 12:13:29 +00:00
|
|
|
}
|
|
|
|
runned(millis());
|
|
|
|
setInterval(50);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RotaryEncoderInterruptBase::intBHandler()
|
|
|
|
{
|
|
|
|
// CW rotation (at least on most common rotary encoders)
|
|
|
|
int currentLevelB = digitalRead(this->_pinB);
|
|
|
|
if (this->rotaryLevelB == currentLevelB)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->rotaryLevelB = currentLevelB;
|
|
|
|
bool pinBRaising = currentLevelB == HIGH;
|
|
|
|
if (pinBRaising && (this->rotaryLevelA == LOW))
|
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
if (this->rotaryStateCW == ROTARY_EVENT_CLEARED)
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
this->rotaryStateCW = ROTARY_EVENT_OCCURRED;
|
|
|
|
if ((this->action == ROTARY_ACTION_NONE)
|
|
|
|
|| (this->action == ROTARY_ACTION_CCW))
|
2022-01-08 12:13:29 +00:00
|
|
|
{
|
2022-01-09 09:08:31 +00:00
|
|
|
this->action = ROTARY_ACTION_CW;
|
2022-01-09 20:14:23 +00:00
|
|
|
DEBUG_MSG("Rotary action CW\n");
|
2022-01-08 12:13:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!pinBRaising && (this->rotaryLevelA == HIGH))
|
|
|
|
{
|
|
|
|
// Logic to prevent bouncing.
|
2022-01-09 09:08:31 +00:00
|
|
|
this->rotaryStateCW = ROTARY_EVENT_CLEARED;
|
2022-01-08 12:13:29 +00:00
|
|
|
}
|
|
|
|
runned(millis());
|
|
|
|
setInterval(50);
|
|
|
|
}
|