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
@@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <Tactility/hal/display/KernelDisplayDriver.h>
|
||||
|
||||
#include <tactility/drivers/display.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace tt::hal::display {
|
||||
|
||||
static ColorFormat toColorFormat(DisplayColorFormat format) {
|
||||
switch (format) {
|
||||
case DISPLAY_COLOR_FORMAT_MONOCHROME:
|
||||
return ColorFormat::Monochrome;
|
||||
case DISPLAY_COLOR_FORMAT_BGR565:
|
||||
return ColorFormat::BGR565;
|
||||
case DISPLAY_COLOR_FORMAT_BGR565_SWAPPED:
|
||||
return ColorFormat::BGR565Swapped;
|
||||
case DISPLAY_COLOR_FORMAT_RGB565:
|
||||
return ColorFormat::RGB565;
|
||||
case DISPLAY_COLOR_FORMAT_RGB565_SWAPPED:
|
||||
return ColorFormat::RGB565Swapped;
|
||||
case DISPLAY_COLOR_FORMAT_RGB888:
|
||||
return ColorFormat::RGB888;
|
||||
default:
|
||||
std::unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
KernelDisplayDriver::KernelDisplayDriver(::Device* device) : device(device) {
|
||||
assert(device_get_type(device) == &DISPLAY_TYPE);
|
||||
}
|
||||
|
||||
ColorFormat KernelDisplayDriver::getColorFormat() const {
|
||||
return toColorFormat(display_get_color_format(device));
|
||||
}
|
||||
|
||||
uint16_t KernelDisplayDriver::getPixelWidth() const {
|
||||
return display_get_resolution_x(device);
|
||||
}
|
||||
|
||||
uint16_t KernelDisplayDriver::getPixelHeight() const {
|
||||
return display_get_resolution_y(device);
|
||||
}
|
||||
|
||||
bool KernelDisplayDriver::drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) {
|
||||
return display_draw_bitmap(device, xStart, yStart, xEnd, yEnd, pixelData) == ERROR_NONE;
|
||||
}
|
||||
|
||||
uint8_t KernelDisplayDriver::getFrameBuffers(void* outBuffers[2]) const {
|
||||
uint8_t count = std::min<uint8_t>(display_get_frame_buffer_count(device), 2);
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
display_get_frame_buffer(device, i, &outBuffers[i]);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/power_supply.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace tt::hal::power {
|
||||
|
||||
#define GET_POWER_DEVICE(device) (static_cast<PowerDevice*>(device_get_driver_data(device)))
|
||||
|
||||
static PowerDevice::MetricType toMetricType(PowerSupplyProperty property) {
|
||||
switch (property) {
|
||||
case POWER_SUPPLY_PROP_IS_CHARGING:
|
||||
return PowerDevice::MetricType::IsCharging;
|
||||
case POWER_SUPPLY_PROP_CURRENT:
|
||||
return PowerDevice::MetricType::Current;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE:
|
||||
return PowerDevice::MetricType::BatteryVoltage;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
default:
|
||||
return PowerDevice::MetricType::ChargeLevel;
|
||||
}
|
||||
}
|
||||
|
||||
static int toIntValue(PowerDevice::MetricType type, const PowerDevice::MetricData& data) {
|
||||
switch (type) {
|
||||
case PowerDevice::MetricType::IsCharging:
|
||||
return data.valueAsBool ? 1 : 0;
|
||||
case PowerDevice::MetricType::Current:
|
||||
return data.valueAsInt32;
|
||||
case PowerDevice::MetricType::BatteryVoltage:
|
||||
return static_cast<int>(data.valueAsUint32);
|
||||
case PowerDevice::MetricType::ChargeLevel:
|
||||
default:
|
||||
return data.valueAsUint8;
|
||||
}
|
||||
}
|
||||
|
||||
static bool apiSupportsProperty(::Device* device, PowerSupplyProperty property) {
|
||||
return GET_POWER_DEVICE(device)->supportsMetric(toMetricType(property));
|
||||
}
|
||||
|
||||
static error_t apiGetProperty(::Device* device, PowerSupplyProperty property, PowerSupplyPropertyValue* outValue) {
|
||||
auto* power_device = GET_POWER_DEVICE(device);
|
||||
auto metric_type = toMetricType(property);
|
||||
if (!power_device->supportsMetric(metric_type)) {
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
PowerDevice::MetricData data;
|
||||
if (!power_device->getMetric(metric_type, data)) {
|
||||
return ERROR_NOT_FOUND;
|
||||
}
|
||||
outValue->int_value = toIntValue(metric_type, data);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool apiSupportsChargeControl(::Device* device) {
|
||||
return GET_POWER_DEVICE(device)->supportsChargeControl();
|
||||
}
|
||||
|
||||
static bool apiIsAllowedToCharge(::Device* device) {
|
||||
return GET_POWER_DEVICE(device)->isAllowedToCharge();
|
||||
}
|
||||
|
||||
static error_t apiSetAllowedToCharge(::Device* device, bool allowed) {
|
||||
auto* power_device = GET_POWER_DEVICE(device);
|
||||
if (!power_device->supportsChargeControl()) {
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
power_device->setAllowedToCharge(allowed);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool apiSupportsQuickCharge(::Device* device) {
|
||||
return GET_POWER_DEVICE(device)->supportsQuickCharge();
|
||||
}
|
||||
|
||||
static bool apiIsQuickChargeEnabled(::Device* device) {
|
||||
return GET_POWER_DEVICE(device)->isQuickChargeEnabled();
|
||||
}
|
||||
|
||||
static error_t apiSetQuickChargeEnabled(::Device* device, bool enabled) {
|
||||
auto* power_device = GET_POWER_DEVICE(device);
|
||||
if (!power_device->supportsQuickCharge()) {
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
power_device->setQuickChargeEnabled(enabled);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool apiSupportsPowerOff(::Device* device) {
|
||||
return GET_POWER_DEVICE(device)->supportsPowerOff();
|
||||
}
|
||||
|
||||
static error_t apiPowerOff(::Device* device) {
|
||||
auto* power_device = GET_POWER_DEVICE(device);
|
||||
if (!power_device->supportsPowerOff()) {
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
power_device->powerOff();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t startDevice(::Device*) { return ERROR_NONE; }
|
||||
static error_t stopDevice(::Device*) { return ERROR_NONE; }
|
||||
|
||||
static PowerSupplyApi powerSupplyApi {
|
||||
.supports_property = apiSupportsProperty,
|
||||
.get_property = apiGetProperty,
|
||||
.supports_charge_control = apiSupportsChargeControl,
|
||||
.is_allowed_to_charge = apiIsAllowedToCharge,
|
||||
.set_allowed_to_charge = apiSetAllowedToCharge,
|
||||
.supports_quick_charge = apiSupportsQuickCharge,
|
||||
.is_quick_charge_enabled = apiIsQuickChargeEnabled,
|
||||
.set_quick_charge_enabled = apiSetQuickChargeEnabled,
|
||||
.supports_power_off = apiSupportsPowerOff,
|
||||
.power_off = apiPowerOff,
|
||||
};
|
||||
|
||||
static const char* powerSupplyCompatible[] = { "hal-power-device", nullptr };
|
||||
|
||||
static Driver powerSupplyDriver {
|
||||
.name = "hal-power-device",
|
||||
.compatible = powerSupplyCompatible,
|
||||
.start_device = startDevice,
|
||||
.stop_device = stopDevice,
|
||||
.api = &powerSupplyApi,
|
||||
.device_type = &POWER_SUPPLY_TYPE,
|
||||
.owner = nullptr,
|
||||
.internal = nullptr,
|
||||
};
|
||||
|
||||
/** Registers the "hal-power-device" driver with the kernel on first use. */
|
||||
static Driver& getPowerSupplyDriver() {
|
||||
static const bool registered = [] {
|
||||
check(driver_construct_add(&powerSupplyDriver) == ERROR_NONE);
|
||||
return true;
|
||||
}();
|
||||
(void)registered;
|
||||
return powerSupplyDriver;
|
||||
}
|
||||
|
||||
void PowerDevice::createPowerSupplyDevice() {
|
||||
kernelDeviceName = std::format("power-supply-{}", getId());
|
||||
kernelDevice.name = kernelDeviceName.c_str();
|
||||
check(device_construct(&kernelDevice) == ERROR_NONE);
|
||||
check(device_add(&kernelDevice) == ERROR_NONE);
|
||||
device_set_driver(&kernelDevice, &getPowerSupplyDriver());
|
||||
check(device_start(&kernelDevice) == ERROR_NONE);
|
||||
device_set_driver_data(&kernelDevice, this);
|
||||
}
|
||||
|
||||
void PowerDevice::destroyPowerSupplyDevice() {
|
||||
device_set_driver_data(&kernelDevice, nullptr);
|
||||
check(device_stop(&kernelDevice) == ERROR_NONE);
|
||||
check(device_remove(&kernelDevice) == ERROR_NONE);
|
||||
check(device_destruct(&kernelDevice) == ERROR_NONE);
|
||||
}
|
||||
|
||||
PowerDevice::PowerDevice() {
|
||||
createPowerSupplyDevice();
|
||||
}
|
||||
|
||||
PowerDevice::~PowerDevice() {
|
||||
destroyPowerSupplyDevice();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <Tactility/hal/touch/KernelTouchDriver.h>
|
||||
|
||||
#include <tactility/drivers/pointer.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace tt::hal::touch {
|
||||
|
||||
// Bus reads are expected to complete quickly; bound the wait so a stalled controller can't block the LVGL indev poll.
|
||||
static constexpr TickType_t READ_TIMEOUT = pdMS_TO_TICKS(10);
|
||||
|
||||
KernelTouchDriver::KernelTouchDriver(::Device* device) : device(device) {
|
||||
assert(device_get_type(device) == &POINTER_TYPE);
|
||||
}
|
||||
|
||||
bool KernelTouchDriver::getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) {
|
||||
if (pointer_read_data(device, READ_TIMEOUT) != ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
return pointer_get_touched_points(device, x, y, strength, pointCount, maxPointCount);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user