M5Stack StickS3 - New Tab5 - driver modules (#516)
Font size set to 18 for 800x480 displays Fix web server dashboard not rendering when sdcard isn't present Added new driver modules - BM8563 RTC - RX8130CE RTC - MPU6886 IMU - QMI8658 IMU - M5PM1 Power Management Chip Applied the above modules to applicable devicetrees. Added new device: M5Stack StickS3 Added new M5Stack Tab5 St7123 variant. ButtonControl changed to use interupts and xQueue, added AppClose action. And some bonus symbols of course, the apps are hungry for symbols.
This commit is contained in:
@@ -102,11 +102,17 @@ static void initExpander0(::Device* io_expander0) {
|
||||
static void initExpander1(::Device* io_expander1) {
|
||||
|
||||
auto* c6_wlan_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_C6_WLAN_ENABLE, GPIO_OWNER_GPIO);
|
||||
check(c6_wlan_enable_pin);
|
||||
auto* usb_a_5v_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_USB_A_5V_ENABLE, GPIO_OWNER_GPIO);
|
||||
check(usb_a_5v_enable_pin);
|
||||
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
|
||||
check(device_power_pin);
|
||||
auto* ip2326_ncharge_qc_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_OWNER_GPIO);
|
||||
check(ip2326_ncharge_qc_enable_pin);
|
||||
auto* ip2326_charge_state_led_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_STAT_LED, GPIO_OWNER_GPIO);
|
||||
check(ip2326_charge_state_led_pin);
|
||||
auto* ip2326_charge_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_OWNER_GPIO);
|
||||
check(ip2326_charge_enable_pin);
|
||||
|
||||
gpio_descriptor_set_flags(c6_wlan_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
gpio_descriptor_set_flags(usb_a_5v_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "Detect.h"
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <esp_lcd_touch_gt911.h>
|
||||
#include <esp_lcd_touch_st7123.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
static const auto LOGGER = tt::Logger("Tab5Detect");
|
||||
|
||||
Tab5Variant detectVariant() {
|
||||
// Allow time for touch IC to fully boot after expander reset in initBoot().
|
||||
// 100ms is enough for I2C ACK (probe) but cold power-on needs ~300ms before
|
||||
// register reads (read_fw_info) succeed reliably.
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
|
||||
auto* i2c0 = device_find_by_name("i2c0");
|
||||
check(i2c0);
|
||||
|
||||
constexpr auto PROBE_TIMEOUT = pdMS_TO_TICKS(50);
|
||||
|
||||
for (int attempt = 0; attempt < 3; ++attempt) {
|
||||
// GT911 address depends on INT pin state during reset:
|
||||
// GPIO 23 has a pull-up resistor to 3V3, so INT is high at reset → GT911 uses 0x5D (primary)
|
||||
// It may also appear at 0x14 (backup) if the pin happened to be driven low
|
||||
if (i2c_controller_has_device_at_address(i2c0, ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, PROBE_TIMEOUT) == ERROR_NONE ||
|
||||
i2c_controller_has_device_at_address(i2c0, ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP, PROBE_TIMEOUT) == ERROR_NONE) {
|
||||
LOGGER.info("Detected GT911 touch — using ILI9881C display");
|
||||
return Tab5Variant::Ili9881c_Gt911;
|
||||
}
|
||||
|
||||
// Probe for ST7123 touch (new variant)
|
||||
if (i2c_controller_has_device_at_address(i2c0, ESP_LCD_TOUCH_IO_I2C_ST7123_ADDRESS, PROBE_TIMEOUT) == ERROR_NONE) {
|
||||
LOGGER.info("Detected ST7123 touch — using ST7123 display");
|
||||
return Tab5Variant::St7123;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
LOGGER.warn("No known touch controller detected, defaulting to ST7123");
|
||||
return Tab5Variant::St7123;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
enum class Tab5Variant {
|
||||
Ili9881c_Gt911, // Older variant
|
||||
St7123, // Newer variant (default)
|
||||
};
|
||||
|
||||
[[nodiscard]] Tab5Variant detectVariant();
|
||||
@@ -1,16 +1,22 @@
|
||||
#include "Detect.h"
|
||||
#include "Display.h"
|
||||
#include "Ili9881cDisplay.h"
|
||||
#include "St7123Display.h"
|
||||
#include "St7123Touch.h"
|
||||
|
||||
#include <Gt911Touch.h>
|
||||
#include <PwmBacklight.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
static const auto LOGGER = tt::Logger("Tab5Display");
|
||||
|
||||
constexpr auto LCD_PIN_RESET = GPIO_NUM_0; // Match P4 EV board reset line
|
||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_22;
|
||||
|
||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createGt911Touch() {
|
||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
||||
I2C_NUM_0,
|
||||
720,
|
||||
@@ -19,25 +25,46 @@ static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
||||
false, // mirrorX
|
||||
false, // mirrorY
|
||||
GPIO_NUM_NC, // reset pin
|
||||
GPIO_NUM_NC // "GPIO_NUM_23 cannot be used due to resistor to 3V3" https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L76234
|
||||
GPIO_NUM_NC // "GPIO_NUM_23 cannot be used due to resistor to 3V3"
|
||||
// https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L76234
|
||||
);
|
||||
|
||||
return std::make_shared<Gt911Touch>(std::move(configuration));
|
||||
}
|
||||
|
||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createSt7123Touch() {
|
||||
auto configuration = std::make_unique<St7123Touch::Configuration>(
|
||||
I2C_NUM_0,
|
||||
720,
|
||||
1280,
|
||||
false, // swapXY
|
||||
false, // mirrorX
|
||||
false, // mirrorY
|
||||
GPIO_NUM_23 // interrupt pin
|
||||
);
|
||||
return std::make_shared<St7123Touch>(std::move(configuration));
|
||||
}
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||
// Initialize PWM backlight
|
||||
if (!driver::pwmbacklight::init(LCD_PIN_BACKLIGHT, 5000, LEDC_TIMER_1, LEDC_CHANNEL_0)) {
|
||||
tt::Logger("Tab5").warn("Failed to initialize backlight");
|
||||
LOGGER.warn("Failed to initialize backlight");
|
||||
}
|
||||
|
||||
auto touch = createTouch();
|
||||
Tab5Variant variant = detectVariant();
|
||||
|
||||
// Work-around to init touch : interrupt pin must be set to low
|
||||
// Note: There is a resistor to 3V3 on interrupt pin which is blocking GT911 touch
|
||||
// See https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L777
|
||||
tt::hal::gpio::configure(23, tt::hal::gpio::Mode::Output, true, false);
|
||||
tt::hal::gpio::setLevel(23, false);
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
|
||||
|
||||
if (variant == Tab5Variant::St7123) {
|
||||
touch = createSt7123Touch();
|
||||
} else {
|
||||
touch = createGt911Touch();
|
||||
|
||||
// Work-around to init GT911 touch: interrupt pin must be set to low
|
||||
// Note: There is a resistor to 3V3 on interrupt pin which is blocking GT911 touch
|
||||
// See https://github.com/espressif/esp-bsp/blob/ad668c765cbad177495a122181df0a70ff9f8f61/bsp/m5stack_tab5/src/m5stack_tab5.c#L777
|
||||
tt::hal::gpio::configure(23, tt::hal::gpio::Mode::Output, true, false);
|
||||
tt::hal::gpio::setLevel(23, false);
|
||||
}
|
||||
|
||||
auto configuration = std::make_shared<EspLcdConfiguration>(EspLcdConfiguration {
|
||||
.horizontalResolution = 720,
|
||||
@@ -50,6 +77,8 @@ std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||
.mirrorY = false,
|
||||
.invertColor = false,
|
||||
.bufferSize = 0, // 0 = default (1/10 of screen)
|
||||
.swRotate = (variant == Tab5Variant::St7123), // ST7123 MIPI-DSI panel does not support hardware swap_xy
|
||||
.buffSpiram = (variant == Tab5Variant::St7123), // sw_rotate needs a 3rd buffer; use PSRAM to avoid OOM in internal SRAM
|
||||
.touch = touch,
|
||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
||||
.resetPin = LCD_PIN_RESET,
|
||||
@@ -59,6 +88,13 @@ std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||
.bitsPerPixel = 16
|
||||
});
|
||||
|
||||
const auto display = std::make_shared<Ili9881cDisplay>(configuration);
|
||||
return std::static_pointer_cast<tt::hal::display::DisplayDevice>(display);
|
||||
if (variant == Tab5Variant::St7123) {
|
||||
return std::static_pointer_cast<tt::hal::display::DisplayDevice>(
|
||||
std::make_shared<St7123Display>(configuration)
|
||||
);
|
||||
} else {
|
||||
return std::static_pointer_cast<tt::hal::display::DisplayDevice>(
|
||||
std::make_shared<Ili9881cDisplay>(configuration)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "Ili9881cDisplay.h"
|
||||
#include "disp_init_data.h"
|
||||
#include "ili9881_init_data.h"
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <esp_lcd_ili9881c.h>
|
||||
@@ -47,6 +47,8 @@ bool Ili9881cDisplay::createMipiDsiBus() {
|
||||
|
||||
if (esp_lcd_new_dsi_bus(&bus_config, &mipiDsiBus) != ESP_OK) {
|
||||
LOGGER.error("Failed to create bus");
|
||||
esp_ldo_release_channel(ldoChannel);
|
||||
ldoChannel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,6 +69,10 @@ bool Ili9881cDisplay::createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) {
|
||||
|
||||
if (esp_lcd_new_panel_io_dbi(mipiDsiBus, &dbi_config, &ioHandle) != ESP_OK) {
|
||||
LOGGER.error("Failed to create panel IO");
|
||||
esp_lcd_del_dsi_bus(mipiDsiBus);
|
||||
mipiDsiBus = nullptr;
|
||||
esp_ldo_release_channel(ldoChannel);
|
||||
ldoChannel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -108,15 +114,15 @@ bool Ili9881cDisplay::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, cons
|
||||
.vsync_back_porch = 20,
|
||||
.vsync_front_porch = 20,
|
||||
},
|
||||
.flags {
|
||||
.flags = {
|
||||
.use_dma2d = 1, // TODO: true?
|
||||
.disable_lp = 0,
|
||||
}
|
||||
};
|
||||
|
||||
ili9881c_vendor_config_t vendor_config = {
|
||||
.init_cmds = disp_init_data,
|
||||
.init_cmds_size = std::size(disp_init_data),
|
||||
.init_cmds = ili9881_init_data,
|
||||
.init_cmds_size = std::size(ili9881_init_data),
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipiDsiBus,
|
||||
.dpi_config = &dpi_config,
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
#include "St7123Display.h"
|
||||
#include "st7123_init_data.h"
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <esp_lcd_st7123.h>
|
||||
|
||||
static const auto LOGGER = tt::Logger("St7123");
|
||||
|
||||
St7123Display::~St7123Display() {
|
||||
// TODO: This should happen during ::stop(), but this isn't currently exposed
|
||||
if (mipiDsiBus != nullptr) {
|
||||
esp_lcd_del_dsi_bus(mipiDsiBus);
|
||||
mipiDsiBus = nullptr;
|
||||
}
|
||||
if (ldoChannel != nullptr) {
|
||||
esp_ldo_release_channel(ldoChannel);
|
||||
ldoChannel = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool St7123Display::createMipiDsiBus() {
|
||||
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||
.chan_id = 3,
|
||||
.voltage_mv = 2500,
|
||||
.flags = {
|
||||
.adjustable = 0,
|
||||
.owned_by_hw = 0,
|
||||
.bypass = 0
|
||||
}
|
||||
};
|
||||
|
||||
if (esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldoChannel) != ESP_OK) {
|
||||
LOGGER.error("Failed to acquire LDO channel for MIPI DSI PHY");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.info("Powered on");
|
||||
|
||||
const esp_lcd_dsi_bus_config_t bus_config = {
|
||||
.bus_id = 0,
|
||||
.num_data_lanes = 2,
|
||||
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
|
||||
.lane_bit_rate_mbps = 965 // ST7123 lane bitrate per M5Stack BSP
|
||||
};
|
||||
|
||||
if (esp_lcd_new_dsi_bus(&bus_config, &mipiDsiBus) != ESP_OK) {
|
||||
LOGGER.error("Failed to create bus");
|
||||
esp_ldo_release_channel(ldoChannel);
|
||||
ldoChannel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.info("Bus created");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool St7123Display::createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) {
|
||||
if (mipiDsiBus == nullptr) {
|
||||
if (!createMipiDsiBus()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// DBI interface for LCD commands/parameters (8-bit cmd/param per ST7123 spec)
|
||||
esp_lcd_dbi_io_config_t dbi_config = {
|
||||
.virtual_channel = 0,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_io_dbi(mipiDsiBus, &dbi_config, &ioHandle) != ESP_OK) {
|
||||
LOGGER.error("Failed to create panel IO");
|
||||
esp_lcd_del_dsi_bus(mipiDsiBus);
|
||||
mipiDsiBus = nullptr;
|
||||
esp_ldo_release_channel(ldoChannel);
|
||||
ldoChannel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t St7123Display::createPanelConfig(std::shared_ptr<EspLcdConfiguration> espLcdConfiguration, gpio_num_t resetPin) {
|
||||
return {
|
||||
.reset_gpio_num = resetPin,
|
||||
.rgb_ele_order = espLcdConfiguration->rgbElementOrder,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.flags = {
|
||||
.reset_active_high = 0
|
||||
},
|
||||
.vendor_config = nullptr
|
||||
};
|
||||
}
|
||||
|
||||
bool St7123Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) {
|
||||
esp_lcd_dpi_panel_config_t dpi_config = {
|
||||
.virtual_channel = 0,
|
||||
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
|
||||
.dpi_clock_freq_mhz = 70,
|
||||
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
|
||||
.num_fbs = 1,
|
||||
.video_timing = {
|
||||
.h_size = 720,
|
||||
.v_size = 1280,
|
||||
.hsync_pulse_width = 2,
|
||||
.hsync_back_porch = 40,
|
||||
.hsync_front_porch = 40,
|
||||
.vsync_pulse_width = 2,
|
||||
.vsync_back_porch = 8,
|
||||
.vsync_front_porch = 220,
|
||||
},
|
||||
.flags = {
|
||||
.use_dma2d = 1,
|
||||
.disable_lp = 0,
|
||||
}
|
||||
};
|
||||
|
||||
st7123_vendor_config_t vendor_config = {
|
||||
.init_cmds = st7123_init_data,
|
||||
.init_cmds_size = std::size(st7123_init_data),
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipiDsiBus,
|
||||
.dpi_config = &dpi_config,
|
||||
},
|
||||
};
|
||||
|
||||
// Create a mutable copy of panelConfig to set vendor_config
|
||||
esp_lcd_panel_dev_config_t mutable_panel_config = panelConfig;
|
||||
mutable_panel_config.vendor_config = &vendor_config;
|
||||
|
||||
if (esp_lcd_new_panel_st7123(ioHandle, &mutable_panel_config, &panelHandle) != ESP_OK) {
|
||||
LOGGER.error("Failed to create panel");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.info("Panel created successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
lvgl_port_display_dsi_cfg_t St7123Display::getLvglPortDisplayDsiConfig(esp_lcd_panel_io_handle_t /*ioHandle*/, esp_lcd_panel_handle_t /*panelHandle*/) {
|
||||
// Disable avoid_tearing to prevent stalls/blank flashes when other tasks (e.g. flash writes) block timing
|
||||
return lvgl_port_display_dsi_cfg_t{
|
||||
.flags = {
|
||||
.avoid_tearing = 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <EspLcdDisplayV2.h>
|
||||
|
||||
#include <esp_lcd_mipi_dsi.h>
|
||||
#include <esp_ldo_regulator.h>
|
||||
|
||||
class St7123Display final : public EspLcdDisplayV2 {
|
||||
|
||||
esp_lcd_dsi_bus_handle_t mipiDsiBus = nullptr;
|
||||
esp_ldo_channel_handle_t ldoChannel = nullptr;
|
||||
|
||||
bool createMipiDsiBus();
|
||||
|
||||
protected:
|
||||
|
||||
bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) override;
|
||||
|
||||
esp_lcd_panel_dev_config_t createPanelConfig(std::shared_ptr<EspLcdConfiguration> espLcdConfiguration, gpio_num_t resetPin) override;
|
||||
|
||||
bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) override;
|
||||
|
||||
bool useDsiPanel() const override { return true; }
|
||||
|
||||
lvgl_port_display_dsi_cfg_t getLvglPortDisplayDsiConfig(esp_lcd_panel_io_handle_t /*ioHandle*/, esp_lcd_panel_handle_t /*panelHandle*/) override;
|
||||
|
||||
public:
|
||||
|
||||
St7123Display(
|
||||
const std::shared_ptr<EspLcdConfiguration>& configuration
|
||||
) : EspLcdDisplayV2(configuration) {}
|
||||
|
||||
~St7123Display() override;
|
||||
|
||||
std::string getName() const override { return "St7123"; }
|
||||
|
||||
std::string getDescription() const override { return "St7123 MIPI-DSI display"; }
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "St7123Touch.h"
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <esp_lcd_touch_st7123.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
static const auto LOGGER = tt::Logger("ST7123Touch");
|
||||
|
||||
bool St7123Touch::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
|
||||
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_ST7123_CONFIG();
|
||||
return esp_lcd_new_panel_io_i2c(
|
||||
static_cast<esp_lcd_i2c_bus_handle_t>(configuration->port),
|
||||
&io_config,
|
||||
&outHandle
|
||||
) == ESP_OK;
|
||||
}
|
||||
|
||||
bool St7123Touch::createTouchHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_touch_config_t& config, esp_lcd_touch_handle_t& touchHandle) {
|
||||
return esp_lcd_touch_new_i2c_st7123(ioHandle, &config, &touchHandle) == ESP_OK;
|
||||
}
|
||||
|
||||
esp_lcd_touch_config_t St7123Touch::createEspLcdTouchConfig() {
|
||||
return {
|
||||
.x_max = configuration->xMax,
|
||||
.y_max = configuration->yMax,
|
||||
.rst_gpio_num = GPIO_NUM_NC,
|
||||
.int_gpio_num = configuration->pinInterrupt,
|
||||
.levels = {
|
||||
.reset = 0,
|
||||
.interrupt = 0,
|
||||
},
|
||||
.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
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <EspLcdTouch.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <driver/i2c.h>
|
||||
|
||||
class St7123Touch 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 pinInterrupt = GPIO_NUM_NC
|
||||
) : port(port),
|
||||
xMax(xMax),
|
||||
yMax(yMax),
|
||||
swapXy(swapXy),
|
||||
mirrorX(mirrorX),
|
||||
mirrorY(mirrorY),
|
||||
pinInterrupt(pinInterrupt)
|
||||
{}
|
||||
|
||||
i2c_port_t port;
|
||||
uint16_t xMax;
|
||||
uint16_t yMax;
|
||||
bool swapXy;
|
||||
bool mirrorX;
|
||||
bool mirrorY;
|
||||
gpio_num_t pinInterrupt;
|
||||
};
|
||||
|
||||
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& config, esp_lcd_touch_handle_t& touchHandle) override;
|
||||
|
||||
esp_lcd_touch_config_t createEspLcdTouchConfig() override;
|
||||
|
||||
public:
|
||||
|
||||
explicit St7123Touch(std::unique_ptr<Configuration> inConfiguration) : configuration(std::move(inConfiguration)) {
|
||||
assert(configuration != nullptr);
|
||||
}
|
||||
|
||||
std::string getName() const override { return "ST7123Touch"; }
|
||||
|
||||
std::string getDescription() const override { return "ST7123 I2C touch driver"; }
|
||||
};
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
#include <esp_lcd_ili9881c.h>
|
||||
|
||||
static const ili9881c_lcd_init_cmd_t disp_init_data[] = {
|
||||
static const ili9881c_lcd_init_cmd_t ili9881_init_data[] = {
|
||||
// {cmd, { data }, data_size, delay}
|
||||
|
||||
/**** CMD_Page 1 ****/
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
#include <esp_lcd_st7123.h>
|
||||
|
||||
//Refer to https://github.com/m5stack/M5Tab5-UserDemo
|
||||
//https://github.com/m5stack/M5Tab5-UserDemo/blob/main/LICENSE
|
||||
static const st7123_lcd_init_cmd_t st7123_init_data[] = {
|
||||
{0x60, (uint8_t[]){0x71, 0x23, 0xa2}, 3, 0},
|
||||
{0x60, (uint8_t[]){0x71, 0x23, 0xa3}, 3, 0},
|
||||
{0x60, (uint8_t[]){0x71, 0x23, 0xa4}, 3, 0},
|
||||
{0xA4, (uint8_t[]){0x31}, 1, 0},
|
||||
{0xD7, (uint8_t[]){0x10, 0x0A, 0x10, 0x2A, 0x80, 0x80}, 6, 0},
|
||||
{0x90, (uint8_t[]){0x71, 0x23, 0x5A, 0x20, 0x24, 0x09, 0x09}, 7, 0},
|
||||
{0xA3, (uint8_t[]){0x80, 0x01, 0x88, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x4F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x6F, 0x58, 0x00, 0x00, 0x00, 0xFF}, 40, 0},
|
||||
{0xA6, (uint8_t[]){0x03, 0x00, 0x24, 0x55, 0x36, 0x00, 0x39, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, 0x55, 0x38, 0x00, 0x37, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0xEC, 0x11, 0x00, 0x03, 0x00, 0x03, 0x6E, 0x6E, 0xFF, 0xFF, 0x00, 0x08, 0x80, 0x08, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00}, 55, 0},
|
||||
{0xA7, (uint8_t[]){0x19, 0x19, 0x80, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x44, 0x03, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x25, 0x34, 0x40, 0x00, 0x02, 0x01, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x6E, 0x6E, 0x84, 0xFF, 0x08, 0x80, 0x44}, 60, 0},
|
||||
{0xAC, (uint8_t[]){0x03, 0x19, 0x19, 0x18, 0x18, 0x06, 0x13, 0x13, 0x11, 0x11, 0x08, 0x08, 0x0A, 0x0A, 0x1C, 0x1C, 0x07, 0x07, 0x00, 0x00, 0x02, 0x02, 0x01, 0x19, 0x19, 0x18, 0x18, 0x06, 0x12, 0x12, 0x10, 0x10, 0x09, 0x09, 0x0B, 0x0B, 0x1C, 0x1C, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01}, 44, 0},
|
||||
{0xAD, (uint8_t[]){0xF0, 0x00, 0x46, 0x00, 0x03, 0x50, 0x50, 0xFF, 0xFF, 0xF0, 0x40, 0x06, 0x01, 0x07, 0x42, 0x42, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, 25, 0},
|
||||
{0xAE, (uint8_t[]){0xFE, 0x3F, 0x3F, 0xFE, 0x3F, 0x3F, 0x00}, 7, 0},
|
||||
{0xB2, (uint8_t[]){0x15, 0x19, 0x05, 0x23, 0x49, 0xAF, 0x03, 0x2E, 0x5C, 0xD2, 0xFF, 0x10, 0x20, 0xFD, 0x20, 0xC0, 0x00}, 17, 0},
|
||||
{0xE8, (uint8_t[]){0x20, 0x6F, 0x04, 0x97, 0x97, 0x3E, 0x04, 0xDC, 0xDC, 0x3E, 0x06, 0xFA, 0x26, 0x3E}, 15, 0},
|
||||
{0x75, (uint8_t[]){0x03, 0x04}, 2, 0},
|
||||
{0xE7, (uint8_t[]){0x3B, 0x00, 0x00, 0x7C, 0xA1, 0x8C, 0x20, 0x1A, 0xF0, 0xB1, 0x50, 0x00, 0x50, 0xB1, 0x50, 0xB1, 0x50, 0xD8, 0x00, 0x55, 0x00, 0xB1, 0x00, 0x45, 0xC9, 0x6A, 0xFF, 0x5A, 0xD8, 0x18, 0x88, 0x15, 0xB1, 0x01, 0x01, 0x77}, 36, 0},
|
||||
{0xEA, (uint8_t[]){0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2C}, 8, 0},
|
||||
{0xB0, (uint8_t[]){0x22, 0x43, 0x11, 0x61, 0x25, 0x43, 0x43}, 7, 0},
|
||||
{0xB7, (uint8_t[]){0x00, 0x00, 0x73, 0x73}, 0x04, 0},
|
||||
{0xBF, (uint8_t[]){0xA6, 0xAA}, 2, 0},
|
||||
{0xA9, (uint8_t[]){0x00, 0x00, 0x73, 0xFF, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03}, 10, 0},
|
||||
{0xC8, (uint8_t[]){0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF}, 37, 0},
|
||||
{0xC9, (uint8_t[]){0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF}, 37, 0},
|
||||
{0x36, (uint8_t[]){0x00}, 1, 0},
|
||||
{0x11, (uint8_t[]){0x00}, 1, 100},
|
||||
{0x29, (uint8_t[]){0x00}, 1, 0},
|
||||
{0x35, (uint8_t[]){0x00}, 1, 100},
|
||||
};
|
||||
Reference in New Issue
Block a user