mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-19 03:13:14 +00:00
Add AXP192 driver
This commit is contained in:
parent
0513037dbf
commit
f45f809c9b
@ -45,6 +45,8 @@ public:
|
||||
return isInitialized;
|
||||
}
|
||||
|
||||
axp192_t* getAxp192() { return &axpDevice; }
|
||||
|
||||
std::string getName() const override { return "AXP192"; }
|
||||
std::string getDescription() const override { return "AXP192 power management via I2C"; }
|
||||
|
||||
|
||||
7
Drivers/ButtonControl/CMakeLists.txt
Normal file
7
Drivers/ButtonControl/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility esp_lvgl_port driver
|
||||
)
|
||||
3
Drivers/ButtonControl/README.md
Normal file
3
Drivers/ButtonControl/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Button Control
|
||||
|
||||
A driver for navigating apps with 1 or more GPIO buttons.
|
||||
162
Drivers/ButtonControl/Source/ButtonControl.cpp
Normal file
162
Drivers/ButtonControl/Source/ButtonControl.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
#include "ButtonControl.h"
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
|
||||
#include <esp_lvgl_port.h>
|
||||
|
||||
constexpr auto* TAG = "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(20)) {
|
||||
|
||||
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) {
|
||||
TT_LOG_W(TAG, "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() {
|
||||
TT_LOG_I(TAG, "Start");
|
||||
|
||||
mutex.lock();
|
||||
|
||||
interruptDriverThread = false;
|
||||
|
||||
driverThread = std::make_shared<tt::Thread>("ButtonControl", 4096, [this] {
|
||||
driverThreadMain();
|
||||
return 0;
|
||||
});
|
||||
|
||||
driverThread->start();
|
||||
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void ButtonControl::stopThread() {
|
||||
TT_LOG_I(TAG, "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;
|
||||
}
|
||||
110
Drivers/ButtonControl/Source/ButtonControl.h
Normal file
110
Drivers/ButtonControl/Source/ButtonControl.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/encoder/EncoderDevice.h>
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
|
||||
class ButtonControl final : public tt::hal::encoder::EncoderDevice {
|
||||
|
||||
public:
|
||||
|
||||
enum class Event {
|
||||
ShortPress,
|
||||
LongPress
|
||||
};
|
||||
|
||||
enum class Action {
|
||||
UiSelectNext,
|
||||
UiSelectPrevious,
|
||||
UiPressSelected,
|
||||
AppClose,
|
||||
};
|
||||
|
||||
struct PinConfiguration {
|
||||
tt::hal::gpio::Pin pin;
|
||||
Event event;
|
||||
Action action;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct PinState {
|
||||
long pressStartTime = 0;
|
||||
long pressReleaseTime = 0;
|
||||
bool pressState = false;
|
||||
bool triggerShortPress = false;
|
||||
bool triggerLongPress = false;
|
||||
};
|
||||
|
||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
||||
std::shared_ptr<tt::Thread> driverThread;
|
||||
bool interruptDriverThread = false;
|
||||
tt::Mutex mutex;
|
||||
std::vector<PinConfiguration> pinConfigurations;
|
||||
std::vector<PinState> pinStates;
|
||||
|
||||
bool shouldInterruptDriverThread() const;
|
||||
|
||||
static void updatePin(std::vector<PinConfiguration>::const_reference value, std::vector<PinState>::reference pin_state);
|
||||
|
||||
void driverThreadMain();
|
||||
|
||||
static void readCallback(lv_indev_t* indev, lv_indev_data_t* data);
|
||||
|
||||
void startThread();
|
||||
void stopThread();
|
||||
|
||||
public:
|
||||
|
||||
explicit ButtonControl(const std::vector<PinConfiguration>& pinConfigurations);
|
||||
|
||||
~ButtonControl() override;
|
||||
|
||||
std::string getName() const override { return "ButtonControl"; }
|
||||
std::string getDescription() const override { return "ButtonControl input driver"; }
|
||||
|
||||
bool startLvgl(lv_display_t* display) override;
|
||||
bool stopLvgl() override;
|
||||
|
||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
||||
|
||||
static std::shared_ptr<ButtonControl> createOneButtonControl(tt::hal::gpio::Pin pin) {
|
||||
return std::make_shared<ButtonControl>(std::vector {
|
||||
PinConfiguration {
|
||||
.pin = pin,
|
||||
.event = Event::ShortPress,
|
||||
.action = Action::UiSelectNext
|
||||
},
|
||||
PinConfiguration {
|
||||
.pin = pin,
|
||||
.event = Event::LongPress,
|
||||
.action = Action::UiPressSelected
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static std::shared_ptr<ButtonControl> createTwoButtonControl(tt::hal::gpio::Pin primaryPin, tt::hal::gpio::Pin secondaryPin) {
|
||||
return std::make_shared<ButtonControl>(std::vector {
|
||||
PinConfiguration {
|
||||
.pin = primaryPin,
|
||||
.event = Event::ShortPress,
|
||||
.action = Action::UiPressSelected
|
||||
},
|
||||
PinConfiguration {
|
||||
.pin = primaryPin,
|
||||
.event = Event::LongPress,
|
||||
.action = Action::AppClose
|
||||
},
|
||||
PinConfiguration {
|
||||
.pin = secondaryPin,
|
||||
.event = Event::ShortPress,
|
||||
.action = Action::UiSelectNext
|
||||
},
|
||||
PinConfiguration {
|
||||
.pin = secondaryPin,
|
||||
.event = Event::LongPress,
|
||||
.action = Action::UiSelectPrevious
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user