Device migrations, driver migrations and more (#575)

This commit is contained in:
Ken Van Hoeylandt
2026-07-20 23:43:17 +02:00
committed by GitHub
parent 2d768ef3a1
commit 2fbc44466a
221 changed files with 8824 additions and 3652 deletions
@@ -1,7 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port EspLcdCompat AXS5106 JD9853
INCLUDE_DIRS "source"
REQUIRES TactilityKernel
)
@@ -1,18 +0,0 @@
#include "devices/Display.h"
#include <Tactility/hal/Configuration.h>
bool initBoot();
using namespace tt::hal;
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
return {
createDisplay(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,45 +0,0 @@
#include <Tactility/LogMessages.h>
#include <Tactility/TactilityCore.h>
#include <tactility/log.h>
#include <driver/ledc.h>
constexpr auto* TAG = "Waveshare";
constexpr auto LCD_BL_LEDC_TIMER = LEDC_TIMER_0;
constexpr auto LCD_BL_LEDC_MODE = LEDC_LOW_SPEED_MODE;
constexpr auto LCD_BL_LEDC_CHANNEL = LEDC_CHANNEL_0;
constexpr auto LCD_BL_LEDC_DUTY_RES = LEDC_TIMER_10_BIT;
constexpr auto LCD_BL_LEDC_DUTY = 1024;
constexpr auto LCD_BL_LEDC_FREQUENCY = 10000;
void setBacklightDuty(uint8_t level) {
uint32_t duty = (level * (LCD_BL_LEDC_DUTY - 1)) / 255;
ESP_ERROR_CHECK(ledc_set_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL, duty));
ESP_ERROR_CHECK(ledc_update_duty(LCD_BL_LEDC_MODE, LCD_BL_LEDC_CHANNEL));
}
void initBacklight() {
ledc_timer_config_t timer_config = {
.speed_mode = LCD_BL_LEDC_MODE,
.duty_resolution = LCD_BL_LEDC_DUTY_RES,
.timer_num = LCD_BL_LEDC_TIMER,
.freq_hz = LCD_BL_LEDC_FREQUENCY,
.clk_cfg = LEDC_AUTO_CLK};
ESP_ERROR_CHECK(ledc_timer_config(&timer_config));
ledc_channel_config_t channel_config = {
.gpio_num = GPIO_NUM_46,
.speed_mode = LCD_BL_LEDC_MODE,
.channel = LCD_BL_LEDC_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LCD_BL_LEDC_TIMER,
.duty = 0, // Set duty to 0%
.hpoint = 0};
ESP_ERROR_CHECK(ledc_channel_config(&channel_config));
}
bool initBoot() {
LOG_I(TAG, LOG_MESSAGE_POWER_ON_START);
initBacklight();
return true;
}
@@ -1,35 +0,0 @@
#include "Axs5106Touch.h"
#include <esp_lcd_touch_axs5106.h>
#include <esp_err.h>
bool Axs5106Touch::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_AXS5106_CONFIG();
return esp_lcd_new_panel_io_i2c(configuration->port, &io_config, &outHandle) == ESP_OK;
}
bool Axs5106Touch::createTouchHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_touch_config_t& configuration, esp_lcd_touch_handle_t& panelHandle) {
return esp_lcd_touch_new_i2c_axs5106(ioHandle, &configuration, &panelHandle) == ESP_OK;
}
esp_lcd_touch_config_t Axs5106Touch::createEspLcdTouchConfig() {
return {
.x_max = configuration->xMax,
.y_max = configuration->yMax,
.rst_gpio_num = configuration->pinReset,
.int_gpio_num = configuration->pinInterrupt,
.levels = {
.reset = configuration->pinResetLevel,
.interrupt = configuration->pinInterruptLevel,
},
.flags = {
.swap_xy = configuration->swapXy,
.mirror_x = configuration->mirrorX,
.mirror_y = configuration->mirrorY,
},
.process_coordinates = nullptr,
.interrupt_callback = nullptr,
.user_data = nullptr,
.driver_data = nullptr
};
}
@@ -1,70 +0,0 @@
#pragma once
#include <Tactility/hal/touch/TouchDevice.h>
#include <Tactility/TactilityCore.h>
#include <driver/i2c.h>
#include <EspLcdTouch.h>
class Axs5106Touch final : public EspLcdTouch {
public:
class Configuration {
public:
Configuration(
i2c_port_t port,
uint16_t xMax,
uint16_t yMax,
bool swapXy = false,
bool mirrorX = false,
bool mirrorY = false,
gpio_num_t pinReset = GPIO_NUM_NC,
gpio_num_t pinInterrupt = GPIO_NUM_NC,
unsigned int pinResetLevel = 0,
unsigned int pinInterruptLevel = 0
) : port(port),
xMax(xMax),
yMax(yMax),
swapXy(swapXy),
mirrorX(mirrorX),
mirrorY(mirrorY),
pinReset(pinReset),
pinInterrupt(pinInterrupt),
pinResetLevel(pinResetLevel),
pinInterruptLevel(pinInterruptLevel)
{}
i2c_port_t port;
uint16_t xMax;
uint16_t yMax;
bool swapXy;
bool mirrorX;
bool mirrorY;
gpio_num_t pinReset;
gpio_num_t pinInterrupt;
unsigned int pinResetLevel;
unsigned int pinInterruptLevel;
};
private:
std::unique_ptr<Configuration> configuration;
bool createIoHandle(esp_lcd_panel_io_handle_t& outHandle) override;
bool createTouchHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_touch_config_t& configuration, esp_lcd_touch_handle_t& panelHandle) override;
esp_lcd_touch_config_t createEspLcdTouchConfig() override;
public:
explicit Axs5106Touch(std::unique_ptr<Configuration> inConfiguration) : configuration(std::move(inConfiguration)) {
assert(configuration != nullptr);
}
std::string getName() const override { return "AXS5106"; }
std::string getDescription() const override { return "AXS5106 I2C touch driver"; }
};
@@ -1,50 +0,0 @@
#include "Display.h"
#include "Jd9853Display.h"
#include "Axs5106Touch.h"
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_21;
constexpr auto LCD_PIN_DC = GPIO_NUM_45;
constexpr auto LCD_PIN_RESET = GPIO_NUM_40;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 172;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
void setBacklightDuty(uint8_t level);
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Axs5106Touch::Configuration>(
I2C_NUM_0,
172,
320,
false,
false,
false,
GPIO_NUM_47,
GPIO_NUM_48
);
return std::make_shared<Axs5106Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
auto configuration = std::make_unique<Jd9853Display::Configuration>(
LCD_SPI_HOST,
LCD_PIN_CS,
LCD_PIN_DC,
LCD_PIN_RESET,
172,
320,
touch,
false,
false,
false,
true
);
configuration->backlightDutyFunction = setBacklightDuty;
auto display = std::make_shared<Jd9853Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
}
@@ -1,5 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
@@ -1,161 +0,0 @@
#include "Jd9853Display.h"
#include <esp_lcd_jd9853.h>
#include <esp_lcd_panel_commands.h>
#include <esp_lvgl_port.h>
#include <tactility/log.h>
constexpr auto* TAG = "JD9853";
bool Jd9853Display::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
const esp_lcd_panel_io_spi_config_t panel_io_config = {
.cs_gpio_num = configuration->csPin,
.dc_gpio_num = configuration->dcPin,
.spi_mode = 0,
.pclk_hz = configuration->pixelClockFrequency,
.trans_queue_depth = configuration->transactionQueueDepth,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.flags = {
.dc_high_on_cmd = 0,
.dc_low_on_data = 0,
.dc_low_on_param = 0,
.octal_mode = 0,
.quad_mode = 0,
.sio_mode = 0,
.lsb_first = 0,
.cs_high_active = 0
}
};
return esp_lcd_new_panel_io_spi(configuration->spiHostDevice, &panel_io_config, &outHandle) == ESP_OK;
}
bool Jd9853Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) {
jd9853_vendor_config_t vendor_config = {
.init_cmds = nullptr,
.init_cmds_size = 0
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = configuration->resetPin,
.rgb_ele_order = configuration->rgbElementOrder,
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
.bits_per_pixel = 16,
.flags = {
.reset_active_high = false
},
.vendor_config = &vendor_config
};
if (esp_lcd_new_panel_jd9853(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
LOG_E(TAG, "Failed to create panel");
return false;
}
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
LOG_E(TAG, "Failed to reset panel");
return false;
}
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
LOG_E(TAG, "Failed to init panel");
return false;
}
if (esp_lcd_panel_swap_xy(panelHandle, configuration->swapXY) != ESP_OK) {
LOG_E(TAG, "Failed to swap XY");
return false;
}
if (esp_lcd_panel_mirror(panelHandle, configuration->mirrorX, configuration->mirrorY) != ESP_OK) {
LOG_E(TAG, "Failed to set panel to mirror");
return false;
}
if (esp_lcd_panel_invert_color(panelHandle, configuration->invertColor) != ESP_OK) {
LOG_E(TAG, "Failed to set panel to invert");
return false;
}
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
LOG_E(TAG, "Failed to turn display on");
return false;
}
if (esp_lcd_panel_set_gap(panelHandle, 34, 0) != ESP_OK) {
LOG_E(TAG, "Failed to set panel gap");
return false;
}
return true;
}
lvgl_port_display_cfg_t Jd9853Display::getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
return {
.io_handle = ioHandle,
.panel_handle = panelHandle,
.control_handle = nullptr,
.buffer_size = configuration->bufferSize,
.double_buffer = false,
.trans_size = 0,
.hres = configuration->horizontalResolution,
.vres = configuration->verticalResolution,
.monochrome = false,
.rotation = {
.swap_xy = configuration->swapXY,
.mirror_x = configuration->mirrorX,
.mirror_y = configuration->mirrorY,
},
.color_format = LV_COLOR_FORMAT_RGB565,
.flags = {
.buff_dma = true,
.buff_spiram = false,
.sw_rotate = false,
.swap_bytes = true,
.full_refresh = false,
.direct_mode = false
}
};
}
/**
* Note:
* The datasheet implies this should work, but it doesn't:
* https://www.digikey.com/htmldatasheets/production/1640716/0/0/1/ILI9341-Datasheet.pdf
*
* This repo claims it only has 1 curve:
* https://github.com/brucemack/hello-ili9341
*
* I'm leaving it in as I'm not sure if it's just my hardware that's problematic.
*/
void Jd9853Display::setGammaCurve(uint8_t index) {
uint8_t gamma_curve;
switch (index) {
case 0:
gamma_curve = 0x01;
break;
case 1:
gamma_curve = 0x04;
break;
case 2:
gamma_curve = 0x02;
break;
case 3:
gamma_curve = 0x08;
break;
default:
return;
}
const uint8_t param[] = {
gamma_curve
};
if (esp_lcd_panel_io_tx_param(getIoHandle() , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
LOG_E(TAG, "Failed to set gamma");
}
}
@@ -1,106 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <EspLcdDisplay.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <esp_lcd_panel_io.h>
#include <esp_lcd_types.h>
#include <functional>
#include <lvgl.h>
class Jd9853Display final : public EspLcdDisplay {
public:
class Configuration {
public:
Configuration(
spi_host_device_t spiHostDevice,
gpio_num_t csPin,
gpio_num_t dcPin,
gpio_num_t resetPin,
unsigned int horizontalResolution,
unsigned int verticalResolution,
std::shared_ptr<tt::hal::touch::TouchDevice> touch,
bool swapXY = false,
bool mirrorX = false,
bool mirrorY = false,
bool invertColor = false,
uint32_t bufferSize = 0, // Size in pixel count. 0 means default, which is 1/10 of the screen size,
lcd_rgb_element_order_t rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB
) : spiHostDevice(spiHostDevice),
csPin(csPin),
dcPin(dcPin),
resetPin(resetPin),
horizontalResolution(horizontalResolution),
verticalResolution(verticalResolution),
swapXY(swapXY),
mirrorX(mirrorX),
mirrorY(mirrorY),
invertColor(invertColor),
bufferSize(bufferSize),
rgbElementOrder(rgbElementOrder),
touch(std::move(touch)
) {
if (this->bufferSize == 0) {
this->bufferSize = horizontalResolution * verticalResolution / 10;
}
}
spi_host_device_t spiHostDevice;
gpio_num_t csPin;
gpio_num_t dcPin;
gpio_num_t resetPin;
unsigned int pixelClockFrequency = 40'000'000; // Hertz
size_t transactionQueueDepth = 10;
unsigned int horizontalResolution;
unsigned int verticalResolution;
bool swapXY;
bool mirrorX;
bool mirrorY;
bool invertColor;
uint32_t bufferSize; // Size in pixel count. 0 means default, which is 1/10 of the screen size
lcd_rgb_element_order_t rgbElementOrder;
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> backlightDutyFunction = nullptr;
};
private:
std::unique_ptr<Configuration> configuration;
bool createIoHandle(esp_lcd_panel_io_handle_t& outHandle) override;
bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) override;
lvgl_port_display_cfg_t getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) override;
public:
explicit Jd9853Display(std::unique_ptr<Configuration> inConfiguration) :
configuration(std::move(inConfiguration)
) {}
std::string getName() const override { return "JD9853"; }
std::string getDescription() const override { return "JD9853 display"; }
std::shared_ptr<tt::hal::touch::TouchDevice> getTouchDevice() override { return configuration->touch; }
void setBacklightDuty(uint8_t backlightDuty) override {
if (configuration->backlightDutyFunction != nullptr) {
configuration->backlightDutyFunction(backlightDuty);
}
}
bool supportsBacklightDuty() const override { return configuration->backlightDutyFunction != nullptr; }
void setGammaCurve(uint8_t index) override;
uint8_t getGammaCurveCount() const override { return 4; };
};
@@ -1,23 +0,0 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module waveshare_s3_touch_lcd_147_module = {
.name = "waveshare-s3-touch-lcd-147",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
@@ -3,7 +3,6 @@ general.name=S3 Touch LCD 1.47"
general.incubating=true
apps.launcherAppId=Launcher
apps.autoStartAppId=ApWebServer
hardware.target=ESP32S3
hardware.flashSize=16MB
@@ -14,13 +13,13 @@ hardware.tinyUsb=true
hardware.esptoolFlashFreq=120M
hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD
display.size=1.47"
display.shape=rectangle
display.dpi=247
cdn.warningMessage=Touch doesn't work yet
lvgl.colorDepth=16
lvgl.uiDensity=compact
@@ -1,3 +1,6 @@
dependencies:
- Platforms/platform-esp32
- Drivers/axs5106-module
- Drivers/button-control-module
- Drivers/jd9853-module
dts: waveshare,s3-touch-lcd-147.dts
@@ -0,0 +1,14 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module waveshare_s3_touch_lcd_147_module = {
.name = "waveshare-s3-touch-lcd-147",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
@@ -7,7 +7,11 @@
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/axs5106.h>
#include <bindings/button_control.h>
#include <bindings/jd9853.h>
// Reference: https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.47
/ {
@@ -35,6 +39,32 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 42 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 41 GPIO_FLAG_NONE>;
touch0 {
compatible = "axs,axs5106";
reg = <0x63>;
x-max = <172>;
y-max = <320>;
mirror-x;
pin-reset = <&gpio0 47 GPIO_FLAG_NONE>;
pin-interrupt = <&gpio0 48 GPIO_FLAG_NONE>;
};
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 46 GPIO_FLAG_NONE>;
period-ns = <100000>;
ledc-timer = <0>;
ledc-channel = <0>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
@@ -44,8 +74,15 @@
pin-mosi = <&gpio0 39 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 38 GPIO_FLAG_NONE>;
display {
compatible = "display-placeholder";
display@0 {
compatible = "jadard,jd9853";
horizontal-resolution = <172>;
vertical-resolution = <320>;
gap-x = <34>;
invert-color;
pin-dc = <&gpio0 45 GPIO_FLAG_NONE>;
pin-reset = <&gpio0 40 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
@@ -56,10 +93,15 @@
pin-mosi = <&gpio0 15 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 17 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 16 GPIO_FLAG_NONE>;
sdcard@0 {
compatible = "espressif,esp32-sdspi";
frequency-khz = <20000>;
};
};
buttons {
compatible = "tactility,button-control";
pin-primary = <&gpio0 0 GPIO_FLAG_NONE>;
};
};