mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
- `TT_LOG_*` macros are replaced by `Logger` via `#include<Tactility/Logger.h>` - Changed default timezone to Europe/Amsterdam - Fix for logic bug in unPhone hardware - Fix for init/deinit in DRV2605 driver - Other fixes - Removed optimization that broke unPhone (disabled the moving of heap-related functions to flash)
163 lines
4.6 KiB
C++
163 lines
4.6 KiB
C++
#include "ButtonControl.h"
|
|
|
|
#include <Tactility/Logger.h>
|
|
|
|
#include <esp_lvgl_port.h>
|
|
|
|
static const auto LOGGER = tt::Logger("ButtonControl");
|
|
|
|
ButtonControl::ButtonControl(const std::vector<PinConfiguration>& pinConfigurations) : pinConfigurations(pinConfigurations) {
|
|
pinStates.resize(pinConfigurations.size());
|
|
for (const auto& pinConfiguration : pinConfigurations) {
|
|
tt::hal::gpio::configure(pinConfiguration.pin, tt::hal::gpio::Mode::Input, false, false);
|
|
}
|
|
}
|
|
|
|
ButtonControl::~ButtonControl() {
|
|
if (driverThread != nullptr && driverThread->getState() != tt::Thread::State::Stopped) {
|
|
interruptDriverThread = true;
|
|
driverThread->join();
|
|
}
|
|
}
|
|
|
|
void ButtonControl::readCallback(lv_indev_t* indev, lv_indev_data_t* data) {
|
|
// Defaults
|
|
data->enc_diff = 0;
|
|
data->state = LV_INDEV_STATE_RELEASED;
|
|
|
|
auto* self = static_cast<ButtonControl*>(lv_indev_get_driver_data(indev));
|
|
|
|
if (self->mutex.lock(100)) {
|
|
|
|
for (int i = 0; i < self->pinConfigurations.size(); i++) {
|
|
const auto& config = self->pinConfigurations[i];
|
|
std::vector<PinState>::reference state = self->pinStates[i];
|
|
const bool trigger = (config.event == Event::ShortPress && state.triggerShortPress) ||
|
|
(config.event == Event::LongPress && state.triggerLongPress);
|
|
state.triggerShortPress = false;
|
|
state.triggerLongPress = false;
|
|
if (trigger) {
|
|
switch (config.action) {
|
|
case Action::UiSelectNext:
|
|
data->enc_diff = 1;
|
|
break;
|
|
case Action::UiSelectPrevious:
|
|
data->enc_diff = -1;
|
|
break;
|
|
case Action::UiPressSelected:
|
|
data->state = LV_INDEV_STATE_PRESSED;
|
|
break;
|
|
case Action::AppClose:
|
|
// TODO: implement
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
self->mutex.unlock();
|
|
}
|
|
}
|
|
|
|
void ButtonControl::updatePin(std::vector<PinConfiguration>::const_reference configuration, std::vector<PinState>::reference state) {
|
|
if (tt::hal::gpio::getLevel(configuration.pin)) { // if pressed
|
|
if (state.pressState) {
|
|
// check time for long press trigger
|
|
auto time_passed = tt::kernel::getMillis() - state.pressStartTime;
|
|
if (time_passed > 500) {
|
|
// state.triggerLongPress = true;
|
|
}
|
|
} else {
|
|
state.pressStartTime = tt::kernel::getMillis();
|
|
state.pressState = true;
|
|
}
|
|
} else { // released
|
|
if (state.pressState) {
|
|
auto time_passed = tt::kernel::getMillis() - state.pressStartTime;
|
|
if (time_passed < 500) {
|
|
LOGGER.debug("Trigger short press");
|
|
state.triggerShortPress = true;
|
|
}
|
|
state.pressState = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ButtonControl::driverThreadMain() {
|
|
while (!shouldInterruptDriverThread()) {
|
|
if (mutex.lock(100)) {
|
|
for (int i = 0; i < pinConfigurations.size(); i++) {
|
|
updatePin(pinConfigurations[i], pinStates[i]);
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
tt::kernel::delayMillis(5);
|
|
}
|
|
}
|
|
|
|
bool ButtonControl::shouldInterruptDriverThread() const {
|
|
bool interrupt = false;
|
|
if (mutex.lock(50 / portTICK_PERIOD_MS)) {
|
|
interrupt = interruptDriverThread;
|
|
mutex.unlock();
|
|
}
|
|
return interrupt;
|
|
}
|
|
|
|
void ButtonControl::startThread() {
|
|
LOGGER.info("Start");
|
|
|
|
mutex.lock();
|
|
|
|
interruptDriverThread = false;
|
|
|
|
driverThread = std::make_shared<tt::Thread>("ButtonControl", 4096, [this] {
|
|
driverThreadMain();
|
|
return 0;
|
|
});
|
|
|
|
driverThread->start();
|
|
|
|
mutex.unlock();
|
|
}
|
|
|
|
void ButtonControl::stopThread() {
|
|
LOGGER.info("Stop");
|
|
|
|
mutex.lock();
|
|
interruptDriverThread = true;
|
|
mutex.unlock();
|
|
|
|
driverThread->join();
|
|
|
|
mutex.lock();
|
|
driverThread = nullptr;
|
|
mutex.unlock();
|
|
}
|
|
|
|
bool ButtonControl::startLvgl(lv_display_t* display) {
|
|
if (deviceHandle != nullptr) {
|
|
return false;
|
|
}
|
|
|
|
startThread();
|
|
|
|
deviceHandle = lv_indev_create();
|
|
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_ENCODER);
|
|
lv_indev_set_driver_data(deviceHandle, this);
|
|
lv_indev_set_read_cb(deviceHandle, readCallback);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ButtonControl::stopLvgl() {
|
|
if (deviceHandle == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
lv_indev_delete(deviceHandle);
|
|
deviceHandle = nullptr;
|
|
|
|
stopThread();
|
|
|
|
return true;
|
|
}
|