New kernel drivers and more (#560)
- Added kernel base drivers for: display, pointer (touch, mouse, etc.), keyboard, adc, power supply and backlight - Implement new kernel driver modules: `st7789-module` and `gt911-module` - Implement ESP32 ADC "oneshot" kernel driver - Implement ESP32 backlight kernel driver with ledc API - Implemented `battery-sense` driver that allows for voltage measurement and creates a power supply child device - Updated github actions - Updated flash scripts - Fix for esp32 legacy driver conflict with ADC - Created separate `lilygo-tdeck` and `lilygo-tdeck-plus` devices - Created `lilygo-module` with LilyGO kernel drivers - Fix for intermittent errors in build related to code generation of `devicetree.c` - `lvgl-module` can now map kernel drivers onto LVGL devices - Created `KernelDisplayApp` as a mirror of `HalDisplayApp` (formerly `DisplayApp`) - Removed `struct` and `enum` prefix in a lot of kernel driver cpp source files - `lilygo-tdeck` and `lilygo-tdeck-plus` are now fully relying on kernel drivers and don't use any of the old HAL
This commit is contained in:
committed by
GitHub
parent
c4406b24ba
commit
50c0a14a93
@@ -6,7 +6,7 @@ idf_component_register(
|
||||
SRCS ${SOURCES}
|
||||
INCLUDE_DIRS "include/"
|
||||
PRIV_INCLUDE_DIRS "private/"
|
||||
REQUIRES TactilityKernel driver esp_driver_i2c vfs fatfs esp_wifi esp_netif esp_event
|
||||
REQUIRES TactilityKernel driver esp_adc esp_driver_i2c vfs fatfs esp_wifi esp_netif esp_event
|
||||
)
|
||||
|
||||
idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
description: ESP32 ADC Controller (oneshot mode)
|
||||
|
||||
include: ["adc-controller.yaml"]
|
||||
|
||||
compatible: "espressif,esp32-adc-oneshot"
|
||||
|
||||
properties:
|
||||
unit-id:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
The ADC unit, defined by adc_unit_t (e.g. ADC_UNIT_1, ADC_UNIT_2).
|
||||
clk-src:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Clock source, defined by adc_oneshot_clk_src_t. 0 selects the default clock source.
|
||||
ulp-mode:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
ULP control mode, defined by adc_ulp_mode_t. 0 means ADC_ULP_MODE_DISABLE.
|
||||
channels:
|
||||
type: phandle-array
|
||||
element-type: "struct Esp32AdcOneshotChannelConfig"
|
||||
default: "{ }"
|
||||
description: |
|
||||
Per-channel configuration. Each entry is written as <channel atten bitwidth>,
|
||||
e.g. <ADC_CHANNEL_3 ADC_ATTEN_DB_12 ADC_BITWIDTH_DEFAULT>.
|
||||
A consumer device refers to a channel with a phandle and channel number, e.g. `<&adc0 3>`.
|
||||
@@ -0,0 +1,29 @@
|
||||
description: ESP32 LEDC-backed PWM backlight
|
||||
|
||||
compatible: "espressif,esp32-ledc-backlight"
|
||||
|
||||
properties:
|
||||
pin-backlight:
|
||||
type: phandles
|
||||
required: true
|
||||
description: Backlight PWM output pin
|
||||
frequency-hz:
|
||||
type: int
|
||||
default: 30000
|
||||
description: PWM frequency in Hz
|
||||
brightness-level-range:
|
||||
type: values
|
||||
default: [0, 255]
|
||||
description: Inclusive [min,max] brightness range. The minimum value turns the backlight off.
|
||||
brightness-default:
|
||||
type: int
|
||||
default: 200
|
||||
description: Default brightness level, applied by set_brightness_default(). Should fall within brightness-level-range.
|
||||
ledc-timer:
|
||||
type: int
|
||||
default: 0
|
||||
description: LEDC timer index, defined by ledc_timer_t
|
||||
ledc-channel:
|
||||
type: int
|
||||
default: 0
|
||||
description: LEDC channel index, defined by ledc_channel_t
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <tactility/bindings/bindings.h>
|
||||
#include <tactility/drivers/esp32_adc_oneshot.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICETREE(esp32_adc_oneshot, struct Esp32AdcOneshotConfig)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <tactility/bindings/bindings.h>
|
||||
#include <tactility/drivers/esp32_ledc_backlight.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DEFINE_DEVICETREE(esp32_ledc_backlight, struct Esp32LedcBacklightConfig)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <tactility/device.h>
|
||||
|
||||
#include <esp_adc/adc_oneshot.h>
|
||||
#include <hal/adc_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Esp32AdcOneshotChannelConfig {
|
||||
adc_channel_t channel;
|
||||
adc_atten_t atten;
|
||||
adc_bitwidth_t bitwidth;
|
||||
};
|
||||
|
||||
struct Esp32AdcOneshotConfig {
|
||||
adc_unit_t unit_id;
|
||||
adc_oneshot_clk_src_t clk_src;
|
||||
adc_ulp_mode_t ulp_mode;
|
||||
/** Per-channel configuration */
|
||||
const struct Esp32AdcOneshotChannelConfig* channels;
|
||||
/** The item count of channels */
|
||||
size_t channel_count;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <driver/ledc.h>
|
||||
#include <tactility/drivers/backlight.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Esp32LedcBacklightConfig {
|
||||
struct GpioPinSpec pin_backlight;
|
||||
uint32_t frequency_hz;
|
||||
struct BrightnessLevelRange brightness_range;
|
||||
uint8_t brightness_default;
|
||||
ledc_timer_t ledc_timer;
|
||||
ledc_channel_t ledc_channel;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <esp_adc/adc_oneshot.h>
|
||||
|
||||
#include <tactility/error_esp32.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/adc_controller.h>
|
||||
#include <tactility/drivers/esp32_adc_oneshot.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/time.h>
|
||||
|
||||
#define TAG "esp32_adc_oneshot"
|
||||
|
||||
#define GET_CONFIG(device) ((Esp32AdcOneshotConfig*)device->config)
|
||||
#define GET_HANDLE(device) ((adc_oneshot_unit_handle_t)device_get_driver_data(device))
|
||||
|
||||
static const Esp32AdcOneshotChannelConfig* find_channel_config(const Esp32AdcOneshotConfig* dts_config, uint8_t channel_index) {
|
||||
if (channel_index >= dts_config->channel_count) {
|
||||
return nullptr;
|
||||
}
|
||||
return &dts_config->channels[channel_index];
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
static error_t read_raw(Device* device, uint8_t channel, int* out_raw, TickType_t timeout) {
|
||||
if (xPortInIsrContext()) return ERROR_ISR_STATUS;
|
||||
auto* dts_config = GET_CONFIG(device);
|
||||
auto* channel_config = find_channel_config(dts_config, channel);
|
||||
if (channel_config == nullptr) {
|
||||
return ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
esp_err_t esp_error = adc_oneshot_read(GET_HANDLE(device), channel_config->channel, out_raw);
|
||||
if (esp_error != ESP_OK) {
|
||||
LOG_E(TAG, "read(channel=%u) failed: %s", channel, esp_err_to_name(esp_error));
|
||||
}
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static error_t start(Device* device) {
|
||||
LOG_I(TAG, "start %s", device->name);
|
||||
auto* dts_config = GET_CONFIG(device);
|
||||
|
||||
adc_oneshot_unit_init_cfg_t init_config = {
|
||||
.unit_id = dts_config->unit_id,
|
||||
.clk_src = dts_config->clk_src,
|
||||
.ulp_mode = dts_config->ulp_mode,
|
||||
};
|
||||
|
||||
adc_oneshot_unit_handle_t handle;
|
||||
esp_err_t esp_error = adc_oneshot_new_unit(&init_config, &handle);
|
||||
if (esp_error != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to create ADC unit %d: %s", (int)dts_config->unit_id, esp_err_to_name(esp_error));
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < dts_config->channel_count; i++) {
|
||||
const auto& channel_config = dts_config->channels[i];
|
||||
adc_oneshot_chan_cfg_t chan_cfg = {
|
||||
.atten = channel_config.atten,
|
||||
.bitwidth = channel_config.bitwidth,
|
||||
};
|
||||
esp_error = adc_oneshot_config_channel(handle, channel_config.channel, &chan_cfg);
|
||||
if (esp_error != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to configure channel %d: %s", (int)channel_config.channel, esp_err_to_name(esp_error));
|
||||
adc_oneshot_del_unit(handle);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
device_set_driver_data(device, handle);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop(Device* device) {
|
||||
LOG_I(TAG, "stop %s", device->name);
|
||||
esp_err_t esp_error = adc_oneshot_del_unit(GET_HANDLE(device));
|
||||
if (esp_error != ESP_OK) {
|
||||
LOG_E(TAG, "Deleting ADC unit failed: %s", esp_err_to_name(esp_error));
|
||||
}
|
||||
device_set_driver_data(device, nullptr);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static constexpr AdcControllerApi ESP32_ADC_ONESHOT_API = {
|
||||
.read_raw = read_raw
|
||||
};
|
||||
|
||||
extern Module platform_esp32_module;
|
||||
|
||||
Driver esp32_adc_oneshot_driver = {
|
||||
.name = "esp32_adc_oneshot",
|
||||
.compatible = (const char*[]) { "espressif,esp32-adc-oneshot", nullptr },
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = &ESP32_ADC_ONESHOT_API,
|
||||
.device_type = &ADC_CONTROLLER_TYPE,
|
||||
.owner = &platform_esp32_module,
|
||||
.internal = nullptr
|
||||
};
|
||||
|
||||
} // extern "C"
|
||||
@@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/drivers/esp32_ledc_backlight.h>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/backlight.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <driver/ledc.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#define TAG "Esp32LedcBacklight"
|
||||
#define GET_CONFIG(device) (static_cast<const Esp32LedcBacklightConfig*>((device)->config))
|
||||
|
||||
struct Esp32LedcBacklightInternal {
|
||||
uint8_t brightness;
|
||||
};
|
||||
|
||||
// region Driver lifecycle
|
||||
|
||||
static error_t start(Device* device) {
|
||||
const auto* config = GET_CONFIG(device);
|
||||
|
||||
ledc_timer_config_t timer_config = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.duty_resolution = LEDC_TIMER_8_BIT,
|
||||
.timer_num = config->ledc_timer,
|
||||
.freq_hz = config->frequency_hz,
|
||||
.clk_cfg = LEDC_AUTO_CLK,
|
||||
.deconfigure = false,
|
||||
};
|
||||
if (ledc_timer_config(&timer_config) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to configure LEDC timer");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
ledc_channel_config_t channel_config = {
|
||||
.gpio_num = (int)config->pin_backlight.pin,
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = config->ledc_channel,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.timer_sel = config->ledc_timer,
|
||||
.duty = config->brightness_range.min,
|
||||
.hpoint = 0,
|
||||
.sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD,
|
||||
.flags = {
|
||||
.output_invert = 0,
|
||||
},
|
||||
};
|
||||
if (ledc_channel_config(&channel_config) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to configure LEDC channel");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
auto* internal = static_cast<Esp32LedcBacklightInternal*>(malloc(sizeof(Esp32LedcBacklightInternal)));
|
||||
if (internal == nullptr) {
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
internal->brightness = config->brightness_range.min;
|
||||
|
||||
device_set_driver_data(device, internal);
|
||||
|
||||
backlight_set_brightness_default(device); // Allowed to fail, we don't care about the result
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop(Device* device) {
|
||||
backlight_set_brightness(device, 0); // Allowed to fail, we don't care about the result
|
||||
|
||||
auto* internal = static_cast<Esp32LedcBacklightInternal*>(device_get_driver_data(device));
|
||||
free(internal);
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region BacklightApi
|
||||
|
||||
static error_t esp32_ledc_backlight_set_brightness(Device* device, uint8_t brightness) {
|
||||
const auto* config = GET_CONFIG(device);
|
||||
auto* internal = static_cast<Esp32LedcBacklightInternal*>(device_get_driver_data(device));
|
||||
|
||||
esp_err_t ret = ledc_set_duty(LEDC_LOW_SPEED_MODE, config->ledc_channel, brightness);
|
||||
if (ret == ESP_OK) {
|
||||
ret = ledc_update_duty(LEDC_LOW_SPEED_MODE, config->ledc_channel);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to set brightness: %s", esp_err_to_name(ret));
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
internal->brightness = brightness;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t esp32_ledc_backlight_set_brightness_default(Device* device) {
|
||||
return esp32_ledc_backlight_set_brightness(device, GET_CONFIG(device)->brightness_default);
|
||||
}
|
||||
|
||||
static error_t esp32_ledc_backlight_get_brightness(Device* device, uint8_t* out_brightness) {
|
||||
auto* internal = static_cast<Esp32LedcBacklightInternal*>(device_get_driver_data(device));
|
||||
*out_brightness = internal->brightness;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static uint8_t esp32_ledc_backlight_get_min_brightness(Device* device) {
|
||||
return GET_CONFIG(device)->brightness_range.min;
|
||||
}
|
||||
|
||||
static uint8_t esp32_ledc_backlight_get_max_brightness(Device* device) {
|
||||
return GET_CONFIG(device)->brightness_range.max;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
static const BacklightApi esp32_ledc_backlight_api = {
|
||||
.set_brightness = esp32_ledc_backlight_set_brightness,
|
||||
.set_brightness_default = esp32_ledc_backlight_set_brightness_default,
|
||||
.get_brightness = esp32_ledc_backlight_get_brightness,
|
||||
.get_min_brightness = esp32_ledc_backlight_get_min_brightness,
|
||||
.get_max_brightness = esp32_ledc_backlight_get_max_brightness,
|
||||
};
|
||||
|
||||
extern Module platform_esp32_module;
|
||||
|
||||
Driver esp32_ledc_backlight_driver = {
|
||||
.name = "esp32_ledc_backlight",
|
||||
.compatible = (const char*[]) { "espressif,esp32-ledc-backlight", nullptr },
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = &esp32_ledc_backlight_api,
|
||||
.device_type = &BACKLIGHT_TYPE,
|
||||
.owner = &platform_esp32_module,
|
||||
.internal = nullptr
|
||||
};
|
||||
@@ -11,10 +11,12 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern Driver esp32_adc_oneshot_driver;
|
||||
extern Driver esp32_gpio_driver;
|
||||
extern Driver esp32_i2c_driver;
|
||||
extern Driver esp32_i2c_master_driver;
|
||||
extern Driver esp32_i2s_driver;
|
||||
extern Driver esp32_ledc_backlight_driver;
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
extern Driver esp32_sdmmc_driver;
|
||||
#endif
|
||||
@@ -42,10 +44,12 @@ extern Driver esp32_usbhost_msc_driver;
|
||||
static error_t start() {
|
||||
/* We crash when construct fails, because if a single driver fails to construct,
|
||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||
check(driver_construct_add(&esp32_adc_oneshot_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_i2c_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_i2c_master_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_i2s_driver) == ERROR_NONE);
|
||||
check(driver_construct_add(&esp32_ledc_backlight_driver) == ERROR_NONE);
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
check(driver_construct_add(&esp32_sdmmc_driver) == ERROR_NONE);
|
||||
#endif
|
||||
@@ -91,10 +95,12 @@ static error_t stop() {
|
||||
check(driver_remove_destruct(&esp32_ble_serial_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_bluetooth_driver) == ERROR_NONE);
|
||||
#endif
|
||||
check(driver_remove_destruct(&esp32_adc_oneshot_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_gpio_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_i2c_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_i2c_master_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_i2s_driver) == ERROR_NONE);
|
||||
check(driver_remove_destruct(&esp32_ledc_backlight_driver) == ERROR_NONE);
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
check(driver_remove_destruct(&esp32_sdmmc_driver) == ERROR_NONE);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user