Files
firmware/src/input/RotaryEncoderImpl.cpp

135 lines
4.1 KiB
C++
Raw Normal View History

#ifdef T_LORA_PAGER
#include "RotaryEncoderImpl.h"
#include "InputBroker.h"
#include "RotaryEncoder.h"
#ifdef ARCH_ESP32
#include "sleep.h"
#endif
#define ORIGIN_NAME "RotaryEncoder"
RotaryEncoderImpl *rotaryEncoderImpl;
2026-01-03 21:19:24 +01:00
RotaryEncoderImpl::RotaryEncoderImpl() {
rotary = nullptr;
#ifdef ARCH_ESP32
2026-01-03 21:19:24 +01:00
isFirstInit = true;
#endif
}
2026-01-03 21:19:24 +01:00
RotaryEncoderImpl::~RotaryEncoderImpl() {
LOG_DEBUG("RotaryEncoderImpl destructor");
detachRotaryEncoderInterrupts();
2026-01-03 21:19:24 +01:00
if (rotary != nullptr) {
delete rotary;
rotary = nullptr;
}
2025-08-27 06:50:53 -05:00
}
2026-01-03 21:19:24 +01:00
bool RotaryEncoderImpl::init() {
if (!moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.inputbroker_pin_a == 0 ||
moduleConfig.canned_message.inputbroker_pin_b == 0) {
// Input device is disabled.
return false;
}
2026-01-03 21:19:24 +01:00
eventCw = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_cw);
eventCcw = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_ccw);
eventPressed = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_press);
2026-01-03 21:19:24 +01:00
if (rotary == nullptr) {
rotary = new RotaryEncoder(moduleConfig.canned_message.inputbroker_pin_a, moduleConfig.canned_message.inputbroker_pin_b,
moduleConfig.canned_message.inputbroker_pin_press);
}
2026-01-03 21:19:24 +01:00
attachRotaryEncoderInterrupts();
#ifdef ARCH_ESP32
2026-01-03 21:19:24 +01:00
// Register callbacks for before and after lightsleep
// Used to detach and reattach interrupts
if (isFirstInit) {
lsObserver.observe(&notifyLightSleep);
lsEndObserver.observe(&notifyLightSleepEnd);
isFirstInit = false;
}
#endif
2026-01-03 21:19:24 +01:00
LOG_INFO("RotaryEncoder initialized pins(%d, %d, %d), events(%d, %d, %d)", moduleConfig.canned_message.inputbroker_pin_a,
moduleConfig.canned_message.inputbroker_pin_b, moduleConfig.canned_message.inputbroker_pin_press, eventCw, eventCcw, eventPressed);
return true;
}
2026-01-03 21:19:24 +01:00
void RotaryEncoderImpl::pollOnce() {
InputEvent e{ORIGIN_NAME, INPUT_BROKER_NONE, 0, 0, 0};
2026-01-03 21:19:24 +01:00
static uint32_t lastPressed = millis();
if (rotary->readButton() == RotaryEncoder::ButtonState::BUTTON_PRESSED) {
if (lastPressed + 200 < millis()) {
LOG_DEBUG("Rotary event Press");
lastPressed = millis();
e.inputEvent = this->eventPressed;
inputBroker->queueInputEvent(&e);
}
2026-01-03 21:19:24 +01:00
}
switch (rotary->process()) {
case RotaryEncoder::DIRECTION_CW:
LOG_DEBUG("Rotary event CW");
e.inputEvent = this->eventCw;
inputBroker->queueInputEvent(&e);
break;
case RotaryEncoder::DIRECTION_CCW:
LOG_DEBUG("Rotary event CCW");
e.inputEvent = this->eventCcw;
inputBroker->queueInputEvent(&e);
break;
default:
break;
}
}
2026-01-03 21:19:24 +01:00
void RotaryEncoderImpl::detachRotaryEncoderInterrupts() {
LOG_DEBUG("RotaryEncoderImpl detach button interrupts");
if (interruptInstance == this) {
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_a);
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_b);
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_press);
interruptInstance = nullptr;
} else {
LOG_WARN("RotaryEncoderImpl: interrupts already detached");
}
}
2026-01-03 21:19:24 +01:00
void RotaryEncoderImpl::attachRotaryEncoderInterrupts() {
LOG_DEBUG("RotaryEncoderImpl attach button interrupts");
if (rotary != nullptr && interruptInstance == nullptr) {
rotary->resetButton();
interruptInstance = this;
auto interruptHandler = []() { inputBroker->requestPollSoon(interruptInstance); };
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_a, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_b, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_press, interruptHandler, CHANGE);
} else {
LOG_WARN("RotaryEncoderImpl: interrupts already attached");
}
}
#ifdef ARCH_ESP32
2026-01-03 21:19:24 +01:00
int RotaryEncoderImpl::beforeLightSleep(void *unused) {
detachRotaryEncoderInterrupts();
return 0; // Indicates success;
}
2026-01-03 21:19:24 +01:00
int RotaryEncoderImpl::afterLightSleep(esp_sleep_wakeup_cause_t cause) {
attachRotaryEncoderInterrupts();
return 0; // Indicates success;
}
#endif
RotaryEncoderImpl *RotaryEncoderImpl::interruptInstance;
#endif