mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 02:43:15 +00:00
Create GPIO HAL (#344)
This commit is contained in:
parent
bab3eb19bc
commit
7ad0a3cb04
@ -1,7 +1,7 @@
|
||||
#include "TpagerEncoder.h"
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
#include <Tactility/hal/Gpio.h>
|
||||
#include <driver/gpio.h>
|
||||
|
||||
constexpr auto* TAG = "TpagerEncoder";
|
||||
constexpr auto ENCODER_A = GPIO_NUM_40;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
## Medium Priority
|
||||
|
||||
- TactilityTool: Make API compatibility table (and check for compatibility in the tool itself)
|
||||
- Improve EspLcdDisplay to contain all the standard configuration options, and implement a default init function. Add a configuration class.
|
||||
- Statusbar icon that shows low/critical memory warnings
|
||||
- Make WiFi setup app that starts an access point and hosts a webpage to set up the device.
|
||||
|
||||
@ -63,9 +63,6 @@ struct AppManifest {
|
||||
constexpr static uint32_t Hidden = 1 << 1;
|
||||
};
|
||||
|
||||
/** The version of the manifest file format */
|
||||
std::string manifestVersion = {};
|
||||
|
||||
/** The SDK version that was used to compile this app. (e.g. "0.6.0") */
|
||||
std::string targetSdk = {};
|
||||
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <driver/gpio.h>
|
||||
#else
|
||||
typedef unsigned int gpio_num_t;
|
||||
#endif
|
||||
34
Tactility/Include/Tactility/hal/gpio/Gpio.h
Normal file
34
Tactility/Include/Tactility/hal/gpio/Gpio.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace tt::hal::gpio {
|
||||
|
||||
typedef unsigned int Pin;
|
||||
constexpr Pin NO_PIN = -1;
|
||||
|
||||
/** @warning The order must match GpioMode from tt_hal_gpio.h */
|
||||
enum class Mode {
|
||||
Disable = 0,
|
||||
Input,
|
||||
Output,
|
||||
OutputOpenDrain,
|
||||
InputOutput,
|
||||
InputOutputOpenDrain
|
||||
};
|
||||
|
||||
/** Configure a single pin */
|
||||
bool configure(Pin pin, Mode mode, bool pullUp, bool pullDown);
|
||||
|
||||
/** Configure a set of pins defined by their bit index */
|
||||
bool configureWithPinBitmask(uint64_t pinBitMask, Mode mode, bool pullUp, bool pullDown);
|
||||
|
||||
bool setMode(Pin pin, Mode mode);
|
||||
|
||||
bool getLevel(Pin pin);
|
||||
|
||||
bool setLevel(Pin pin, bool level);
|
||||
|
||||
int getPinCount();
|
||||
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Gpio.h"
|
||||
#include "../gpio/Gpio.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <driver/spi_common.h>
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
#define SPI_HOST_MAX 3
|
||||
|
||||
typedef tt::hal::gpio::Pin gpio_num_t;
|
||||
|
||||
typedef int spi_host_device_t;
|
||||
struct spi_bus_config_t {
|
||||
gpio_num_t miso_io_num;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include <Tactility/RtosCompat.h>
|
||||
|
||||
#include "../Gpio.h"
|
||||
#include "../gpio/Gpio.h"
|
||||
#include "Tactility/Lock.h"
|
||||
#include "UartCompat.h"
|
||||
#include "Tactility/hal/uart/Configuration.h"
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "driver/gpio.h"
|
||||
#define GPIO_NUM_MIN GPIO_NUM_0
|
||||
#else
|
||||
#define GPIO_NUM_MIN 0
|
||||
#define GPIO_NUM_MAX 50
|
||||
#endif
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
int gpio_get_level(int gpio_num);
|
||||
#endif
|
||||
@ -60,11 +60,12 @@ bool parseManifest(const std::map<std::string, std::string>& map, AppManifest& m
|
||||
|
||||
// [manifest]
|
||||
|
||||
if (!getValueFromManifest(map, "[manifest]version", manifest.manifestVersion)) {
|
||||
std::string manifest_version;
|
||||
if (!getValueFromManifest(map, "[manifest]version", manifest_version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isValidManifestVersion(manifest.manifestVersion)) {
|
||||
if (!isValidManifestVersion(manifest_version)) {
|
||||
TT_LOG_E(TAG, "Invalid version");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/app/gpio/GpioHal.h>
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
#include "Tactility/lvgl/Toolbar.h"
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Color.h>
|
||||
@ -13,8 +13,8 @@ extern const AppManifest manifest;
|
||||
|
||||
class GpioApp : public App {
|
||||
|
||||
lv_obj_t* lvPins[GPIO_NUM_MAX] = { nullptr };
|
||||
uint8_t pinStates[GPIO_NUM_MAX] = { 0 };
|
||||
std::vector<lv_obj_t*> pinWidgets;
|
||||
std::vector<bool> pinStates;
|
||||
std::unique_ptr<Timer> timer;
|
||||
Mutex mutex;
|
||||
|
||||
@ -36,12 +36,8 @@ public:
|
||||
void GpioApp::updatePinStates() {
|
||||
mutex.lock();
|
||||
// Update pin states
|
||||
for (int i = 0; i < GPIO_NUM_MAX; ++i) {
|
||||
#ifdef ESP_PLATFORM
|
||||
pinStates[i] = gpio_get_level(static_cast<gpio_num_t>(i));
|
||||
#else
|
||||
pinStates[i] = gpio_get_level(i);
|
||||
#endif
|
||||
for (int i = 0; i < pinStates.size(); ++i) {
|
||||
pinStates[i] = hal::gpio::getLevel(i);
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
@ -50,9 +46,10 @@ void GpioApp::updatePinWidgets() {
|
||||
auto scoped_lvgl_lock = lvgl::getSyncLock()->asScopedLock();
|
||||
auto scoped_gpio_lock = mutex.asScopedLock();
|
||||
if (scoped_gpio_lock.lock() && scoped_lvgl_lock.lock(lvgl::defaultLockTime)) {
|
||||
for (int j = 0; j < GPIO_NUM_MAX; ++j) {
|
||||
assert(pinStates.size() == pinWidgets.size());
|
||||
for (int j = 0; j < pinStates.size(); ++j) {
|
||||
int level = pinStates[j];
|
||||
lv_obj_t* label = lvPins[j];
|
||||
lv_obj_t* label = pinWidgets[j];
|
||||
void* label_user_data = lv_obj_get_user_data(label);
|
||||
// The user data stores the state, so we can avoid unnecessary updates
|
||||
if (reinterpret_cast<void*>(level) != label_user_data) {
|
||||
@ -146,7 +143,12 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
lv_obj_align(row_wrapper, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
mutex.lock();
|
||||
for (int i = GPIO_NUM_MIN; i < GPIO_NUM_MAX; ++i) {
|
||||
|
||||
auto pin_count = hal::gpio::getPinCount();
|
||||
pinStates.resize(pin_count);
|
||||
pinWidgets.resize(pin_count);
|
||||
|
||||
for (int i = 0; i < pin_count; ++i) {
|
||||
constexpr uint8_t offset_from_left_label = 4;
|
||||
|
||||
// Add the GPIO number before the first item on a row
|
||||
@ -160,7 +162,8 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
lv_obj_set_pos(status_label, (column+1) * x_spacing + offset_from_left_label, 0);
|
||||
lv_label_set_text_fmt(status_label, "%s", LV_SYMBOL_STOP);
|
||||
lv_obj_set_style_text_color(status_label, lv_color_background_darkest(), LV_STATE_DEFAULT);
|
||||
lvPins[i] = status_label;
|
||||
pinWidgets[i] = status_label;
|
||||
pinStates[i] = false;
|
||||
|
||||
column++;
|
||||
|
||||
@ -185,6 +188,11 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) {
|
||||
|
||||
void GpioApp::onHide(AppContext& app) {
|
||||
stopTask();
|
||||
|
||||
mutex.lock();
|
||||
pinWidgets.clear();
|
||||
pinStates.clear();
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
extern const AppManifest manifest = {
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
int gpio_get_level(int gpio_num) {
|
||||
return gpio_num % 3;
|
||||
}
|
||||
|
||||
#endif
|
||||
87
Tactility/Source/hal/gpio/Gpio.cpp
Normal file
87
Tactility/Source/hal/gpio/Gpio.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <driver/gpio.h>
|
||||
#endif
|
||||
|
||||
namespace tt::hal::gpio {
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
constexpr gpio_num_t toEspPin(Pin pin) { return static_cast<gpio_num_t>(pin); }
|
||||
|
||||
constexpr gpio_mode_t toEspGpioMode(Mode mode) {
|
||||
switch (mode) {
|
||||
case Mode::Input:
|
||||
return GPIO_MODE_INPUT;
|
||||
case Mode::Output:
|
||||
return GPIO_MODE_OUTPUT;
|
||||
case Mode::OutputOpenDrain:
|
||||
return GPIO_MODE_OUTPUT_OD;
|
||||
case Mode::InputOutput:
|
||||
return GPIO_MODE_INPUT_OUTPUT;
|
||||
case Mode::InputOutputOpenDrain:
|
||||
return GPIO_MODE_INPUT_OUTPUT_OD;
|
||||
case Mode::Disable:
|
||||
default:
|
||||
return GPIO_MODE_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool getLevel(Pin pin) {
|
||||
#ifdef ESP_PLATFORM
|
||||
return gpio_get_level(toEspPin(pin)) == 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool setLevel(Pin pin, bool level) {
|
||||
#ifdef ESP_PLATFORM
|
||||
return gpio_set_level(toEspPin(pin), level) == ESP_OK;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int getPinCount() {
|
||||
#ifdef ESP_PLATFORM
|
||||
return GPIO_NUM_MAX;
|
||||
#else
|
||||
return 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool configureWithPinBitmask(uint64_t pinBitMask, Mode mode, bool pullUp, bool pullDown) {
|
||||
#ifdef ESP_PLATFORM
|
||||
gpio_config_t sd_gpio_config = {
|
||||
.pin_bit_mask = pinBitMask,
|
||||
.mode = toEspGpioMode(mode),
|
||||
.pull_up_en = pullUp ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = pullDown ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
return gpio_config(&sd_gpio_config) == ESP_OK;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool configure(Pin pin, Mode mode, bool pullUp, bool pullDown) {
|
||||
#ifdef ESP_PLATFORM
|
||||
return configureWithPinBitmask(BIT64(toEspPin(pin)), mode, pullUp, pullDown);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool setMode(Pin pin, Mode mode) {
|
||||
#ifdef ESP_PLATFORM
|
||||
return gpio_set_direction(toEspPin(pin), toEspGpioMode(mode)) == ESP_OK;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,10 +1,9 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include "Tactility/hal/sdcard/SpiSdCardDevice.h"
|
||||
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||
#include <Tactility/Log.h>
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_vfs_fat.h>
|
||||
#include <sdmmc_cmd.h>
|
||||
|
||||
@ -27,21 +26,13 @@ bool SpiSdCardDevice::applyGpioWorkAround() {
|
||||
pin_bit_mask |= BIT64(pin);
|
||||
}
|
||||
|
||||
gpio_config_t sd_gpio_config = {
|
||||
.pin_bit_mask = pin_bit_mask,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
|
||||
if (gpio_config(&sd_gpio_config) != ESP_OK) {
|
||||
if (!gpio::configureWithPinBitmask(pin_bit_mask, gpio::Mode::Output, false, false)) {
|
||||
TT_LOG_E(TAG, "GPIO init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto const& pin: config->csPinWorkAround) {
|
||||
if (gpio_set_level(pin, 1) != ESP_OK) {
|
||||
if (!gpio::setLevel(pin, true)) {
|
||||
TT_LOG_E(TAG, "Failed to set board CS pin high");
|
||||
return false;
|
||||
}
|
||||
@ -94,7 +85,7 @@ bool SpiSdCardDevice::mountInternal(const std::string& newMountPath) {
|
||||
|
||||
bool SpiSdCardDevice::mount(const std::string& newMountPath) {
|
||||
if (!applyGpioWorkAround()) {
|
||||
TT_LOG_E(TAG, "Failed to set SPI CS pins high. This is a pre-requisite for mounting.");
|
||||
TT_LOG_E(TAG, "Failed to apply GPIO work-around");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
39
TactilityC/Include/tt_hal_gpio.h
Normal file
39
TactilityC/Include/tt_hal_gpio.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned int GpioPin;
|
||||
#define GPIO_NO_PIN -1
|
||||
|
||||
/** @warning The order must match tt::hal::gpio::Mode */
|
||||
enum class GpioMode {
|
||||
Disable = 0,
|
||||
Input,
|
||||
Output,
|
||||
OutputOpenDrain,
|
||||
InputOutput,
|
||||
InputOutputOpenDrain
|
||||
};
|
||||
|
||||
/** Configure a single pin */
|
||||
bool tt_hal_gpio_configure(GpioPin pin, GpioMode mode, bool pullUp, bool pullDown);
|
||||
|
||||
/** Configure a set of pins defined by their bit index */
|
||||
bool tt_hal_gpio_configure_with_pin_bitmask(uint64_t pinBitMask, GpioMode mode, bool pullUp, bool pullDown);
|
||||
|
||||
bool tt_hal_gpio_set_mode(GpioPin pin, GpioMode mode);
|
||||
|
||||
bool tt_hal_gpio_get_level(GpioPin pin);
|
||||
|
||||
bool tt_hal_gpio_set_level(GpioPin pin, bool level);
|
||||
|
||||
int tt_hal_gpio_get_pin_count();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
32
TactilityC/Source/tt_hal_gpio.cpp
Normal file
32
TactilityC/Source/tt_hal_gpio.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "tt_hal_gpio.h"
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
bool tt_hal_gpio_configure(GpioPin pin, GpioMode mode, bool pullUp, bool pullDown) {
|
||||
return gpio::configure(pin, static_cast<gpio::Mode>(mode), pullUp, pullDown);
|
||||
}
|
||||
|
||||
bool tt_hal_gpio_configure_with_pin_bitmask(uint64_t pinBitMask, GpioMode mode, bool pullUp, bool pullDown) {
|
||||
return gpio::configureWithPinBitmask(pinBitMask, static_cast<gpio::Mode>(mode), pullUp, pullDown);
|
||||
}
|
||||
|
||||
bool tt_hal_gpio_set_mode(GpioPin pin, GpioMode mode) {
|
||||
return gpio::setMode(pin, static_cast<gpio::Mode>(mode));
|
||||
}
|
||||
|
||||
bool tt_hal_gpio_get_level(GpioPin pin) {
|
||||
return gpio::getLevel(pin);
|
||||
}
|
||||
|
||||
bool tt_hal_gpio_set_level(GpioPin pin, bool level) {
|
||||
return gpio::setLevel(pin, level);
|
||||
}
|
||||
|
||||
int tt_hal_gpio_get_pin_count() {
|
||||
return gpio::getPinCount();
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,6 +8,7 @@
|
||||
#include "tt_gps.h"
|
||||
#include "tt_hal_device.h"
|
||||
#include "tt_hal_display.h"
|
||||
#include "tt_hal_gpio.h"
|
||||
#include "tt_hal_i2c.h"
|
||||
#include "tt_hal_touch.h"
|
||||
#include "tt_kernel.h"
|
||||
@ -205,6 +206,12 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_lock),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_unlock),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_supported),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_configure),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_configure_with_pin_bitmask),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_set_mode),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_get_level),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_set_level),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_gpio_get_pin_count),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_i2c_start),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_i2c_stop),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_i2c_is_started),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user