GPIO descriptor fixes (#578)
This commit is contained in:
committed by
GitHub
parent
a3fda9ad8f
commit
8b92aa8e5a
@@ -86,9 +86,7 @@
|
||||
vsync-back-porch = <8>;
|
||||
vsync-front-porch = <8>;
|
||||
pclk-active-neg;
|
||||
num-fbs = <2>;
|
||||
double-fb;
|
||||
bounce-buffer-size-px = <8000>;
|
||||
bounce-buffer-size-px = <4000>;
|
||||
pin-hsync = <&gpio0 40 GPIO_FLAG_NONE>;
|
||||
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
|
||||
pin-de = <&gpio0 42 GPIO_FLAG_NONE>;
|
||||
|
||||
@@ -89,9 +89,7 @@
|
||||
vsync-back-porch = <12>;
|
||||
vsync-front-porch = <8>;
|
||||
pclk-active-neg;
|
||||
num-fbs = <2>;
|
||||
double-fb;
|
||||
bounce-buffer-size-px = <8000>;
|
||||
bounce-buffer-size-px = <4000>;
|
||||
pin-hsync = <&gpio0 39 GPIO_FLAG_NONE>;
|
||||
pin-vsync = <&gpio0 41 GPIO_FLAG_NONE>;
|
||||
pin-de = <&gpio0 40 GPIO_FLAG_NONE>;
|
||||
|
||||
@@ -205,5 +205,4 @@
|
||||
backlight = <&display_backlight>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "papers3_power.h"
|
||||
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/power_supply.h>
|
||||
#include <tactility/drivers/pwm.h>
|
||||
@@ -13,7 +15,7 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#define TAG "Papers3Power"
|
||||
constexpr auto* TAG = "Papers3Power";
|
||||
#define GET_CONFIG(device) (static_cast<const Papers3PowerConfig*>((device)->config))
|
||||
|
||||
// Power-off signal timing, ported from the old deprecated-HAL PaperS3Power::powerOff().
|
||||
@@ -192,17 +194,8 @@ static void destroy_power_supply_child(Device* child) {
|
||||
// region Driver lifecycle
|
||||
|
||||
static error_t acquire_input(const GpioPinSpec& pin, GpioDescriptor** out_descriptor) {
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_INPUT);
|
||||
if (error != ERROR_NONE) {
|
||||
gpio_descriptor_release(descriptor);
|
||||
return error;
|
||||
}
|
||||
*out_descriptor = descriptor;
|
||||
return ERROR_NONE;
|
||||
*out_descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
|
||||
return (*out_descriptor != nullptr) ? ERROR_NONE : ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
static error_t start(Device* device) {
|
||||
@@ -226,13 +219,8 @@ static error_t start(Device* device) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, GPIO_OWNER_GPIO);
|
||||
if (internal->power_off_descriptor == nullptr ||
|
||||
gpio_descriptor_set_flags(internal->power_off_descriptor, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure power-off pin");
|
||||
if (internal->power_off_descriptor != nullptr) {
|
||||
gpio_descriptor_release(internal->power_off_descriptor);
|
||||
}
|
||||
internal->power_off_descriptor = gpio_descriptor_acquire(config->pin_power_off.gpio_controller, config->pin_power_off.pin, config->pin_power_off.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (internal->power_off_descriptor == nullptr) {
|
||||
gpio_descriptor_release(internal->usb_detect_descriptor);
|
||||
gpio_descriptor_release(internal->charge_status_descriptor);
|
||||
delete internal;
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <tactility/bindings/esp32_grove.h>
|
||||
#include <tactility/bindings/esp32_i2c.h>
|
||||
#include <tactility/bindings/esp32_i2s.h>
|
||||
#include <tactility/bindings/esp32_sdspi.h>
|
||||
#include <tactility/bindings/esp32_spi.h>
|
||||
#include <tactility/bindings/esp32_uart.h>
|
||||
#include <tactility/bindings/gpio_hog.h>
|
||||
#include <bindings/aw88298.h>
|
||||
#include <bindings/aw9523b.h>
|
||||
#include <bindings/axp2101.h>
|
||||
@@ -20,8 +22,6 @@
|
||||
#include <bindings/ili9341.h>
|
||||
#include <bindings/ina226.h>
|
||||
#include <bindings/py32ioexpander.h>
|
||||
#include <tactility/bindings/esp32_sdspi.h>
|
||||
#include <tactility/bindings/gpio_hog.h>
|
||||
|
||||
// Reference: https://docs.m5stack.com/en/StackChan
|
||||
/ {
|
||||
@@ -101,7 +101,7 @@
|
||||
aw9523_sdcard_switch {
|
||||
compatible = "gpio-hog";
|
||||
pin = <&aw9523b 4 GPIO_FLAG_NONE>;
|
||||
mode = <GPIO_HOG_MODE_OUTPUT_HIGH>;
|
||||
mode = <GPIO_HOG_MODE_INPUT>;
|
||||
};
|
||||
|
||||
aw9523_boost_enable {
|
||||
|
||||
@@ -36,14 +36,14 @@ static void apply_gt911_int_workaround() {
|
||||
LOG_W(TAG, "display_detect: gpio0 not found, GT911 INT workaround not applied");
|
||||
return;
|
||||
}
|
||||
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_OWNER_GPIO);
|
||||
auto* int_pin = gpio_descriptor_acquire(gpio0, 23, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
device_put(gpio0);
|
||||
if (int_pin == nullptr) {
|
||||
LOG_W(TAG, "display_detect: failed to acquire GPIO23 for GT911 INT workaround");
|
||||
return;
|
||||
}
|
||||
gpio_descriptor_set_flags(int_pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_PULL_UP);
|
||||
gpio_descriptor_set_level(int_pin, false);
|
||||
gpio_descriptor_set_level(int_pin, true);
|
||||
gpio_descriptor_release(int_pin);
|
||||
}
|
||||
|
||||
@@ -67,8 +67,6 @@ static void create_gt911_touch(Device* i2c0) {
|
||||
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
|
||||
.pin_reset = GPIO_PIN_SPEC_NONE,
|
||||
.pin_interrupt = GPIO_PIN_SPEC_NONE,
|
||||
.reset_active_high = false,
|
||||
.interrupt_active_high = false,
|
||||
};
|
||||
gt911_device.config = >911_config;
|
||||
|
||||
@@ -103,7 +101,6 @@ void tab5_create_devices_v1(Device* i2c0) {
|
||||
// LCD reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a
|
||||
// direct SoC GPIO.
|
||||
.pin_reset = GPIO_PIN_SPEC_NONE,
|
||||
.reset_active_high = false,
|
||||
.ldo_channel = 3,
|
||||
.ldo_voltage_mv = 2500,
|
||||
.dsi_bus_id = 0,
|
||||
|
||||
@@ -50,8 +50,6 @@ static void create_st7123_touch(Device* i2c0) {
|
||||
// Reset is pulsed via io_expander0 (detect.cpp's pulse_display_reset_pins), not a direct SoC GPIO.
|
||||
.pin_reset = GPIO_PIN_SPEC_NONE,
|
||||
.pin_interrupt = pin_interrupt,
|
||||
.reset_active_high = false,
|
||||
.interrupt_active_high = false,
|
||||
};
|
||||
st7123_touch_device.config = &st7123_touch_config;
|
||||
|
||||
@@ -82,7 +80,6 @@ void tab5_create_devices_v2(Device* i2c0) {
|
||||
.mirror_x = false,
|
||||
.mirror_y = false,
|
||||
.pin_reset = GPIO_PIN_SPEC_NONE,
|
||||
.reset_active_high = false,
|
||||
.ldo_channel = 3,
|
||||
.ldo_voltage_mv = 2500,
|
||||
.dsi_bus_id = 0,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "detect.h"
|
||||
|
||||
#include "../../../../TactilityKernel/include/tactility/log.h"
|
||||
#include "devices_common.h"
|
||||
#include "devices_v1.h"
|
||||
#include "devices_v2.h"
|
||||
@@ -8,6 +7,7 @@
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/device_listener.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
@@ -36,8 +36,8 @@ constexpr auto GPIO_EXP0_PIN_LCD_RESET = 4;
|
||||
constexpr auto GPIO_EXP0_PIN_TOUCH_RESET = 5;
|
||||
|
||||
bool pulse_display_reset_pins(Device* io_expander0) {
|
||||
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_OWNER_GPIO);
|
||||
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_OWNER_GPIO);
|
||||
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (lcd_reset_pin == nullptr || touch_reset_pin == nullptr) {
|
||||
LOG_E(TAG, "display_detect: failed to acquire LCD/touch reset pins on io_expander0");
|
||||
if (lcd_reset_pin != nullptr) {
|
||||
@@ -51,11 +51,11 @@ bool pulse_display_reset_pins(Device* io_expander0) {
|
||||
|
||||
gpio_descriptor_set_flags(lcd_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_flags(touch_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(lcd_reset_pin, false);
|
||||
gpio_descriptor_set_level(touch_reset_pin, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_descriptor_set_level(lcd_reset_pin, true);
|
||||
gpio_descriptor_set_level(touch_reset_pin, true);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_descriptor_set_level(lcd_reset_pin, false);
|
||||
gpio_descriptor_set_level(touch_reset_pin, false);
|
||||
|
||||
gpio_descriptor_release(lcd_reset_pin);
|
||||
gpio_descriptor_release(touch_reset_pin);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "tab5_headphone_detect.h"
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
@@ -35,7 +36,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
|
||||
return; // Not ready yet, will retry on next tick
|
||||
}
|
||||
|
||||
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
|
||||
auto* hp_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
|
||||
if (!hp_pin) {
|
||||
LOG_W(TAG, "hp_detect: HP_DET pin busy");
|
||||
return;
|
||||
@@ -53,7 +54,7 @@ static void headphone_detect_callback(TimerHandle_t /*timer*/) {
|
||||
LOG_D(TAG, "hp_detect: HP_DET=%d", (int)hp);
|
||||
|
||||
if (!hp_detect_initialized || hp != hp_detect_last) {
|
||||
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
|
||||
auto* spk_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (!spk_pin) {
|
||||
LOG_W(TAG, "hp_detect: SPK_EN pin busy, will retry");
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/power_supply.h>
|
||||
#include <tactility/log.h>
|
||||
@@ -51,15 +52,12 @@ static error_t ps_set_allowed_to_charge(Device* device, bool allowed) {
|
||||
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
|
||||
auto* io_expander1 = device_get_parent(device);
|
||||
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_OWNER_GPIO);
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (pin == nullptr) {
|
||||
LOG_W(TAG, "Failed to acquire CHG_EN pin");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_set_level(pin, allowed);
|
||||
}
|
||||
auto error = gpio_descriptor_set_level(pin, allowed);
|
||||
gpio_descriptor_release(pin);
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_W(TAG, "Failed to set CHG_EN pin");
|
||||
@@ -83,15 +81,12 @@ static error_t ps_set_quick_charge_enabled(Device* device, bool enabled) {
|
||||
auto* internal = static_cast<Tab5PowerControlInternal*>(device_get_driver_data(device));
|
||||
auto* io_expander1 = device_get_parent(device);
|
||||
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_OWNER_GPIO);
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (pin == nullptr) {
|
||||
LOG_W(TAG, "Failed to acquire nCHG_QC_EN pin");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_flags(pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_set_level(pin, !enabled); // active-low
|
||||
}
|
||||
auto error = gpio_descriptor_set_level(pin, !enabled); // active-low
|
||||
gpio_descriptor_release(pin);
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_W(TAG, "Failed to set nCHG_QC_EN pin");
|
||||
@@ -108,7 +103,7 @@ static bool ps_supports_power_off(Device*) {
|
||||
|
||||
static error_t ps_power_off(Device* device) {
|
||||
auto* io_expander1 = device_get_parent(device);
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
|
||||
auto* pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (pin == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire DEVICE_POWER pin");
|
||||
return ERROR_RESOURCE;
|
||||
@@ -153,9 +148,8 @@ static error_t start(Device* device) {
|
||||
// as an idle-low output up front so it's in a known state (previously done by Configuration.cpp's
|
||||
// initExpander1(), now owned here - see that function's comment for why it no longer touches it).
|
||||
auto* io_expander1 = device_get_parent(device);
|
||||
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
|
||||
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (device_power_pin != nullptr) {
|
||||
gpio_descriptor_set_flags(device_power_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(device_power_pin, false);
|
||||
gpio_descriptor_release(device_power_pin);
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <tactility/module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/device_listener.h>
|
||||
@@ -25,14 +26,11 @@ constexpr auto GPIO_EXP0_PIN_HEADPHONE_DETECT = 7;
|
||||
static void tab5_init_expander0(Device* io_expander0) {
|
||||
// Speaker and heapdhone pins are managed at runtime, so we can't have them as a hog in the dts file
|
||||
// We have to init them manually.
|
||||
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
|
||||
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
check(speaker_enable_pin);
|
||||
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
|
||||
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
|
||||
check(headphone_detect_pin);
|
||||
|
||||
gpio_descriptor_set_flags(speaker_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_flags(headphone_detect_pin, GPIO_FLAG_DIRECTION_INPUT);
|
||||
|
||||
gpio_descriptor_set_level(speaker_enable_pin, false);
|
||||
|
||||
gpio_descriptor_release(speaker_enable_pin);
|
||||
@@ -40,7 +38,7 @@ static void tab5_init_expander0(Device* io_expander0) {
|
||||
}
|
||||
|
||||
static void tab5_enable_speaker_amp(Device* io_expander0) {
|
||||
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
|
||||
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
check(speaker_enable_pin, "Failed to acquire speaker enable pin");
|
||||
error_t error = gpio_descriptor_set_level(speaker_enable_pin, true);
|
||||
gpio_descriptor_release(speaker_enable_pin);
|
||||
|
||||
@@ -21,10 +21,8 @@ bool BatteryManager::initGpioExpander() {
|
||||
return false;
|
||||
}
|
||||
|
||||
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_OWNER_GPIO);
|
||||
expanderPowerPin = gpio_descriptor_acquire(expander, expanderpin::EXPANDER_POWER, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
check(expanderPowerPin != nullptr);
|
||||
gpio_descriptor_set_flags(expanderPowerPin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
|
||||
device_put(expander);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -90,21 +90,19 @@ static int32_t nav_buttons_thread_main(UnphoneNavButtonsInternal* internal) {
|
||||
// region Pin acquisition
|
||||
|
||||
static error_t acquire_button(const GpioPinSpec& pin, void (*callback)(void*), void* arg, GpioDescriptor** out_descriptor) {
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
// Digital pull-up; the buttons pull the pin low while pressed. Listen for the release
|
||||
// (positive edge) rather than the press - if we listen to the press, these buttons can
|
||||
// generate more than one signal when held down (mirrors the original unPhone init).
|
||||
gpio_flags_t flags = GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
|
||||
flags = GPIO_FLAG_INTERRUPT_TO_OPTIONS(flags, GPIO_INTERRUPT_POS_EDGE);
|
||||
|
||||
error_t error = gpio_descriptor_set_flags(descriptor, flags);
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_add_callback(descriptor, callback, arg);
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, flags, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
auto error = gpio_descriptor_add_callback(descriptor, callback, arg);
|
||||
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_enable_interrupt(descriptor);
|
||||
}
|
||||
|
||||
@@ -25,18 +25,12 @@ extern Module unphone_module;
|
||||
static error_t start(Device* device) {
|
||||
const auto* config = GET_CONFIG(device);
|
||||
|
||||
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, GPIO_OWNER_GPIO);
|
||||
auto* descriptor = gpio_descriptor_acquire(config->pin.gpio_controller, config->pin.pin, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire GPIO descriptor");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (gpio_descriptor_set_flags(descriptor, config->pin.flags | GPIO_FLAG_DIRECTION_INPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure power switch pin as input");
|
||||
gpio_descriptor_release(descriptor);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
gpio_num_t native_pin;
|
||||
if (gpio_descriptor_get_native_pin_number(descriptor, &native_pin) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Power switch pin has no native pin number");
|
||||
|
||||
@@ -96,9 +96,8 @@
|
||||
vsync-back-porch = <8>;
|
||||
vsync-front-porch = <8>;
|
||||
pclk-active-neg;
|
||||
num-fbs = <2>;
|
||||
double-fb;
|
||||
bounce-buffer-size-px = <8000>;
|
||||
num-fbs = <1>;
|
||||
bounce-buffer-size-px = <4000>;
|
||||
pin-hsync = <&gpio0 46 GPIO_FLAG_NONE>;
|
||||
pin-vsync = <&gpio0 3 GPIO_FLAG_NONE>;
|
||||
pin-de = <&gpio0 5 GPIO_FLAG_NONE>;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
## Higher Priority
|
||||
|
||||
- LilyGO T-Dongle S3: 1 button control, stop auto-launching web server
|
||||
- Core2: support power off via software
|
||||
- Create `#define` for empty module (for modules that fully rely on device.properties and don't define drivers or have start/stop logic)
|
||||
- Get rid of TactilityC in favour of TactilityKernel and kernel modules
|
||||
- Improve SPI kernel driver (implement read, write, transactions)
|
||||
|
||||
@@ -17,7 +17,7 @@ struct GpioAdapterContext {
|
||||
|
||||
static struct GpioAdapterContext* g_context = NULL;
|
||||
|
||||
static struct GpioDescriptor* acquire_descriptor(int16_t gpio) {
|
||||
static struct GpioDescriptor* acquire_descriptor(int16_t gpio, gpio_flags_t flags) {
|
||||
if (g_context == NULL || gpio < 0 || (size_t) gpio >= g_context->pin_count) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -31,24 +31,31 @@ static struct GpioDescriptor* acquire_descriptor(int16_t gpio) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct GpioDescriptor* descriptor = gpio_descriptor_acquire(spec->gpio_controller, spec->pin, GPIO_OWNER_GPIO);
|
||||
struct GpioDescriptor* descriptor = gpio_descriptor_acquire(
|
||||
spec->gpio_controller, spec->pin, spec->flags | flags, GPIO_OWNER_GPIO
|
||||
);
|
||||
if (descriptor != NULL) {
|
||||
gpio_descriptor_set_flags(descriptor, spec->flags);
|
||||
g_context->descriptors[gpio] = descriptor;
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
static int gpio_setup(int16_t gpio, audio_gpio_dir_t dir, audio_gpio_mode_t mode) {
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio);
|
||||
gpio_flags_t flags = (dir == AUDIO_GPIO_DIR_OUT) ? GPIO_FLAG_DIRECTION_OUTPUT : GPIO_FLAG_DIRECTION_INPUT;
|
||||
if ((mode & AUDIO_GPIO_MODE_PULL_UP) != 0) {
|
||||
flags |= GPIO_FLAG_PULL_UP;
|
||||
}
|
||||
if ((mode & AUDIO_GPIO_MODE_PULL_DOWN) != 0) {
|
||||
flags |= GPIO_FLAG_PULL_DOWN;
|
||||
}
|
||||
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio, flags);
|
||||
if (descriptor == NULL) {
|
||||
return ESP_CODEC_DEV_NOT_FOUND;
|
||||
}
|
||||
|
||||
gpio_flags_t flags = GPIO_FLAG_NONE;
|
||||
gpio_descriptor_get_flags(descriptor, &flags);
|
||||
flags &= ~(GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_PULL_UP | GPIO_FLAG_PULL_DOWN);
|
||||
|
||||
flags |= (dir == AUDIO_GPIO_DIR_OUT) ? GPIO_FLAG_DIRECTION_OUTPUT : GPIO_FLAG_DIRECTION_INPUT;
|
||||
if ((mode & AUDIO_GPIO_MODE_PULL_UP) != 0) {
|
||||
flags |= GPIO_FLAG_PULL_UP;
|
||||
@@ -61,7 +68,7 @@ static int gpio_setup(int16_t gpio, audio_gpio_dir_t dir, audio_gpio_mode_t mode
|
||||
}
|
||||
|
||||
static int gpio_set(int16_t gpio, bool high) {
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio);
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
if (descriptor == NULL) {
|
||||
return ESP_CODEC_DEV_NOT_FOUND;
|
||||
}
|
||||
@@ -72,7 +79,7 @@ static int gpio_set(int16_t gpio, bool high) {
|
||||
// acquire and a legitimate low reading are indistinguishable to the caller; log so the
|
||||
// failure is at least visible.
|
||||
static bool gpio_get(int16_t gpio) {
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio);
|
||||
struct GpioDescriptor* descriptor = acquire_descriptor(gpio, GPIO_FLAG_DIRECTION_INPUT);
|
||||
if (descriptor == NULL) {
|
||||
LOG_E(TAG, "gpio_get: failed to acquire descriptor for pin %d", gpio);
|
||||
return false;
|
||||
|
||||
@@ -253,15 +253,14 @@ error_t start_device(Device* device) {
|
||||
// (unlike a board Configuration.cpp initBoot() callback, which only runs after ALL
|
||||
// devicetree devices, including this one, have already started).
|
||||
if (config->reset_pin.gpio_controller != nullptr) {
|
||||
auto* reset_descriptor = gpio_descriptor_acquire(config->reset_pin.gpio_controller, config->reset_pin.pin, GPIO_OWNER_GPIO);
|
||||
auto* reset_descriptor = gpio_descriptor_acquire(config->reset_pin.gpio_controller, config->reset_pin.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset pin descriptor");
|
||||
goto cleanup;
|
||||
}
|
||||
gpio_descriptor_set_flags(reset_descriptor, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(reset_descriptor, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_descriptor_set_level(reset_descriptor, true);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_descriptor_set_level(reset_descriptor, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
gpio_descriptor_release(reset_descriptor);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,10 @@ static error_t set_level(GpioDescriptor* descriptor, bool high) {
|
||||
uint8_t bit = 1U << (descriptor->pin % 8U);
|
||||
uint8_t reg = portRegister(isPort1, AW9523B_REG_OUTPUT_P0, AW9523B_REG_OUTPUT_P1);
|
||||
|
||||
if (high) {
|
||||
// This chip has no output polarity register: active-low must be inverted in software.
|
||||
bool physical_high = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !high : high;
|
||||
|
||||
if (physical_high) {
|
||||
return i2c_controller_register8_set_bits(parent, address, reg, bit, portMAX_DELAY);
|
||||
} else {
|
||||
return i2c_controller_register8_reset_bits(parent, address, reg, bit, portMAX_DELAY);
|
||||
@@ -90,7 +93,8 @@ static error_t get_level(GpioDescriptor* descriptor, bool* high) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*high = (bits & bit) != 0;
|
||||
bool physical_high = (bits & bit) != 0;
|
||||
*high = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !physical_high : physical_high;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -126,6 +130,7 @@ static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
||||
|
||||
// Config register is inverted: 0 = output, 1 = input.
|
||||
*flags = (val & bit) ? GPIO_FLAG_DIRECTION_INPUT : GPIO_FLAG_DIRECTION_OUTPUT;
|
||||
*flags |= (descriptor->flags & GPIO_FLAG_ACTIVE_LOW);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,14 +35,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
transmit-timeout:
|
||||
type: int
|
||||
default: 100
|
||||
|
||||
@@ -19,8 +19,6 @@ struct Axs5106Config {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
// Timeout (ms) for the register-address write half of a read, and for the data-read half,
|
||||
// done as two separate I2C transactions - matches the vendor factory demo's
|
||||
// i2c_master_transmit()/i2c_master_receive() split (each with its own 100ms timeout),
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/axs5106.h>
|
||||
|
||||
#include <axs5106_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/gpio_descriptor.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
#include <tactility/error.h>
|
||||
@@ -41,16 +42,10 @@ struct Axs5106Internal {
|
||||
|
||||
// region Driver lifecycle
|
||||
|
||||
// Matches the vendor demo's touch_axs5106_reset(): pulse the reset pin active for 10ms, then
|
||||
// release it for 10ms before any I2C traffic. No separate init step follows - the vendor demo's
|
||||
// touch_axs5106_init() is a no-op too.
|
||||
static error_t reset_pulse(GpioDescriptor* descriptor, bool active_high) {
|
||||
bool idle_level = !active_high;
|
||||
|
||||
bool ok = gpio_descriptor_set_flags(descriptor, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, active_high) == ERROR_NONE;
|
||||
static error_t reset_pulse(GpioDescriptor* descriptor) {
|
||||
bool ok = gpio_descriptor_set_level(descriptor, true) == ERROR_NONE;
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, idle_level) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, false) == ERROR_NONE;
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
return ok ? ERROR_NONE : ERROR_RESOURCE;
|
||||
@@ -73,14 +68,14 @@ static error_t start(Device* device) {
|
||||
internal->point_count = 0;
|
||||
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset pin");
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (reset_pulse(internal->reset_descriptor, config->reset_active_high) != ERROR_NONE) {
|
||||
if (reset_pulse(internal->reset_descriptor) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to pulse reset pin");
|
||||
gpio_descriptor_release(internal->reset_descriptor);
|
||||
free(internal);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/button_control.h>
|
||||
|
||||
#include <button_control_module.h>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/keyboard.h>
|
||||
#include <tactility/error.h>
|
||||
@@ -72,18 +74,12 @@ static error_t acquire_button(const GpioPinSpec& pin, uint32_t short_press_key,
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, pin.flags | GPIO_FLAG_DIRECTION_INPUT, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire GPIO descriptor");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_INPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure GPIO as input");
|
||||
gpio_descriptor_release(descriptor);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
*out_state = {
|
||||
.descriptor = descriptor,
|
||||
.in_use = true,
|
||||
|
||||
@@ -26,7 +26,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Optional reset GPIO pin. Falls back to a software reset command if not set.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
|
||||
@@ -17,7 +17,6 @@ struct Cst328Config {
|
||||
bool mirror_x;
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/cst328.h>
|
||||
|
||||
#include <cst328_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/delay.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
@@ -55,12 +57,11 @@ static bool query(Device* i2c, uint8_t address, uint8_t b0, uint8_t b1, uint8_t*
|
||||
// chip's own software reset command instead.
|
||||
static void perform_reset(Device* i2c, uint8_t address, const Cst328Config* config) {
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (rst != nullptr) {
|
||||
gpio_descriptor_set_flags(rst, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(rst, config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, true);
|
||||
delay_millis(100);
|
||||
gpio_descriptor_set_level(rst, !config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, false);
|
||||
gpio_descriptor_release(rst);
|
||||
delay_millis(100);
|
||||
return;
|
||||
|
||||
@@ -35,7 +35,3 @@ properties:
|
||||
type: phandles
|
||||
required: true
|
||||
description: Reset GPIO pin. The chip only re-initializes into normal reporting mode after a clean reset pulse.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
|
||||
@@ -19,7 +19,6 @@ struct Cst66xxConfig {
|
||||
bool mirror_x;
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/cst66xx.h>
|
||||
|
||||
#include <cst66xx_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/delay.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/gpio_descriptor.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
#include <tactility/error.h>
|
||||
@@ -61,15 +62,18 @@ static void perform_hardware_reset(const Cst66xxConfig* config) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
// Not requesting GPIO_FLAG_ACTIVE_LOW here: some GPIO expanders (e.g. xl9555/tca95xx/
|
||||
// tca9534) can only invert what's read back from an input, not what's driven on an
|
||||
// output, so they reject ACTIVE_LOW combined with OUTPUT. Drive the raw physical level
|
||||
// instead: this pin's reset line is active-low, so low asserts and high releases.
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (rst == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_descriptor_set_flags(rst, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(rst, config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, false);
|
||||
delay_millis(10);
|
||||
gpio_descriptor_set_level(rst, !config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, true);
|
||||
gpio_descriptor_release(rst);
|
||||
// The reset pulse exits boot mode; give the controller time to re-init.
|
||||
delay_millis(80);
|
||||
|
||||
@@ -35,11 +35,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -22,8 +22,6 @@ struct Cst816sConfig {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -75,9 +75,10 @@ static error_t start(Device* device) {
|
||||
.y_max = config->y_max,
|
||||
.rst_gpio_num = pin_or_nc(config->pin_reset),
|
||||
.int_gpio_num = pin_or_nc(config->pin_interrupt),
|
||||
// CST816S's reset and interrupt lines are both fixed active-low in hardware.
|
||||
.levels = {
|
||||
.reset = config->reset_active_high ? 1u : 0u,
|
||||
.interrupt = config->interrupt_active_high ? 1u : 0u,
|
||||
.reset = 0u,
|
||||
.interrupt = 0u,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = config->swap_xy ? 1u : 0u,
|
||||
|
||||
@@ -35,11 +35,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin (currently unused - reads are polled via read_data())
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -19,8 +19,6 @@ struct Cst816tConfig {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/cst816t.h>
|
||||
|
||||
#include <cst816t_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/gpio_descriptor.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
#include <tactility/error.h>
|
||||
@@ -44,15 +45,12 @@ struct Cst816tInternal {
|
||||
// Timings match the reference driver linked above: it holds RST high for 100ms (well past the
|
||||
// datasheet's Tpor/Tron minimum of 100ms), pulses it low for 10ms (Trst minimum is 0.1ms), then
|
||||
// waits another 100ms (Tron) for the chip to finish reinitializing before any I2C traffic.
|
||||
static error_t reset_pulse(GpioDescriptor* descriptor, bool active_high) {
|
||||
bool idle_level = !active_high;
|
||||
|
||||
bool ok = gpio_descriptor_set_flags(descriptor, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, idle_level) == ERROR_NONE;
|
||||
static error_t reset_pulse(GpioDescriptor* descriptor) {
|
||||
bool ok = gpio_descriptor_set_level(descriptor, false) == ERROR_NONE;
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, active_high) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, true) == ERROR_NONE;
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, idle_level) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, false) == ERROR_NONE;
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
return ok ? ERROR_NONE : ERROR_RESOURCE;
|
||||
@@ -77,14 +75,14 @@ static error_t start(Device* device) {
|
||||
internal->y = 0;
|
||||
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset pin");
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (reset_pulse(internal->reset_descriptor, config->reset_active_high) != ERROR_NONE) {
|
||||
if (reset_pulse(internal->reset_descriptor) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to pulse reset pin");
|
||||
gpio_descriptor_release(internal->reset_descriptor);
|
||||
free(internal);
|
||||
|
||||
@@ -35,11 +35,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -21,8 +21,6 @@ struct Ft5x06Config {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -36,30 +36,26 @@ struct Ft5x06Internal {
|
||||
// over as if it were one (the previous pin_or_nc() behavior below) silently toggles the wrong,
|
||||
// unrelated physical pin whenever pin_reset actually points at an I2C expander.
|
||||
GpioDescriptor* reset_descriptor;
|
||||
bool reset_active_high;
|
||||
};
|
||||
|
||||
// Only valid for pin_interrupt: esp_lcd_touch only ever reads this pin's level / attaches an ISR
|
||||
// to it, both of which esp_lcd_touch performs via ESP-IDF's native gpio_* calls, so - like
|
||||
// ili9341-module's cs/dc pins - it must be a real ESP32 GPIO. pin_reset has no such requirement and
|
||||
// must never go through this helper; see pulse_reset() instead.
|
||||
static inline gpio_num_t pin_or_nc(const struct GpioPinSpec& pin) {
|
||||
static inline gpio_num_t pin_or_nc(const GpioPinSpec& pin) {
|
||||
return pin.gpio_controller == nullptr ? GPIO_NUM_NC : static_cast<gpio_num_t>(pin.pin);
|
||||
}
|
||||
|
||||
// See esp_lcd_ili9341-module's pulse_reset() for the full rationale; same idea, same 10ms/10ms
|
||||
// timing (matches esp_lcd_touch_ft5x06's own touch_ft5x06_reset()). esp_lcd_touch's rst_gpio_num is
|
||||
// always left at GPIO_NUM_NC (see start()), under which it just skips its own reset step entirely.
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor, bool active_high) {
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor) {
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_level(descriptor, active_high);
|
||||
error_t error = gpio_descriptor_set_level(descriptor, true);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
error = gpio_descriptor_set_level(descriptor, !active_high);
|
||||
error = gpio_descriptor_set_level(descriptor, false);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
@@ -101,20 +97,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
internal->reset_descriptor = nullptr;
|
||||
internal->reset_active_high = config->reset_active_high;
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset GPIO descriptor");
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
if (gpio_descriptor_set_flags(internal->reset_descriptor, config->pin_reset.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure reset pin as output");
|
||||
gpio_descriptor_release(internal->reset_descriptor);
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t ret = create_io_handle(parent, &internal->io_handle);
|
||||
@@ -126,7 +115,7 @@ static error_t start(Device* device) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (pulse_reset(internal->reset_descriptor, internal->reset_active_high) != ERROR_NONE) {
|
||||
if (pulse_reset(internal->reset_descriptor) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to pulse reset pin");
|
||||
esp_lcd_panel_io_del(internal->io_handle);
|
||||
if (internal->reset_descriptor != nullptr) {
|
||||
@@ -143,9 +132,10 @@ static error_t start(Device* device) {
|
||||
// why); esp_lcd_touch just skips its own no-op reset step when this is NC.
|
||||
.rst_gpio_num = GPIO_NUM_NC,
|
||||
.int_gpio_num = pin_or_nc(config->pin_interrupt),
|
||||
// FT5x06's reset and interrupt lines are both fixed active-low in hardware.
|
||||
.levels = {
|
||||
.reset = config->reset_active_high ? 1u : 0u,
|
||||
.interrupt = config->interrupt_active_high ? 1u : 0u,
|
||||
.reset = 0u,
|
||||
.interrupt = 0u,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = config->swap_xy ? 1u : 0u,
|
||||
|
||||
@@ -35,11 +35,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -21,8 +21,6 @@ struct Ft6x36Config {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/ft6x36.h>
|
||||
|
||||
#include <ft6x36_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
@@ -7,6 +8,7 @@
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
@@ -30,13 +32,7 @@ struct Ft6x36Internal {
|
||||
esp_lcd_panel_io_handle_t io_handle;
|
||||
esp_lcd_touch_handle_t touch_handle;
|
||||
// Non-null when pin_reset is configured. Owned/pulsed by this driver instead of esp_lcd_touch
|
||||
// (see pulse_reset() below) so the reset pin can live on any GPIO_CONTROLLER, not just native
|
||||
// gpio0 - esp_lcd_touch's rst_gpio_num only accepts a native ESP32 GPIO number (it calls
|
||||
// gpio_set_level() directly), and just reading a GpioPinSpec's raw pin index and handing it
|
||||
// over as if it were one (the previous pin_or_nc() behavior below) silently toggles the wrong,
|
||||
// unrelated physical pin whenever pin_reset actually points at an I2C expander.
|
||||
GpioDescriptor* reset_descriptor;
|
||||
bool reset_active_high;
|
||||
};
|
||||
|
||||
// Only valid for pin_interrupt: esp_lcd_touch only ever reads this pin's level / attaches an ISR
|
||||
@@ -50,16 +46,18 @@ static inline gpio_num_t pin_or_nc(const struct GpioPinSpec& pin) {
|
||||
// See ili9341-module's pulse_reset() for the full rationale; same idea, same 10ms/10ms timing.
|
||||
// esp_lcd_touch's rst_gpio_num is always left at GPIO_NUM_NC (see start()), under which it just
|
||||
// skips its own reset step entirely.
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor, bool active_high) {
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor) {
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_level(descriptor, active_high);
|
||||
// Logical high (physical low, because of earlier GPIO_FLAG_ACTIVE_LOW)
|
||||
error_t error = gpio_descriptor_set_level(descriptor, true);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
error = gpio_descriptor_set_level(descriptor, !active_high);
|
||||
// Logical low (physical high, because of earlier GPIO_FLAG_ACTIVE_LOW)
|
||||
error = gpio_descriptor_set_level(descriptor, false);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
@@ -101,20 +99,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
internal->reset_descriptor = nullptr;
|
||||
internal->reset_active_high = config->reset_active_high;
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset GPIO descriptor");
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
if (gpio_descriptor_set_flags(internal->reset_descriptor, config->pin_reset.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure reset pin as output");
|
||||
gpio_descriptor_release(internal->reset_descriptor);
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t ret = create_io_handle(parent, &internal->io_handle);
|
||||
@@ -126,7 +117,7 @@ static error_t start(Device* device) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
if (pulse_reset(internal->reset_descriptor, internal->reset_active_high) != ERROR_NONE) {
|
||||
if (pulse_reset(internal->reset_descriptor) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to pulse reset pin");
|
||||
esp_lcd_panel_io_del(internal->io_handle);
|
||||
if (internal->reset_descriptor != nullptr) {
|
||||
@@ -143,9 +134,10 @@ static error_t start(Device* device) {
|
||||
// why); esp_lcd_touch just skips its own no-op reset step when this is NC.
|
||||
.rst_gpio_num = GPIO_NUM_NC,
|
||||
.int_gpio_num = pin_or_nc(config->pin_interrupt),
|
||||
// FT6x36's reset and interrupt lines are both fixed active-low in hardware.
|
||||
.levels = {
|
||||
.reset = config->reset_active_high ? 1u : 0u,
|
||||
.interrupt = config->interrupt_active_high ? 1u : 0u,
|
||||
.reset = 0u,
|
||||
.interrupt = 0u,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = config->swap_xy ? 1u : 0u,
|
||||
|
||||
@@ -57,10 +57,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -25,7 +25,6 @@ struct Gc9a01Config {
|
||||
uint8_t transaction_queue_depth;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -106,7 +106,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// GC9A01's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -35,11 +35,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -22,8 +22,6 @@ struct Gt911Config {
|
||||
bool mirror_y;
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -84,9 +84,10 @@ static error_t start(Device* device) {
|
||||
.y_max = config->y_max,
|
||||
.rst_gpio_num = pin_or_nc(config->pin_reset),
|
||||
.int_gpio_num = pin_or_nc(config->pin_interrupt),
|
||||
// GT911's reset and interrupt lines are both fixed active-low in hardware.
|
||||
.levels = {
|
||||
.reset = config->reset_active_high ? 1u : 0u,
|
||||
.interrupt = config->interrupt_active_high ? 1u : 0u,
|
||||
.reset = 0u,
|
||||
.interrupt = 0u,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = config->swap_xy ? 1u : 0u,
|
||||
|
||||
@@ -54,10 +54,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -23,7 +23,6 @@ struct Hx8357Config {
|
||||
uint32_t pixel_clock_hz;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -264,9 +264,10 @@ static error_t start(Device* device) {
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
gpio_set_level(static_cast<gpio_num_t>(reset_pin), config->reset_active_high ? 1 : 0);
|
||||
// HX8357's reset line is fixed active-low in hardware.
|
||||
gpio_set_level(static_cast<gpio_num_t>(reset_pin), 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(static_cast<gpio_num_t>(reset_pin), config->reset_active_high ? 0 : 1);
|
||||
gpio_set_level(static_cast<gpio_num_t>(reset_pin), 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
|
||||
|
||||
@@ -71,16 +71,16 @@ static int pin_or_unused(const struct GpioPinSpec& pin) {
|
||||
// start()), which makes it fall back to sending a SWRESET command instead - itself a valid and
|
||||
// commonly-recommended reset path, so this pulse plus that fallback is redundant-safe, not harmful.
|
||||
// Timing (10ms low, 10ms recovery) matches esp_lcd_ili9341's own hardware-reset path exactly.
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor, bool active_high) {
|
||||
static error_t pulse_reset(GpioDescriptor* descriptor) {
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
error_t error = gpio_descriptor_set_level(descriptor, active_high);
|
||||
error_t error = gpio_descriptor_set_level(descriptor, true);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
error = gpio_descriptor_set_level(descriptor, !active_high);
|
||||
error = gpio_descriptor_set_level(descriptor, false);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
@@ -117,20 +117,13 @@ static error_t start(Device* device) {
|
||||
internal->reset_descriptor = nullptr;
|
||||
internal->reset_active_high = config->reset_active_high;
|
||||
if (config->pin_reset.gpio_controller != nullptr) {
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
internal->reset_descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->reset_descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset GPIO descriptor");
|
||||
vSemaphoreDelete(internal->draw_done_semaphore);
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
if (gpio_descriptor_set_flags(internal->reset_descriptor, config->pin_reset.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to configure reset pin as output");
|
||||
gpio_descriptor_release(internal->reset_descriptor);
|
||||
vSemaphoreDelete(internal->draw_done_semaphore);
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
@@ -195,7 +188,7 @@ static error_t start(Device* device) {
|
||||
// Every failure path below must clean up fully: unlike stop_device, this is never retried by the kernel
|
||||
// if start_device fails (see device_start() in TactilityKernel), so a partial failure here would leak.
|
||||
bool ok =
|
||||
pulse_reset(internal->reset_descriptor, internal->reset_active_high) == ERROR_NONE &&
|
||||
pulse_reset(internal->reset_descriptor) == ERROR_NONE &&
|
||||
esp_lcd_panel_reset(internal->panel_handle) == ESP_OK &&
|
||||
esp_lcd_panel_init(internal->panel_handle) == ESP_OK &&
|
||||
(!config->invert_color || esp_lcd_panel_invert_color(internal->panel_handle, true) == ESP_OK);
|
||||
@@ -263,7 +256,7 @@ static error_t stop(Device* device) {
|
||||
|
||||
static error_t ili9341_reset(Device* device) {
|
||||
auto* internal = static_cast<Ili9341Internal*>(device_get_driver_data(device));
|
||||
error_t error = pulse_reset(internal->reset_descriptor, internal->reset_active_high);
|
||||
error_t error = pulse_reset(internal->reset_descriptor);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -29,7 +29,6 @@ struct Ili9488Config {
|
||||
uint8_t transaction_queue_depth;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -111,7 +111,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ILI9488's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -40,10 +40,6 @@ properties:
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin. Falls back to a software reset (sent over the DBI command
|
||||
interface) if not set.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
ldo-channel:
|
||||
type: int
|
||||
required: true
|
||||
|
||||
@@ -23,7 +23,6 @@ struct Ili9881cConfig {
|
||||
// Reset pin for the panel. GPIO_PIN_SPEC_NONE falls back to a software reset sent over the
|
||||
// DBI command interface (see esp_lcd_ili9881c's panel_ili9881c_reset()).
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
|
||||
// LDO channel powering the MIPI DSI PHY - the PHY has no power of its own until this is
|
||||
// acquired, so it must happen before the DSI bus is created. Both fields are int32_t (not
|
||||
|
||||
@@ -226,7 +226,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ILI9881C's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
|
||||
@@ -39,10 +39,6 @@ properties:
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin. Falls back to a software reset (sent over the DBI command
|
||||
interface) if not set.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
ldo-channel:
|
||||
type: int
|
||||
required: true
|
||||
|
||||
@@ -23,7 +23,6 @@ struct Jd9165Config {
|
||||
// Reset pin for the panel. GPIO_PIN_SPEC_NONE falls back to a software reset sent over the
|
||||
// DBI command interface (see esp_lcd_jd9165's panel_jd9165_reset()).
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
|
||||
// LDO channel powering the MIPI DSI PHY - the PHY has no power of its own until this is
|
||||
// acquired, so it must happen before the DSI bus is created. Both fields are int32_t (not
|
||||
|
||||
@@ -225,7 +225,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// JD9165's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
|
||||
@@ -63,10 +63,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -27,7 +27,6 @@ struct Jd9853Config {
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -117,7 +117,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// JD9853's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
|
||||
@@ -57,18 +57,15 @@ static void on_click(void* arg) {
|
||||
// region Pin acquisition
|
||||
|
||||
static error_t acquire_pin(const GpioPinSpec& spec, GpioInterruptType interrupt_type, void (*callback)(void*), void* arg, GpioDescriptor** out_descriptor) {
|
||||
auto* descriptor = gpio_descriptor_acquire(spec.gpio_controller, spec.pin, GPIO_OWNER_GPIO);
|
||||
gpio_flags_t flags = GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
|
||||
flags = GPIO_FLAG_INTERRUPT_TO_OPTIONS(flags, interrupt_type);
|
||||
|
||||
auto* descriptor = gpio_descriptor_acquire(spec.gpio_controller, spec.pin, flags, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
gpio_flags_t flags = GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
|
||||
flags = GPIO_FLAG_INTERRUPT_TO_OPTIONS(flags, interrupt_type);
|
||||
|
||||
error_t error = gpio_descriptor_set_flags(descriptor, flags);
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_add_callback(descriptor, callback, arg);
|
||||
}
|
||||
error_t error = gpio_descriptor_add_callback(descriptor, callback, arg);
|
||||
if (error == ERROR_NONE) {
|
||||
error = gpio_descriptor_enable_interrupt(descriptor);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/gpio_descriptor.h>
|
||||
#include <tactility/log.h>
|
||||
@@ -33,14 +34,7 @@ static error_t read_delta(Device* device, int32_t* out_pulses) {
|
||||
|
||||
static error_t get_button_pressed(Device* device, bool* out_pressed) {
|
||||
auto* internal = GET_INTERNAL(device);
|
||||
bool high = true;
|
||||
error_t error = gpio_descriptor_get_level(internal->pin_enter, &high);
|
||||
if (error != ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
// Active low: pressed when level is low.
|
||||
*out_pressed = !high;
|
||||
return ERROR_NONE;
|
||||
return gpio_descriptor_get_level(internal->pin_enter, out_pressed);
|
||||
}
|
||||
|
||||
error_t tpager_encoder_read_delta(Device* device, int32_t* out_pulses) {
|
||||
@@ -148,7 +142,7 @@ static error_t start(Device* device) {
|
||||
return error;
|
||||
}
|
||||
|
||||
internal->pin_enter = gpio_descriptor_acquire(config->pin_enter.gpio_controller, config->pin_enter.pin, GPIO_OWNER_GPIO);
|
||||
internal->pin_enter = gpio_descriptor_acquire(config->pin_enter.gpio_controller, config->pin_enter.pin, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (internal->pin_enter == nullptr) {
|
||||
pcnt_unit_stop(internal->pcnt_unit);
|
||||
pcnt_del_unit(internal->pcnt_unit);
|
||||
@@ -156,15 +150,6 @@ static error_t start(Device* device) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
error = gpio_descriptor_set_flags(internal->pin_enter, GPIO_FLAG_DIRECTION_INPUT);
|
||||
if (error != ERROR_NONE) {
|
||||
gpio_descriptor_release(internal->pin_enter);
|
||||
pcnt_unit_stop(internal->pcnt_unit);
|
||||
pcnt_del_unit(internal->pcnt_unit);
|
||||
delete internal;
|
||||
return error;
|
||||
}
|
||||
|
||||
device_set_driver_data(device, internal);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// Matrix-scan and keymap logic ported from the M5Stack Cardputer keyboard driver at
|
||||
// https://github.com/m5stack/M5Cardputer-UserDemo/tree/main/main/hal/keyboard (MIT licensed).
|
||||
#include <drivers/cardputer_keyboard.h>
|
||||
|
||||
#include <m5stack_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/keyboard.h>
|
||||
#include <tactility/error.h>
|
||||
@@ -120,11 +122,7 @@ static error_t start(Device* device) {
|
||||
|
||||
for (int i = 0; i < CARDPUTER_OUTPUT_COUNT; i++) {
|
||||
const auto& pin = config->pins_output[i];
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
|
||||
if (descriptor != nullptr && gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_OUTPUT) != ERROR_NONE) {
|
||||
gpio_descriptor_release(descriptor);
|
||||
descriptor = nullptr;
|
||||
}
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, pin.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to configure output pin %d", i);
|
||||
for (int j = 0; j < i; j++) {
|
||||
@@ -141,8 +139,9 @@ static error_t start(Device* device) {
|
||||
const auto& pin = config->pins_input[i];
|
||||
// Rows float high and are pulled low through a pressed key by the active output line,
|
||||
// so an internal pull-up is required regardless of what the devicetree pin flags say.
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr || gpio_descriptor_set_flags(descriptor, pin.flags | GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP) != ERROR_NONE) {
|
||||
auto flags = pin.flags | GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP;
|
||||
auto* descriptor = gpio_descriptor_acquire(pin.gpio_controller, pin.pin, flags, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to configure input pin %d", i);
|
||||
for (int j = 0; j < CARDPUTER_OUTPUT_COUNT; j++) {
|
||||
gpio_descriptor_release(internal->output_descriptors[j]);
|
||||
|
||||
@@ -47,7 +47,10 @@ static error_t set_level(GpioDescriptor* descriptor, bool high) {
|
||||
auto address = GET_CONFIG(device)->address;
|
||||
uint8_t bit = 1 << descriptor->pin;
|
||||
|
||||
if (high) {
|
||||
// This chip has no output polarity register: active-low must be inverted in software.
|
||||
bool physical_high = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !high : high;
|
||||
|
||||
if (physical_high) {
|
||||
return i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_OUTPUT_LEVEL, bit, portMAX_DELAY);
|
||||
} else {
|
||||
return i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_OUTPUT_LEVEL, bit, portMAX_DELAY);
|
||||
@@ -65,7 +68,8 @@ static error_t get_level(GpioDescriptor* descriptor, bool* high) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*high = (bits & (1 << descriptor->pin)) != 0;
|
||||
bool physical_high = (bits & (1 << descriptor->pin)) != 0;
|
||||
*high = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !physical_high : physical_high;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -161,6 +165,8 @@ static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
||||
f |= GPIO_FLAG_HIGH_IMPEDANCE;
|
||||
}
|
||||
|
||||
f |= (descriptor->flags & GPIO_FLAG_ACTIVE_LOW);
|
||||
|
||||
*flags = f;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/display.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/gpio_descriptor.h>
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
@@ -70,17 +70,16 @@ static error_t perform_hardware_reset(const RgbDisplayConfig* config) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
auto* descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
auto* descriptor = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
if (descriptor == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire reset GPIO descriptor");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
bool ok = gpio_descriptor_set_flags(descriptor, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE;
|
||||
ok = ok && gpio_descriptor_set_level(descriptor, config->reset_active_high) == ERROR_NONE;
|
||||
bool ok = gpio_descriptor_set_level(descriptor, true) == ERROR_NONE;
|
||||
if (ok) {
|
||||
delay_millis(100);
|
||||
ok = gpio_descriptor_set_level(descriptor, !config->reset_active_high) == ERROR_NONE;
|
||||
ok = gpio_descriptor_set_level(descriptor, false) == ERROR_NONE;
|
||||
delay_millis(10);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
power-on-delay-ms:
|
||||
type: int
|
||||
default: 0
|
||||
|
||||
@@ -22,7 +22,6 @@ struct Ssd1306Config {
|
||||
|
||||
// Reset pin. GPIO_PIN_SPEC_NONE skips the reset toggle entirely.
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
|
||||
// See the 'power-on-delay-ms' binding property.
|
||||
uint32_t power_on_delay_ms;
|
||||
|
||||
@@ -119,9 +119,10 @@ static void perform_hardware_reset(const Ssd1306Config* config) {
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
|
||||
gpio_set_level(pin, config->reset_active_high ? 1 : 0);
|
||||
// SSD1306's reset line is fixed active-low in hardware.
|
||||
gpio_set_level(pin, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(pin, config->reset_active_high ? 0 : 1);
|
||||
gpio_set_level(pin, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Interrupt GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
interrupt-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the interrupt pin is active high
|
||||
|
||||
@@ -40,10 +40,6 @@ properties:
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin. Falls back to a software reset (sent over the DBI command
|
||||
interface) if not set.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
ldo-channel:
|
||||
type: int
|
||||
required: true
|
||||
|
||||
@@ -23,7 +23,6 @@ struct St7123Config {
|
||||
// Reset pin for the panel. GPIO_PIN_SPEC_NONE falls back to a software reset sent over the
|
||||
// DBI command interface (see esp_lcd_st7123's panel_st7123_reset()).
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
|
||||
// LDO channel powering the MIPI DSI PHY - the PHY has no power of its own until this is
|
||||
// acquired, so it must happen before the DSI bus is created. Both fields are int32_t (not
|
||||
|
||||
@@ -25,8 +25,6 @@ struct St7123TouchConfig {
|
||||
// for parity with the other touch drivers (e.g. gt911-module) in case a board wires it directly.
|
||||
struct GpioPinSpec pin_reset;
|
||||
struct GpioPinSpec pin_interrupt;
|
||||
bool reset_active_high;
|
||||
bool interrupt_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -225,7 +225,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7123's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
|
||||
@@ -75,9 +75,10 @@ static error_t start(Device* device) {
|
||||
.y_max = config->y_max,
|
||||
.rst_gpio_num = pin_or_nc(config->pin_reset),
|
||||
.int_gpio_num = pin_or_nc(config->pin_interrupt),
|
||||
// ST7123's reset and interrupt lines are both fixed active-low in hardware.
|
||||
.levels = {
|
||||
.reset = config->reset_active_high ? 1u : 0u,
|
||||
.interrupt = config->interrupt_active_high ? 1u : 0u,
|
||||
.reset = 0u,
|
||||
.interrupt = 0u,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = config->swap_xy ? 1u : 0u,
|
||||
|
||||
@@ -233,10 +233,6 @@ properties:
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Optional hardware reset pin for the panel. Falls back to a software reset
|
||||
(sent over the 3-wire bus) if not set.
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
mirror-by-cmd:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -88,7 +88,6 @@ struct St7701Config {
|
||||
// Optional hardware reset pin for the panel. GPIO_PIN_SPEC_NONE falls back to a software
|
||||
// reset sent over the 3-wire bus (see esp_lcd_st7701's panel_st7701_reset()).
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
|
||||
// See the 'mirror-by-cmd' and 'auto-del-panel-io' binding properties.
|
||||
bool mirror_by_cmd;
|
||||
|
||||
@@ -238,7 +238,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7701's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
|
||||
@@ -67,10 +67,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -28,7 +28,6 @@ struct St7735Config {
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -117,7 +117,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7735's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -59,10 +59,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -26,7 +26,6 @@ struct St7789I8080Config {
|
||||
// Gamma curve preset index [0,3], sent via the MIPI DCS GAMSET (0x26) command at bring-up.
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -148,7 +148,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7789's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -67,10 +67,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -28,7 +28,6 @@ struct St7789Config {
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -117,7 +117,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7789's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -59,10 +59,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -26,7 +26,6 @@ struct St7796I8080Config {
|
||||
// Gamma curve preset index [0,3], sent via the MIPI DCS GAMSET (0x26) command at bring-up.
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -116,7 +116,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7796's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -67,10 +67,6 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Reset GPIO pin
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
backlight:
|
||||
type: phandle
|
||||
default: "NULL"
|
||||
|
||||
@@ -28,7 +28,6 @@ struct St7796Config {
|
||||
uint8_t gamma_curve;
|
||||
struct GpioPinSpec pin_dc;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
// Optional reference to this display's backlight device, NULL if none.
|
||||
struct Device* backlight;
|
||||
};
|
||||
|
||||
@@ -117,7 +117,8 @@ static error_t start(Device* device) {
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// ST7796's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,3 @@ properties:
|
||||
type: phandles
|
||||
default: GPIO_PIN_SPEC_NONE
|
||||
description: Optional reset GPIO pin, pulsed once at start (20 ms assert, 60 ms settle)
|
||||
reset-active-high:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the reset pin is active high
|
||||
|
||||
@@ -27,7 +27,6 @@ struct Tca8418Config {
|
||||
uint8_t sym_row;
|
||||
uint8_t sym_col;
|
||||
struct GpioPinSpec pin_reset;
|
||||
bool reset_active_high;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/tca8418.h>
|
||||
|
||||
#include <tca8418_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/delay.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/keyboard.h>
|
||||
@@ -116,15 +118,18 @@ static void perform_hardware_reset(const Tca8418Config* config) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_OWNER_GPIO);
|
||||
// Not requesting GPIO_FLAG_ACTIVE_LOW here: some GPIO expanders (e.g. xl9555/tca95xx/
|
||||
// tca9534) can only invert what's read back from an input, not what's driven on an
|
||||
// output, so they reject ACTIVE_LOW combined with OUTPUT. Drive the raw physical level
|
||||
// instead: this pin's reset line is active-low, so low asserts and high releases.
|
||||
auto* rst = gpio_descriptor_acquire(config->pin_reset.gpio_controller, config->pin_reset.pin, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
if (rst == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_descriptor_set_flags(rst, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_level(rst, config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, false);
|
||||
delay_millis(20);
|
||||
gpio_descriptor_set_level(rst, !config->reset_active_high);
|
||||
gpio_descriptor_set_level(rst, true);
|
||||
gpio_descriptor_release(rst);
|
||||
delay_millis(60);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <drivers/xpt2046_softspi.h>
|
||||
|
||||
#include <xpt2046_softspi_module.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
#include <tactility/drivers/power_supply.h>
|
||||
@@ -15,7 +17,7 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
#define TAG "XPT2046SoftSPI"
|
||||
constexpr auto* TAG = "XPT2046SoftSPI";
|
||||
#define GET_CONFIG(device) (static_cast<const Xpt2046SoftSpiConfig*>((device)->config))
|
||||
|
||||
// Rough LiPo discharge curve floor, used together with the configured reference voltage
|
||||
@@ -73,10 +75,10 @@ static error_t start(Device* device) {
|
||||
}
|
||||
*internal = {};
|
||||
|
||||
internal->mosi = gpio_descriptor_acquire(config->pin_mosi.gpio_controller, config->pin_mosi.pin, GPIO_OWNER_GPIO);
|
||||
internal->miso = gpio_descriptor_acquire(config->pin_miso.gpio_controller, config->pin_miso.pin, GPIO_OWNER_GPIO);
|
||||
internal->sck = gpio_descriptor_acquire(config->pin_sck.gpio_controller, config->pin_sck.pin, GPIO_OWNER_GPIO);
|
||||
internal->cs = gpio_descriptor_acquire(config->pin_cs.gpio_controller, config->pin_cs.pin, GPIO_OWNER_GPIO);
|
||||
internal->mosi = gpio_descriptor_acquire(config->pin_mosi.gpio_controller, config->pin_mosi.pin, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
internal->miso = gpio_descriptor_acquire(config->pin_miso.gpio_controller, config->pin_miso.pin, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP, GPIO_OWNER_GPIO);
|
||||
internal->sck = gpio_descriptor_acquire(config->pin_sck.gpio_controller, config->pin_sck.pin, GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
|
||||
internal->cs = gpio_descriptor_acquire(config->pin_cs.gpio_controller, config->pin_cs.pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
|
||||
|
||||
if (internal->mosi == nullptr || internal->miso == nullptr || internal->sck == nullptr || internal->cs == nullptr) {
|
||||
LOG_E(TAG, "Failed to acquire GPIO descriptors");
|
||||
@@ -85,15 +87,8 @@ static error_t start(Device* device) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
bool ok =
|
||||
gpio_descriptor_set_flags(internal->mosi, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE &&
|
||||
gpio_descriptor_set_flags(internal->sck, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE &&
|
||||
gpio_descriptor_set_flags(internal->cs, GPIO_FLAG_DIRECTION_OUTPUT) == ERROR_NONE &&
|
||||
gpio_descriptor_set_flags(internal->miso, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP) == ERROR_NONE;
|
||||
|
||||
// Idle state: CS high (deselected), SCK/MOSI low.
|
||||
ok = ok &&
|
||||
gpio_descriptor_set_level(internal->cs, true) == ERROR_NONE &&
|
||||
bool ok = gpio_descriptor_set_level(internal->cs, false) == ERROR_NONE &&
|
||||
gpio_descriptor_set_level(internal->sck, false) == ERROR_NONE &&
|
||||
gpio_descriptor_set_level(internal->mosi, false) == ERROR_NONE;
|
||||
|
||||
@@ -146,7 +141,7 @@ static error_t stop(Device* device) {
|
||||
static int read_spi_command(Xpt2046SoftSpiInternal* internal, uint8_t command) {
|
||||
int result = 0;
|
||||
|
||||
gpio_descriptor_set_level(internal->cs, false);
|
||||
gpio_descriptor_set_level(internal->cs, true);
|
||||
delay_micros(1);
|
||||
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
@@ -169,7 +164,7 @@ static int read_spi_command(Xpt2046SoftSpiInternal* internal, uint8_t command) {
|
||||
delay_micros(1);
|
||||
}
|
||||
|
||||
gpio_descriptor_set_level(internal->cs, true);
|
||||
gpio_descriptor_set_level(internal->cs, false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ void release_pin(GpioDescriptor** gpio_descriptor);
|
||||
* If the pin spec is invalid, the pointer is set to null.
|
||||
* @return true if the pin was acquired successfully
|
||||
*/
|
||||
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, GpioDescriptor** gpio_descriptor);
|
||||
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor);
|
||||
|
||||
/**
|
||||
* Safely acquire the native pin value.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user