Merge develop into main (#391)

## Improvements

- Created new base driver classes: `EspLcdDisplayV2' and `EspLcdSpiDisplay`
- Updated `St7789Display` to implement `EspLcdSpiDisplay`
- Updated all boards with ST7789 display

## Fixes

- Ensure that `tmp/` is created on startup (for all writeable filesystems)
- Fix for `lv_list` padding on small screen devices
- Fix for `PreferencesEsp` not processing result when writing string to NVS

## Other

- Remove unused build scripts
This commit is contained in:
Ken Van Hoeylandt 2025-10-26 13:50:17 +01:00 committed by GitHub
parent 37420db000
commit db6d3b4acb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 851 additions and 784 deletions

View File

@ -5,25 +5,20 @@
#include <PwmBacklight.h>
#include <Tactility/hal/Configuration.h>
// SPI Transfer
#define CYD_SPI_TRANSFER_SIZE_LIMIT (CYD2432S028RV3_LCD_DRAW_BUFFER_SIZE * LV_COLOR_DEPTH / 8)
// Display backlight (PWM)
#define CYD2432S028RV3_LCD_PIN_BACKLIGHT GPIO_NUM_21
using namespace tt::hal;
static bool initBoot() {
//Set the RGB Led Pins to output and turn them off
// Set the RGB LED Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); //Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); //Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); //Blue
//0 on, 1 off... yep it's backwards.
// 0 on, 1 off... yep it's backwards.
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); //Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); //Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); //Blue
return driver::pwmbacklight::init(CYD2432S028RV3_LCD_PIN_BACKLIGHT);
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
@ -71,7 +66,7 @@ const Configuration cyd_2432s028rv3_config = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = CYD_SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -7,12 +7,12 @@ constexpr auto* TAG = "CYD";
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Xpt2046SoftSpi::Configuration>(
CYD_TOUCH_MOSI_PIN,
CYD_TOUCH_MISO_PIN,
CYD_TOUCH_SCK_PIN,
CYD_TOUCH_CS_PIN,
CYD2432S028RV3_LCD_HORIZONTAL_RESOLUTION, // 240
CYD2432S028RV3_LCD_VERTICAL_RESOLUTION, // 320
TOUCH_MOSI_PIN,
TOUCH_MISO_PIN,
TOUCH_SCK_PIN,
TOUCH_CS_PIN,
LCD_HORIZONTAL_RESOLUTION, // 240
LCD_VERTICAL_RESOLUTION, // 320
false, // swapXY
true, // mirrorX
false // mirrorY
@ -31,24 +31,28 @@ static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = false,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC
};
auto configuration = std::make_unique<St7789Display::Configuration>(
CYD2432S028RV3_LCD_SPI_HOST,
CYD2432S028RV3_LCD_PIN_CS,
CYD2432S028RV3_LCD_PIN_DC,
CYD2432S028RV3_LCD_HORIZONTAL_RESOLUTION,
CYD2432S028RV3_LCD_VERTICAL_RESOLUTION,
touch,
false, // swapXY
false, // mirrorX
false, // mirrorY
false, // invertColor
CYD2432S028RV3_LCD_DRAW_BUFFER_SIZE
);
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,22 +1,28 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
#define CYD2432S028RV3_LCD_SPI_HOST SPI2_HOST
#define CYD2432S028RV3_LCD_HORIZONTAL_RESOLUTION 240
#define CYD2432S028RV3_LCD_VERTICAL_RESOLUTION 320
#define CYD2432S028RV3_LCD_DRAW_BUFFER_HEIGHT (CYD2432S028RV3_LCD_VERTICAL_RESOLUTION / 10)
#define CYD2432S028RV3_LCD_DRAW_BUFFER_SIZE (CYD2432S028RV3_LCD_HORIZONTAL_RESOLUTION * CYD2432S028RV3_LCD_DRAW_BUFFER_HEIGHT)
#define CYD2432S028RV3_LCD_PIN_CS GPIO_NUM_15
#define CYD2432S028RV3_LCD_PIN_DC GPIO_NUM_2
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_21;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
// Touch (Software SPI)
#define CYD_TOUCH_MISO_PIN GPIO_NUM_39
#define CYD_TOUCH_MOSI_PIN GPIO_NUM_32
#define CYD_TOUCH_SCK_PIN GPIO_NUM_25
#define CYD_TOUCH_CS_PIN GPIO_NUM_33
#define CYD_TOUCH_IRQ_PIN GPIO_NUM_36
constexpr auto TOUCH_MISO_PIN = GPIO_NUM_39;
constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_32;
constexpr auto TOUCH_SCK_PIN = GPIO_NUM_25;
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -8,8 +8,6 @@
using namespace tt::hal;
#define CYD_SPI_TRANSFER_SIZE_LIMIT (JC2432W328C_LCD_DRAW_BUFFER_SIZE * LV_COLOR_DEPTH / 8)
static bool initBoot() {
//Set the RGB Led Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); //Red
@ -21,7 +19,7 @@ static bool initBoot() {
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); //Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); //Blue
return driver::pwmbacklight::init(JC2432W328C_LCD_PIN_BACKLIGHT);
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
@ -88,7 +86,7 @@ const Configuration cyd_jc2432w328c_config = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = CYD_SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -7,32 +7,36 @@
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Cst816sTouch::Configuration>(
I2C_NUM_0,
240,
320
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION
);
return std::make_shared<Cst816sTouch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = false,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC
};
auto configuration = std::make_unique<St7789Display::Configuration>(
JC2432W328C_LCD_SPI_HOST,
JC2432W328C_LCD_PIN_CS,
JC2432W328C_LCD_PIN_DC,
JC2432W328C_LCD_HORIZONTAL_RESOLUTION,
JC2432W328C_LCD_VERTICAL_RESOLUTION,
touch,
false,
false,
false,
false,
JC2432W328C_LCD_DRAW_BUFFER_SIZE
);
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,18 +1,23 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include "Display.h"
#include <Tactility/hal/display/DisplayDevice.h>
#include <memory>
#include <driver/gpio.h>
#include <driver/spi_common.h>
// Display backlight (PWM)
#define JC2432W328C_LCD_PIN_BACKLIGHT GPIO_NUM_27
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
// Display
#define JC2432W328C_LCD_SPI_HOST SPI2_HOST
#define JC2432W328C_LCD_HORIZONTAL_RESOLUTION 240
#define JC2432W328C_LCD_VERTICAL_RESOLUTION 320
#define JC2432W328C_LCD_DRAW_BUFFER_HEIGHT (JC2432W328C_LCD_VERTICAL_RESOLUTION / 10)
#define JC2432W328C_LCD_DRAW_BUFFER_SIZE (JC2432W328C_LCD_HORIZONTAL_RESOLUTION * JC2432W328C_LCD_DRAW_BUFFER_HEIGHT)
#define JC2432W328C_LCD_PIN_CS GPIO_NUM_15
#define JC2432W328C_LCD_PIN_DC GPIO_NUM_2
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -1,6 +1,6 @@
#pragma once
#include "Tactility/hal/sdcard/SdCardDevice.h"
#include <Tactility/hal/sdcard/SdCardDevice.h>
using tt::hal::sdcard::SdCardDevice;

View File

@ -1,12 +1,10 @@
#include "PwmBacklight.h"
#include "Tactility/lvgl/LvglSync.h"
#include "devices/Display.h"
#include "devices/SdCard.h"
#include <Tactility/lvgl/LvglSync.h>
#include <Tactility/hal/Configuration.h>
#define CROWPANEL_SPI_TRANSFER_SIZE_LIMIT (CROWPANEL_LCD_HORIZONTAL_RESOLUTION * CROWPANEL_LCD_SPI_TRANSFER_HEIGHT * (LV_COLOR_DEPTH / 8))
using namespace tt::hal;
static bool initBoot() {
@ -60,7 +58,7 @@ extern const Configuration crowpanel_advance_28 = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = CROWPANEL_SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -8,8 +8,8 @@ static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Ft5x06Touch::Configuration>(
I2C_NUM_0,
240,
320,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
false,
false,
false
@ -19,23 +19,28 @@ static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC
};
auto configuration = std::make_unique<St7789Display::Configuration>(
CROWPANEL_LCD_SPI_HOST,
CROWPANEL_LCD_PIN_CS,
CROWPANEL_LCD_PIN_DC,
240,
320,
touch,
false,
false,
false,
true
);
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -2,11 +2,16 @@
#include <Tactility/hal/display/DisplayDevice.h>
#define CROWPANEL_LCD_SPI_HOST SPI2_HOST
#define CROWPANEL_LCD_PIN_CS GPIO_NUM_40
#define CROWPANEL_LCD_PIN_DC GPIO_NUM_41 // RS
#define CROWPANEL_LCD_HORIZONTAL_RESOLUTION 320
#define CROWPANEL_LCD_VERTICAL_RESOLUTION 240
#define CROWPANEL_LCD_SPI_TRANSFER_HEIGHT (CROWPANEL_LCD_VERTICAL_RESOLUTION / 10)
#include <driver/gpio.h>
#include <driver/spi_common.h>
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_40;
constexpr auto LCD_PIN_DC = GPIO_NUM_41; // RS
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -6,8 +6,6 @@
#include "devices/Sdcard.h"
#include "devices/TdeckKeyboard.h"
#define TDECK_SPI_TRANSFER_SIZE_LIMIT (320 * 240 * (LV_COLOR_DEPTH / 8))
bool initBoot();
using namespace tt::hal;
@ -75,7 +73,7 @@ extern const Configuration lilygo_tdeck = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = TDECK_SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -4,13 +4,6 @@
#include <PwmBacklight.h>
#include <St7789Display.h>
#define TDECK_LCD_SPI_HOST SPI2_HOST
#define TDECK_LCD_PIN_CS GPIO_NUM_12
#define TDECK_LCD_PIN_DC GPIO_NUM_11 // RS
#define TDECK_LCD_HORIZONTAL_RESOLUTION 320
#define TDECK_LCD_VERTICAL_RESOLUTION 240
#define TDECK_LCD_SPI_TRANSFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Gt911Touch::Configuration>(
@ -26,23 +19,28 @@ static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
St7789Display::Configuration panel_configuration = {
.horizontalResolution = 320,
.verticalResolution = 240,
.gapX = 0,
.gapY = 0,
.swapXY = true,
.mirrorX = true,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC
};
auto configuration = std::make_unique<St7789Display::Configuration>(
TDECK_LCD_SPI_HOST,
TDECK_LCD_PIN_CS,
TDECK_LCD_PIN_DC,
320,
240,
touch,
true,
true,
false,
true
);
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,5 +1,16 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_12;
constexpr auto LCD_PIN_DC = GPIO_NUM_11; // RS
constexpr auto LCD_HORIZONTAL_RESOLUTION = 320;
constexpr auto LCD_VERTICAL_RESOLUTION = 240;
constexpr auto LCD_BUFFER_HEIGHT = (LCD_VERTICAL_RESOLUTION / 3);
constexpr auto LCD_BUFFER_SIZE = (LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT);
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -9,8 +9,6 @@
#include <lvgl.h>
#include <Tactility/lvgl/LvglSync.h>
#define SPI_TRANSFER_SIZE_LIMIT (LCD_DRAW_BUFFER_SIZE * LV_COLOR_DEPTH / 8)
using namespace tt::hal;
static DeviceVector createDevices() {
@ -62,7 +60,7 @@ extern const Configuration m5stack_cardputer = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -4,25 +4,28 @@
#include <St7789Display.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto configuration = std::make_unique<St7789Display::Configuration>(
LCD_SPI_HOST,
LCD_PIN_CS,
LCD_PIN_DC,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
nullptr,
true,
true,
false,
true,
0,
53, // Should be 52 according to https://github.com/m5stack/M5GFX/blob/master/src/M5GFX.cpp but this leaves a gap at the bottom
40
);
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 53, // Should be 52 according to https://github.com/m5stack/M5GFX/blob/master/src/M5GFX.cpp but this leaves a gap at the bottom
.gapY = 40,
.swapXY = true,
.mirrorX = true,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = nullptr,
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = LCD_PIN_RESET
};
configuration->resetPin = LCD_PIN_RESET;
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,15 +1,18 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include <Tactility/hal/display/DisplayDevice.h>
#include <memory>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#define LCD_SPI_HOST SPI2_HOST
#define LCD_PIN_CS GPIO_NUM_37
#define LCD_PIN_DC GPIO_NUM_34 // RS
#define LCD_PIN_RESET GPIO_NUM_33
#define LCD_HORIZONTAL_RESOLUTION 240
#define LCD_VERTICAL_RESOLUTION 135
#define LCD_DRAW_BUFFER_HEIGHT (LCD_VERTICAL_RESOLUTION / 10)
#define LCD_DRAW_BUFFER_SIZE (LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT)
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_37;
constexpr auto LCD_PIN_DC = GPIO_NUM_34; // RS
constexpr auto LCD_PIN_RESET = GPIO_NUM_33;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 135;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -5,15 +5,9 @@
#include <Tactility/lvgl/LvglSync.h>
#define SPI_TRANSFER_SIZE_LIMIT (LCD_DRAW_BUFFER_SIZE * LV_COLOR_DEPTH / 8)
using namespace tt::hal;
constexpr auto* TAG = "StickCPlus";
bool initBoot() {
TT_LOG_I(TAG, "initBoot");
// CH552 applies 4 V to GPIO 0, which reduces Wi-Fi sensitivity
// Setting output to high adds a bias of 3.3 V and suppresses over-voltage:
gpio::configure(0, gpio::Mode::Output, false, false);
@ -85,7 +79,7 @@ extern const Configuration m5stack_stickc_plus = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -38,26 +38,28 @@ static void setBrightness(uint8_t brightness) {
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto configuration = std::make_unique<St7789Display::Configuration>(
LCD_SPI_HOST,
LCD_PIN_CS,
LCD_PIN_DC,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
nullptr,
false,
false,
false,
true,
LCD_DRAW_BUFFER_SIZE,
52,
40
);
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 52,
.gapY = 40,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = nullptr,
.backlightDutyFunction = setBrightness,
.resetPin = LCD_PIN_RESET
};
configuration->pixelClockFrequency = 40'000'000;
configuration->resetPin = LCD_PIN_RESET;
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
configuration->backlightDutyFunction = setBrightness;
const auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,15 +1,18 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include <Tactility/hal/display/DisplayDevice.h>
#include <memory>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#define LCD_SPI_HOST SPI2_HOST
#define LCD_PIN_CS GPIO_NUM_5
#define LCD_PIN_DC GPIO_NUM_23
#define LCD_PIN_RESET GPIO_NUM_18
#define LCD_HORIZONTAL_RESOLUTION 135
#define LCD_VERTICAL_RESOLUTION 240
#define LCD_DRAW_BUFFER_HEIGHT (LCD_VERTICAL_RESOLUTION / 3)
#define LCD_DRAW_BUFFER_SIZE (LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT)
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_5;
constexpr auto LCD_PIN_DC = GPIO_NUM_23;
constexpr auto LCD_PIN_RESET = GPIO_NUM_18;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 135;
constexpr auto LCD_VERTICAL_RESOLUTION = 240;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 3;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -5,15 +5,9 @@
#include <PwmBacklight.h>
#include <Tactility/lvgl/LvglSync.h>
#define SPI_TRANSFER_SIZE_LIMIT (LCD_DRAW_BUFFER_SIZE * LV_COLOR_DEPTH / 8)
using namespace tt::hal;
constexpr auto* TAG = "StickCPlus2";
bool initBoot() {
TT_LOG_I(TAG, "initBoot");
// CH552 applies 4 V to GPIO 0, which reduces Wi-Fi sensitivity
// Setting output to high adds a bias of 3.3 V and suppresses over-voltage:
gpio::configure(0, gpio::Mode::Output, false, false);
@ -87,7 +81,7 @@ extern const Configuration m5stack_stickc_plus2 = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = SPI_TRANSFER_SIZE_LIMIT,
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -4,26 +4,28 @@
#include <St7789Display.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto configuration = std::make_unique<St7789Display::Configuration>(
LCD_SPI_HOST,
LCD_PIN_CS,
LCD_PIN_DC,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
nullptr,
false,
false,
false,
true,
LCD_DRAW_BUFFER_SIZE,
52,
40
);
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 52,
.gapY = 40,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = nullptr,
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = LCD_PIN_RESET
};
configuration->pixelClockFrequency = 40'000'000;
configuration->resetPin = LCD_PIN_RESET;
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
const auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -2,14 +2,17 @@
#include "Tactility/hal/display/DisplayDevice.h"
#include <memory>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#define LCD_SPI_HOST SPI2_HOST
#define LCD_PIN_CS GPIO_NUM_5
#define LCD_PIN_DC GPIO_NUM_14
#define LCD_PIN_RESET GPIO_NUM_12
#define LCD_HORIZONTAL_RESOLUTION 135
#define LCD_VERTICAL_RESOLUTION 240
#define LCD_DRAW_BUFFER_HEIGHT (LCD_VERTICAL_RESOLUTION / 3)
#define LCD_DRAW_BUFFER_SIZE (LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT)
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_5;
constexpr auto LCD_PIN_DC = GPIO_NUM_14;
constexpr auto LCD_PIN_RESET = GPIO_NUM_12;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 135;
constexpr auto LCD_VERTICAL_RESOLUTION = 240;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 3;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -58,7 +58,7 @@ extern const Configuration waveshare_s3_lcd_13 = {
.data6_io_num = GPIO_NUM_NC,
.data7_io_num = GPIO_NUM_NC,
.data_io_default_level = false,
.max_transfer_sz = ((240 * (240 / 10)) * LV_COLOR_DEPTH / 8),
.max_transfer_sz = LCD_SPI_TRANSFER_SIZE_LIMIT,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0

View File

@ -4,24 +4,28 @@
#include <St7789Display.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = nullptr,
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_42
};
auto configuration = std::make_unique<St7789Display::Configuration>(
SPI2_HOST,
GPIO_NUM_39,
GPIO_NUM_38,
240,
240,
nullptr,
false,
false,
false,
true
);
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = SPI2_HOST,
.csPin = GPIO_NUM_39,
.dcPin = GPIO_NUM_38,
.pixelClockFrequency = 80'000'000,
.transactionQueueDepth = 10
});
configuration->resetPin = GPIO_NUM_42;
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7789Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}

View File

@ -1,5 +1,11 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
#include <Tactility/hal/display/DisplayDevice.h>
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 240;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 3;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;

View File

@ -1,104 +0,0 @@
#!/bin/sh
function build() {
Buildscripts/build.sh $1
}
function release() {
Buildscripts/release.sh $1
}
function releaseSdk() {
Buildscripts/release-sdk.sh $1
}
SECONDS=0
build elecrow-crowpanel-advance-28
release elecrow-crowpanel-advance-28
build elecrow-crowpanel-advance-35
release elecrow-crowpanel-advance-35
build elecrow-crowpanel-advance-50
release elecrow-crowpanel-advance-50
build elecrow-crowpanel-basic-28
release elecrow-crowpanel-basic-28
build elecrow-crowpanel-basic-35
release elecrow-crowpanel-basic-35
build elecrow-crowpanel-basic-50
release elecrow-crowpanel-basic-50
build lilygo-tdeck
release lilygo-tdeck
build lilygo-tdongle-s3
release lilygo-tdongle-s3
build lilygo-tlora-pager
release lilygo-tlora-pager
releaseSdk release/TactilitySDK-esp32s3
build cyd-2432s024c
release cyd-2432s024c
build cyd-2432s028r
release cyd-2432s028r
build cyd-2432s032c
release cyd-2432s032c
build cyd-4848s040c
release cyd-4848s040c
build cyd-8048s043c
release cyd-8048s043c
build cyd-e32r28t
release cyd-e32r28t
build cyd-jc2432w328c
release cyd-jc2432w328c
build cyd-jc8048w550c
release cyd-jc8048w550c
build m5stack-core2
release m5stack-core2
releaseSdk release/TactilitySDK-esp32
build m5stack-cardputer
release m5stack-cardputer
build m5stack-cores3
release m5stack-cores3
build m5stack-stickc-plus
release m5stack-stickc-plus
build m5stack-stickc-plus2
release m5stack-stickc-plus2
build waveshare-s3-touch-43
release waveshare-s3-touch-43
build waveshare-s3-touch-lcd-147
release waveshare-s3-touch-lcd-147
build waveshare-s3-touch-lcd-128
release waveshare-s3-touch-lcd-128
build waveshare-s3-lcd-13
release waveshare-s3-lcd-13
build unphone
release unphone
duration=$SECONDS
echo "Finished in $((duration / 60)) minutes and $((duration % 60)) seconds."

View File

@ -1,50 +0,0 @@
<#
.SYNOPSIS
Usage: build.ps1 [boardname]
Example: build.ps1 lilygo-tdeck
Description: Makes a clean build for the specified board.
#>
function EchoNewPhase {
param (
[string]$message
)
Write-Host "$message" -ForegroundColor Cyan
}
function FatalError {
param (
[string]$message
)
Write-Host "⚠️ $message" -ForegroundColor Red
exit 0
}
$sdkconfig_file = "sdkconfig.board.$($args[0])"
if ($args.Count -lt 1) {
FatalError "Must pass board name as first argument. (e.g. lilygo_tdeck)"
}
if (-Not (Test-Path $sdkconfig_file)) {
FatalError "Board not found: $sdkconfig_file"
}
EchoNewPhase "Cleaning build folder"
$BuildFolder = "build"
if (Test-Path $BuildFolder) {
Remove-Item -Path $BuildFolder -Recurse -Force
EchoNewPhase "Build folder deleted"
} else {
EchoNewPhase "Build folder doesn't exist."
}
EchoNewPhase "Building $sdkconfig_file"
Copy-Item -Path $sdkconfig_file -Destination "sdkconfig"
try {
& idf.py build
} catch {
FatalError "Failed to build esp32s3 SDK"
}

View File

@ -1,39 +0,0 @@
#!/bin/sh
#
# Usage: build.sh [boardname]
# Example: build.sh lilygo-tdeck
# Description: Makes a clean build for the specified board.
#
echoNewPhase() {
echo -e "⏳ \e[36m${1}\e[0m"
}
fatalError() {
echo -e "⚠️ \e[31m${1}\e[0m"
exit 0
}
sdkconfig_file="sdkconfig.board.${1}"
if [ $# -lt 1 ]; then
fatalError "Must pass board name as first argument. (e.g. lilygo_tdeck)"
fi
if [ ! -f $sdkconfig_file ]; then
fatalError "Board not found: ${sdkconfig_file}"
fi
echoNewPhase "Cleaning build folder"
#rm -rf build
echoNewPhase "Building $sdkconfig_file"
cp $sdkconfig_file sdkconfig
idf.py build
if [[ $? != 0 ]]; then
fatalError "Failed to build esp32s3 SDK"
fi

View File

@ -1,79 +0,0 @@
<#
.SYNOPSIS
Releases the current build labeled as a release for the specified board name.
.DESCRIPTION
Usage: .\release.ps1 [boardname]
Example: .\release.ps1 lilygo-tdeck
.PARAMETER board
The name of the board to release.
#>
function EchoNewPhase {
param(
[string]$Message
)
Write-Host "$message" -ForegroundColor Cyan
}
function FatalError {
param(
[string]$Message
)
Write-Host "⚠️ $message" -ForegroundColor Red
exit 0
}
function Release-Symbols {
param(
[string]$TargetPath
)
EchoNewPhase "Making symbols release at '$TargetPath'"
New-Item -ItemType Directory -Path $TargetPath -Force | Out-Null
Copy-Item -Path "build\*.elf" -Destination $TargetPath -Force
}
function Release-Build {
param(
[string]$TargetPath
)
EchoNewPhase "Making release at '$TargetPath'"
$binPath = Join-Path $TargetPath "Binaries"
$partitionTablePath = Join-Path $binPath "partition_table"
$bootloaderPath = Join-Path $binPath "bootloader"
New-Item -ItemType Directory -Path $binPath -Force | Out-Null
New-Item -ItemType Directory -Path $partitionTablePath -Force | Out-Null
New-Item -ItemType Directory -Path $bootloaderPath -Force | Out-Null
Copy-Item -Path "build\*.bin" -Destination $binPath -Force
Copy-Item -Path "build\bootloader\*.bin" -Destination $bootloaderPath -Force
Copy-Item -Path "build\partition_table\*.bin" -Destination $partitionTablePath -Force
Copy-Item -Path "build\flash_args" -Destination $binPath -Force
Copy-Item -Path "build\flasher_args.json" -Destination $binPath -Force
Copy-Item -Path "Buildscripts\Flashing\*" -Destination $TargetPath -Force
}
# Script start
$releasePath = "release"
$sdkconfig_file = "sdkconfig.board.$($args[0])"
$board = "$($args[0])"
if ($args.Count -lt 1) {
FatalError "Must pass board name as first argument. (e.g. lilygo_tdeck)"
}
if (-not (Test-Path $sdkconfig_file)) {
FatalError "Board not found: $sdkconfig_file"
}
$targetReleasePath = Join-Path $releasePath "Tactility-$board"
$targetSymbolsPath = Join-Path $releasePath "Tactility-$board-symbols"
Release-Build $targetReleasePath
Release-Symbols $targetSymbolsPath

View File

@ -1,7 +0,0 @@
#!/bin/sh
cmake -S ./ -B build-sim
cmake --build build-sim --target build-tests -j 14
build-sim/Tests/TactilityCore/TactilityCoreTests --exit
build-sim/Tests/Tactility/TactilityTests --exit

View File

@ -3,6 +3,7 @@
## Before release
- Make better esp_lcd driver (and test all devices)
- AppInstall.cpp fails to untar large files on Cardputer (EFF large word list doesn't fit in memory). Make a buffered reader & writer.
## Higher Priority

View File

@ -0,0 +1,226 @@
#include "EspLcdDisplayV2.h"
#include "EspLcdDisplayDriver.h"
#include <assert.h>
#include <esp_lvgl_port_disp.h>
#include <Tactility/Check.h>
#include <Tactility/LogEsp.h>
#include <Tactility/hal/touch/TouchDevice.h>
constexpr auto* TAG = "EspLcdDispV2";
inline unsigned int getBufferSize(const std::shared_ptr<EspLcdConfiguration>& configuration) {
if (configuration->bufferSize != DEFAULT_BUFFER_SIZE) {
return configuration->bufferSize;
} else {
return configuration->horizontalResolution * (configuration->verticalResolution / 10);
}
}
EspLcdDisplayV2::~EspLcdDisplayV2() {
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
tt_crash("DisplayDriver is still in use. This will cause memory access violations.");
}
}
bool EspLcdDisplayV2::applyConfiguration() const {
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_invert_color(panelHandle, configuration->invertColor) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set panel to invert");
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;
}
bool EspLcdDisplayV2::start() {
if (!createIoHandle(ioHandle)) {
TT_LOG_E(TAG, "Failed to create IO handle");
return false;
}
esp_lcd_panel_dev_config_t panel_config = createPanelConfig(configuration, configuration->resetPin);
if (!createPanelHandle(ioHandle, panel_config, panelHandle)) {
TT_LOG_E(TAG, "Failed to create panel handle");
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
return false;
}
if (!applyConfiguration()) {
esp_lcd_panel_del(panelHandle);
panelHandle = nullptr;
esp_lcd_panel_io_del(ioHandle);
ioHandle = nullptr;
return false;
}
return true;
}
bool EspLcdDisplayV2::stop() {
if (lvglDisplay != nullptr) {
stopLvgl();
lvglDisplay = nullptr;
}
if (panelHandle != nullptr && esp_lcd_panel_del(panelHandle) != ESP_OK) {
return false;
}
if (ioHandle != nullptr && esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
return false;
}
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
TT_LOG_W(TAG, "DisplayDriver is still in use.");
}
return true;
}
bool EspLcdDisplayV2::startLvgl() {
assert(lvglDisplay == nullptr);
if (displayDriver != nullptr && displayDriver.use_count() > 1) {
TT_LOG_W(TAG, "DisplayDriver is still in use.");
}
auto lvgl_port_config = getLvglPortDisplayConfig(configuration, ioHandle, panelHandle);
if (isRgbPanel()) {
auto rgb_config = getLvglPortDisplayRgbConfig(ioHandle, panelHandle);
lvglDisplay = lvgl_port_add_disp_rgb(&lvgl_port_config , &rgb_config);
} else {
lvglDisplay = lvgl_port_add_disp(&lvgl_port_config );
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr && touch_device->supportsLvgl()) {
touch_device->startLvgl(lvglDisplay);
}
return lvglDisplay != nullptr;
}
bool EspLcdDisplayV2::stopLvgl() {
if (lvglDisplay == nullptr) {
return false;
}
auto touch_device = getTouchDevice();
if (touch_device != nullptr) {
touch_device->stopLvgl();
}
lvgl_port_remove_disp(lvglDisplay);
lvglDisplay = nullptr;
return true;
}
lvgl_port_display_cfg_t EspLcdDisplayV2::getLvglPortDisplayConfig(std::shared_ptr<EspLcdConfiguration> configuration, 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 = getBufferSize(configuration),
.double_buffer = false,
.trans_size = 0,
.hres = configuration->horizontalResolution,
.vres = configuration->verticalResolution,
.monochrome = configuration->monochrome,
.rotation = {
.swap_xy = configuration->swapXY,
.mirror_x = configuration->mirrorX,
.mirror_y = configuration->mirrorY,
},
.color_format = configuration->lvglColorFormat,
.flags = {
.buff_dma = 1,
.buff_spiram = 0,
.sw_rotate = 0,
.swap_bytes = configuration->lvglSwapBytes,
.full_refresh = 0,
.direct_mode = 0
}
};
}
std::shared_ptr<tt::hal::display::DisplayDriver> EspLcdDisplayV2::getDisplayDriver() {
assert(lvglDisplay == nullptr); // Still attached to LVGL context. Call stopLvgl() first.
if (displayDriver == nullptr) {
auto lvgl_port_config = getLvglPortDisplayConfig(configuration, ioHandle, panelHandle);
auto panel_config = createPanelConfig(configuration, GPIO_NUM_NC);
tt::hal::display::ColorFormat color_format;
if (lvgl_port_config.color_format == LV_COLOR_FORMAT_I1) {
color_format = tt::hal::display::ColorFormat::Monochrome;
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB565) {
if (panel_config.rgb_ele_order == LCD_RGB_ELEMENT_ORDER_RGB) {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::RGB565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::RGB565;
}
} else {
if (lvgl_port_config.flags.swap_bytes) {
color_format = tt::hal::display::ColorFormat::BGR565Swapped;
} else {
color_format = tt::hal::display::ColorFormat::BGR565;
}
}
} else if (lvgl_port_config.color_format == LV_COLOR_FORMAT_RGB888) {
color_format = tt::hal::display::ColorFormat::RGB888;
} else {
tt_crash("unsupported driver");
}
displayDriver = std::make_shared<EspLcdDisplayDriver>(
panelHandle,
lock,
lvgl_port_config.hres,
lvgl_port_config.vres,
color_format
);
}
return displayDriver;
}

View File

@ -0,0 +1,111 @@
#pragma once
#include <esp_lcd_panel_dev.h>
#include <Tactility/Check.h>
#include <Tactility/Lock.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <esp_lcd_types.h>
#include <esp_lvgl_port_disp.h>
constexpr auto DEFAULT_BUFFER_SIZE = 0;
struct EspLcdConfiguration {
unsigned int horizontalResolution;
unsigned int verticalResolution;
int gapX;
int gapY;
bool monochrome;
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
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> _Nullable backlightDutyFunction;
gpio_num_t resetPin;
lv_color_format_t lvglColorFormat;
bool lvglSwapBytes;
};
class EspLcdDisplayV2 : public tt::hal::display::DisplayDevice {
esp_lcd_panel_io_handle_t _Nullable ioHandle = nullptr;
esp_lcd_panel_handle_t _Nullable panelHandle = nullptr;
lv_display_t* _Nullable lvglDisplay = nullptr;
std::shared_ptr<tt::hal::display::DisplayDriver> _Nullable displayDriver;
std::shared_ptr<tt::Lock> lock;
std::shared_ptr<EspLcdConfiguration> configuration;
bool applyConfiguration() const;
lvgl_port_display_cfg_t getLvglPortDisplayConfig(std::shared_ptr<EspLcdConfiguration> configuration, esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle);
protected:
virtual bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) = 0;
virtual esp_lcd_panel_dev_config_t createPanelConfig(std::shared_ptr<EspLcdConfiguration> espLcdConfiguration, gpio_num_t resetPin) = 0;
virtual bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) = 0;
virtual bool isRgbPanel() const { return false; }
virtual lvgl_port_display_rgb_cfg_t getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) { tt_crash("Not supported"); }
// Used for sending commands such as setting curves
esp_lcd_panel_io_handle_t getIoHandle() const { return ioHandle; }
public:
EspLcdDisplayV2(const std::shared_ptr<EspLcdConfiguration>& configuration, const std::shared_ptr<tt::Lock>& lock) :
lock(lock),
configuration(configuration)
{
assert(configuration != nullptr);
assert(lock != nullptr);
}
~EspLcdDisplayV2() override;
std::shared_ptr<tt::Lock> getLock() const { return lock; }
bool start() final;
bool stop() final;
// region LVGL
bool supportsLvgl() const final { return true; }
bool startLvgl() final;
bool stopLvgl() final;
lv_display_t* _Nullable getLvglDisplay() const final { return lvglDisplay; }
// endregion
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable getTouchDevice() override { return configuration->touch; }
// region Backlight
void setBacklightDuty(uint8_t backlightDuty) override {
if (configuration->backlightDutyFunction != nullptr) {
configuration->backlightDutyFunction(backlightDuty);
}
}
bool supportsBacklightDuty() const override { return configuration->backlightDutyFunction != nullptr; }
// endregion
// region DisplayDriver
bool supportsDisplayDriver() const override { return true; }
/** @return a NativeDisplay instance if this device supports it */
std::shared_ptr<tt::hal::display::DisplayDriver> _Nullable getDisplayDriver() final;
// endregion
};

View File

@ -0,0 +1,70 @@
#include "EspLcdSpiDisplay.h"
#include <esp_lcd_panel_commands.h>
#include <Tactility/LogEsp.h>
constexpr auto* TAG = "EspLcdSpiDsp";
bool EspLcdSpiDisplay::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
TT_LOG_I(TAG, "createIoHandle");
const esp_lcd_panel_io_spi_config_t panel_io_config = {
.cs_gpio_num = spiConfiguration->csPin,
.dc_gpio_num = spiConfiguration->dcPin,
.spi_mode = 0,
.pclk_hz = spiConfiguration->pixelClockFrequency,
.trans_queue_depth = spiConfiguration->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(spiConfiguration->spiHostDevice, &panel_io_config, &outHandle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to create panel");
return false;
}
return true;
}
void EspLcdSpiDisplay::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");
}
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "EspLcdDisplayV2.h"
#include <Tactility/hal/spi/Spi.h>
#include <esp_lcd_io_spi.h>
#include <esp_lcd_types.h>
/**
* Adds IO implementations on top of EspLcdDisplayV2
* @warning This is an abstract class. You need to extend it to use it.
*/
class EspLcdSpiDisplay : public EspLcdDisplayV2 {
public:
struct SpiConfiguration {
spi_host_device_t spiHostDevice;
gpio_num_t csPin;
gpio_num_t dcPin;
unsigned int pixelClockFrequency = 80'000'000; // Hertz
size_t transactionQueueDepth = 10;
};
explicit EspLcdSpiDisplay(const std::shared_ptr<EspLcdConfiguration>& configuration, const std::shared_ptr<SpiConfiguration> spiConfiguration, int gammaCurveCount) :
EspLcdDisplayV2(configuration, tt::hal::spi::getLock(spiConfiguration->spiHostDevice)),
spiConfiguration(spiConfiguration),
gammaCurveCount(gammaCurveCount)
{}
private:
std::shared_ptr<SpiConfiguration> spiConfiguration;
int gammaCurveCount;
protected:
bool createIoHandle(esp_lcd_panel_io_handle_t& ioHandle) override;
// region Gamma
void setGammaCurve(uint8_t index) override;
uint8_t getGammaCurveCount() const override { return gammaCurveCount; }
// endregion
};

View File

@ -1,53 +1,30 @@
#include "St7789Display.h"
#include <Tactility/Log.h>
#include <esp_lcd_panel_commands.h>
#include <esp_lcd_panel_dev.h>
#include <esp_lcd_panel_st7789.h>
#include <esp_lvgl_port.h>
constexpr auto TAG = "ST7789";
bool St7789Display::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;
std::shared_ptr<EspLcdConfiguration> St7789Display::createEspLcdConfiguration(const Configuration& configuration) {
return std::make_shared<EspLcdConfiguration>(EspLcdConfiguration {
.horizontalResolution = configuration.horizontalResolution,
.verticalResolution = configuration.verticalResolution,
.gapX = configuration.gapX,
.gapY = configuration.gapY,
.monochrome = false,
.swapXY = configuration.swapXY,
.mirrorX = configuration.mirrorX,
.mirrorY = configuration.mirrorY,
.invertColor = configuration.invertColor,
.bufferSize = configuration.bufferSize,
.touch = configuration.touch,
.backlightDutyFunction = configuration.backlightDutyFunction,
.resetPin = configuration.resetPin,
.lvglColorFormat = LV_COLOR_FORMAT_RGB565,
.lvglSwapBytes = false
});
}
bool St7789Display::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,
esp_lcd_panel_dev_config_t St7789Display::createPanelConfig(std::shared_ptr<EspLcdConfiguration> espLcdConfiguration, gpio_num_t resetPin) {
return {
.reset_gpio_num = resetPin,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
.bits_per_pixel = 16,
@ -56,115 +33,8 @@ bool St7789Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lc
},
.vendor_config = nullptr
};
if (esp_lcd_new_panel_st7789(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 St7789Display::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 = false,
.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 St7789Display::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");
}
bool St7789Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) {
return esp_lcd_new_panel_st7789(ioHandle, &panelConfig, &panelHandle) == ESP_OK;
}

View File

@ -2,113 +2,57 @@
#include "Tactility/hal/spi/Spi.h"
#include <EspLcdDisplay.h>
#include <EspLcdSpiDisplay.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 St7789Display final : public EspLcdDisplay {
class St7789Display final : public EspLcdSpiDisplay {
std::shared_ptr<tt::Lock> lock;
public:
class Configuration {
public:
Configuration(
spi_host_device_t spiHostDevice,
gpio_num_t csPin,
gpio_num_t dcPin,
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),
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 = 80'000'000; // Hertz
size_t transactionQueueDepth = 10;
/** Minimal set of overrides for EspLcdConfiguration */
struct Configuration {
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
bool swapXY;
bool mirrorX;
bool mirrorY;
bool invertColor;
uint32_t bufferSize; // Pixel count, not byte count. Set to 0 for default (1/10th of display size)
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> _Nullable backlightDutyFunction = nullptr;
std::function<void(uint8_t)> _Nullable backlightDutyFunction;
gpio_num_t resetPin;
};
private:
std::unique_ptr<Configuration> configuration;
static std::shared_ptr<EspLcdConfiguration> createEspLcdConfiguration(const Configuration& configuration);
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, 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;
bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, const esp_lcd_panel_dev_config_t& panelConfig, esp_lcd_panel_handle_t& panelHandle) override;
public:
explicit St7789Display(std::unique_ptr<Configuration> inConfiguration) :
EspLcdDisplay(tt::hal::spi::getLock(inConfiguration->spiHostDevice)),
configuration(std::move(inConfiguration)
) {
assert(configuration != nullptr);
assert(getLock() != nullptr);
explicit St7789Display(const Configuration& configuration, const std::shared_ptr<SpiConfiguration>& spiConfiguration) :
EspLcdSpiDisplay(
createEspLcdConfiguration(configuration),
spiConfiguration,
4
)
{
}
std::string getName() const override { return "ST7789"; }
std::string getDescription() const override { return "ST7789 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();

View File

@ -42,7 +42,10 @@ bool stop(spi_host_device_t device);
/** @return true if communications were started successfully */
bool isStarted(spi_host_device_t device);
/** @return the lock that represents the specified device. Can be used with third party SPI implementations or native API calls (e.g. ESP-IDF). */
/**
* Return the lock for the specified SPI device. Never returns nullptr.
* @return the lock that represents the specified device. Can be used with third party SPI implementations or native API calls (e.g. ESP-IDF).
*/
std::shared_ptr<Lock> getLock(spi_host_device_t device);
} // namespace tt::hal::spi

View File

@ -1,9 +1,8 @@
#pragma once
#include <Tactility/Tactility.h>
namespace tt {
void prepareFileSystems();
void registerApps();
}

View File

@ -88,8 +88,8 @@ bool Preferences::hasString(const std::string& key) const {
void Preferences::putBool(const std::string& key, bool value) {
nvs_handle_t handle;
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_u8(handle, key.c_str(), (uint8_t)value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
if (nvs_set_u8(handle, key.c_str(), value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
}
@ -103,7 +103,7 @@ void Preferences::putInt32(const std::string& key, int32_t value) {
nvs_handle_t handle;
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_i32(handle, key.c_str(), value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
TT_LOG_E(TAG, "Failed to set %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
}
@ -117,7 +117,7 @@ void Preferences::putInt64(const std::string& key, int64_t value) {
nvs_handle_t handle;
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
if (nvs_set_i64(handle, key.c_str(), value) != ESP_OK) {
TT_LOG_E(TAG, "Failed to write %s:%s", namespace_, key.c_str());
TT_LOG_E(TAG, "Failed to set %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
}
@ -130,8 +130,9 @@ void Preferences::putInt64(const std::string& key, int64_t value) {
void Preferences::putString(const std::string& key, const std::string& text) {
nvs_handle_t handle;
if (nvs_open(namespace_, NVS_READWRITE, &handle) == ESP_OK) {
nvs_set_str(handle, key.c_str(), text.c_str());
if (nvs_commit(handle) != ESP_OK) {
if (nvs_set_str(handle, key.c_str(), text.c_str()) != ESP_OK) {
TT_LOG_E(TAG, "Failed to set %s:%s", namespace_, key.c_str());
} else if (nvs_commit(handle) != ESP_OK) {
TT_LOG_E(TAG, "Failed to commit %s:%s", namespace_, key.c_str());
}
nvs_close(handle);

View File

@ -233,6 +233,38 @@ static void registerAndStartPrimaryServices() {
#endif
}
void createTempDirectory(const std::string& rootPath) {
auto temp_path = std::format("{}/tmp", rootPath);
if (!file::isDirectory(temp_path)) {
auto lock = file::getLock(rootPath)->asScopedLock();
if (lock.lock(1000 / portTICK_PERIOD_MS)) {
if (mkdir(temp_path.c_str(), 0777) == 0) {
TT_LOG_I(TAG, "Created %s", temp_path.c_str());
} else {
TT_LOG_E(TAG, "Failed to create %s", temp_path.c_str());
}
} else {
TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, rootPath.c_str());
}
} else {
TT_LOG_I(TAG, "Found existing %s", temp_path.c_str());
}
}
void prepareFileSystems() {
// Temporary directories for SD cards
auto sdcard_devices = hal::findDevices<hal::sdcard::SdCardDevice>(hal::Device::Type::SdCard);
for (const auto& sdcard : sdcard_devices) {
if (sdcard->isMounted()) {
createTempDirectory(sdcard->getMountPath());
}
}
// Temporary directory for /data
if (file::isDirectory(file::MOUNT_POINT_DATA)) {
createTempDirectory(file::MOUNT_POINT_DATA);
}
}
void registerApps() {
registerInternalApps();
auto data_apps_path = std::format("{}/apps", file::MOUNT_POINT_DATA);

View File

@ -100,11 +100,7 @@ class BootApp : public App {
// TODO: Support for multiple displays
TT_LOG_I(TAG, "Setup display");
setupDisplay(); // Set backlight
// This event will likely block as other systems are initialized
// e.g. Wi-Fi reads AP configs from SD card
TT_LOG_I(TAG, "Publish event");
kernel::publishSystemEvent(kernel::SystemEvent::BootSplash);
prepareFileSystems();
if (!setupUsbBootMode()) {
TT_LOG_I(TAG, "initFromBootApp");
@ -114,6 +110,11 @@ class BootApp : public App {
startNextApp();
}
// This event will likely block as other systems are initialized
// e.g. Wi-Fi reads AP configs from SD card
TT_LOG_I(TAG, "Publish event");
kernel::publishSystemEvent(kernel::SystemEvent::BootSplash);
return 0;
}

View File

@ -10,18 +10,19 @@ extern lv_obj_t* __real_lv_list_create(lv_obj_t* parent);
extern lv_obj_t* __real_lv_list_add_button(lv_obj_t* list, const void* icon, const char* txt);
lv_obj_t* __wrap_lv_list_create(lv_obj_t* parent) {
auto list = __real_lv_list_create(parent);
auto* list = __real_lv_list_create(parent);
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
lv_obj_set_style_pad_row(list, 2, LV_STATE_DEFAULT);
lv_obj_set_style_pad_column(list, 2, LV_STATE_DEFAULT);
lv_obj_set_style_pad_all(list, 2, LV_STATE_DEFAULT);
}
return list;
}
lv_obj_t* __wrap_lv_list_add_button(lv_obj_t* list, const void* icon, const char* txt) {
auto button = __real_lv_list_add_button(list, icon, txt);
auto* button = __real_lv_list_add_button(list, icon, txt);
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
lv_obj_set_style_pad_ver(button, 2, LV_STATE_DEFAULT);