Merge develop into main (#368)

New boards:
- LilyGO T-Dongle S3
- M5Stack StickC Plus
- M5Stack StickC Plus2

New drivers:
- AXP192: power control via I2C
- ButtonControl: GPIO button input as LVGL device

Other changes:
- Updated implementation of AXP192 driver for Core2 board
- Fix launcher UX for vertical layout
- Fix error when properties file had an empty line
- Add `__floatsidf` to `tt_init.cpp`
This commit is contained in:
Ken Van Hoeylandt
2025-10-14 20:39:23 +02:00
committed by GitHub
parent 3a59540365
commit d8346998ce
68 changed files with 1857 additions and 142 deletions
+5
View File
@@ -0,0 +1,5 @@
idf_component_register(
SRC_DIRS "Source"
INCLUDE_DIRS "Source"
REQUIRES Tactility driver EspLcdCompat esp_lcd_st7735
)
+3
View File
@@ -0,0 +1,3 @@
# ST7735
A basic ESP32 LVGL driver for ST7735 displays.
+170
View File
@@ -0,0 +1,170 @@
#include "St7735Display.h"
#include <Tactility/Log.h>
#include <esp_lcd_panel_commands.h>
#include <esp_lcd_panel_dev.h>
#include <esp_lcd_st7735.h>
#include <esp_lvgl_port.h>
constexpr auto TAG = "ST7735";
bool St7735Display::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
TT_LOG_I(TAG, "Starting");
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 = 1,
.lsb_first = 0,
.cs_high_active = 0
}
};
if (esp_lcd_new_panel_io_spi(configuration->spiHostDevice, &panel_io_config, &outHandle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to create panel");
return false;
}
return true;
}
bool St7735Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) {
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = configuration->resetPin,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
.bits_per_pixel = 16,
.flags = {
.reset_active_high = false
},
.vendor_config = nullptr
};
if (esp_lcd_new_panel_st7735(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to create panel");
return false;
}
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to reset panel");
return false;
}
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to init panel");
return false;
}
if (esp_lcd_panel_invert_color(panelHandle, configuration->invertColor) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set panel to invert");
return false;
}
// Warning: it looks like LVGL rotation is broken when "gap" is set and the screen is moved to a non-default orientation
int gap_x = configuration->swapXY ? configuration->gapY : configuration->gapX;
int gap_y = configuration->swapXY ? configuration->gapX : configuration->gapY;
if (esp_lcd_panel_set_gap(panelHandle, gap_x, gap_y) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set panel gap");
return false;
}
if (esp_lcd_panel_swap_xy(panelHandle, configuration->swapXY) != ESP_OK) {
TT_LOG_E(TAG, "Failed to swap XY ");
return false;
}
if (esp_lcd_panel_mirror(panelHandle, configuration->mirrorX, configuration->mirrorY) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set panel to mirror");
return false;
}
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
TT_LOG_E(TAG, "Failed to turn display on");
return false;
}
return true;
}
lvgl_port_display_cfg_t St7735Display::getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
return lvgl_port_display_cfg_t {
.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 St7735Display::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
};
auto io_handle = getIoHandle();
assert(io_handle != nullptr);
if (esp_lcd_panel_io_tx_param(io_handle, LCD_CMD_GAMSET, param, 1) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set gamma");
}
}
+116
View File
@@ -0,0 +1,116 @@
#pragma once
#include "Tactility/hal/spi/Spi.h"
#include <EspLcdDisplay.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <esp_lcd_panel_io.h>
#include <esp_lcd_types.h>
#include <functional>
#include <lvgl.h>
class St7735Display final : public EspLcdDisplay {
std::shared_ptr<tt::Lock> lock;
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
int gapX = 0,
int gapY = 0
) : spiHostDevice(spiHostDevice),
csPin(csPin),
dcPin(dcPin),
resetPin(resetPin),
horizontalResolution(horizontalResolution),
verticalResolution(verticalResolution),
gapX(gapX),
gapY(gapY),
swapXY(swapXY),
mirrorX(mirrorX),
mirrorY(mirrorY),
invertColor(invertColor),
bufferSize(bufferSize),
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 = GPIO_NUM_NC;
unsigned int pixelClockFrequency = 27'000'000; // Hertz
size_t transactionQueueDepth = 10;
unsigned int horizontalResolution;
unsigned int verticalResolution;
int gapX;
int gapY;
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
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> _Nullable backlightDutyFunction = nullptr;
};
private:
std::unique_ptr<Configuration> configuration;
bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) 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 St7735Display(std::unique_ptr<Configuration> inConfiguration) :
EspLcdDisplay(tt::hal::spi::getLock(inConfiguration->spiHostDevice)),
configuration(std::move(inConfiguration)
) {
assert(configuration != nullptr);
assert(getLock() != nullptr);
}
std::string getName() const override { return "ST7735"; }
std::string getDescription() const override { return "ST7735 display"; }
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable 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; };
};
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();