Compare commits

...

3 Commits

Author SHA1 Message Date
Ken Van Hoeylandt
ebf9a81395 Update CYD-E32R28T and fixed some minor issues 2025-09-06 14:59:41 +02:00
Ken Van Hoeylandt
c0ed8f0a44
Merge develop into main (#318)
- Disable `DisplayDriver` for `St7701Display` (on CYD 4848)
- Improve `GraphicsDemo`: check for feature capability and show alert dialog if there's an issue
- `DevelopmentService` installs to `/data` instead of `/sdcard`
- Fixed `tt_app_get_data_directory()` and `tt_app_get_data_directory_lvgl()` (C++ to C)
- `tt_kernel.h` now defines `MAX_TICKS`
- `tt_init.cpp` now exports `esp_log()` which is required since ESP-IDF 5.5
2025-09-06 14:44:41 +02:00
NellowTCS
a9b69010d8
CYD-E28R32T Implementation (#317)
- Add implementation for CYD-E28R28T. This implementation has the SD card working, using the same driver as the CYD-2432S028R.
- Edit .gitignore for some missing things.
- run chmod +x on some build scripts
- Make EspLcdDisplay's reference public for access from drivers (needed for driver St7789i8080)
> ```class EspLcdDisplay : public tt::hal::display::DisplayDevice {```
2025-09-06 13:52:46 +02:00
28 changed files with 326 additions and 28 deletions

View File

@ -27,6 +27,15 @@ jobs:
with:
board_id: cyd-2432s028r
arch: esp32
cyd-e32r28t:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Build"
uses: ./.github/actions/build-firmware
with:
board_id: cyd-e32r28t
arch: esp32
cyd-2432s032c:
runs-on: ubuntu-latest
steps:
@ -179,4 +188,4 @@ jobs:
uses: ./.github/actions/build-firmware
with:
board_id: waveshare-s3-touch-43
arch: esp32s3
arch: esp32s3

2
.gitignore vendored
View File

@ -7,6 +7,7 @@ build-sim/
cmake-build-*/
CMakeCache.txt
*.cbp
CMakeFiles
release/
@ -17,4 +18,5 @@ managed_components/
dependencies.lock
.vscode/
.gitpod.yml

View File

@ -25,4 +25,4 @@ else ()
add_definitions(-D_Nullable=)
add_definitions(-D_Nonnull=)
endif ()
endif ()

View File

@ -15,6 +15,8 @@ menu "Tactility App"
bool "CYD 2432S024C"
config TT_BOARD_CYD_2432S028R
bool "CYD 2432S028R"
config TT_BOARD_CYD_E32R28T
bool "CYD E32R28T"
config TT_BOARD_CYD_2432S032C
bool "CYD 2432S032C"
config TT_BOARD_CYD_8048S043C

View File

@ -17,6 +17,9 @@
#elif defined(CONFIG_TT_BOARD_CYD_2432S028R)
#include "CYD2432S028R.h"
#define TT_BOARD_HARDWARE &cyd_2432s028r_config
#elif defined(CONFIG_TT_BOARD_CYD_E32R28T)
#include "E32R28T.h"
#define TT_BOARD_HARDWARE &cyd_e32r28t_config
#elif defined(CONFIG_TT_BOARD_CYD_2432S032C)
#include "CYD2432S032C.h"
#define TT_BOARD_HARDWARE &cyd_2432S032c_config

View File

@ -28,4 +28,4 @@ void app_main() {
tt::run(config);
}
} // extern
} // extern

View File

@ -2,5 +2,5 @@
#include <Tactility/hal/Configuration.h>
// Resitive touch version of the 2.8" yellow board
// Resistive touch version of the 2.8" yellow board
extern const tt::hal::Configuration cyd_2432s028r_config;

View File

@ -32,4 +32,7 @@ public:
void setBacklightDuty(uint8_t backlightDuty) override;
bool supportsBacklightDuty() const override { return true; }
// TODO: Find out why it crashes
bool supportsDisplayDriver() const override { return false; }
};

View File

@ -0,0 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046SoftSPI PwmBacklight driver vfs fatfs
)

View File

@ -0,0 +1,73 @@
#include "E32R28T.h"
#include "devices/SdCard.h"
#include "devices/Display.h"
#include <Tactility/lvgl/LvglSync.h>
#include <PwmBacklight.h>
#define CYD_SPI_TRANSFER_SIZE_LIMIT (240 * 320 / 4 * 2)
static bool initBoot() {
return driver::pwmbacklight::init(CYD_BACKLIGHT_PIN);
}
static tt::hal::DeviceVector createDevices() {
return {
createDisplay(),
createSdCard()
};
}
const tt::hal::Configuration cyd_e32r28t_config = {
.initBoot = initBoot,
.createDevices = createDevices,
.i2c = {},
.spi = {
tt::hal::spi::Configuration {
.device = SPI2_HOST,
.dma = SPI_DMA_CH_AUTO,
.config = {
.mosi_io_num = GPIO_NUM_13,
.miso_io_num = GPIO_NUM_12,
.sclk_io_num = GPIO_NUM_14,
.quadwp_io_num = GPIO_NUM_NC,
.quadhd_io_num = GPIO_NUM_NC,
.data4_io_num = GPIO_NUM_NC,
.data5_io_num = GPIO_NUM_NC,
.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,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0
},
.initMode = tt::hal::spi::InitMode::ByTactility,
.isMutable = false,
.lock = tt::lvgl::getSyncLock()
},
tt::hal::spi::Configuration {
.device = SPI3_HOST,
.dma = SPI_DMA_CH_AUTO,
.config = {
.mosi_io_num = GPIO_NUM_23,
.miso_io_num = GPIO_NUM_19,
.sclk_io_num = GPIO_NUM_18,
.quadwp_io_num = GPIO_NUM_NC,
.quadhd_io_num = GPIO_NUM_NC,
.data4_io_num = GPIO_NUM_NC,
.data5_io_num = GPIO_NUM_NC,
.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,
.flags = 0,
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
.intr_flags = 0
},
.initMode = tt::hal::spi::InitMode::ByTactility,
.isMutable = false,
.lock = tt::lvgl::getSyncLock()
},
}
};

View File

@ -0,0 +1,6 @@
#pragma once
#include <Tactility/hal/Configuration.h>
// Resistive touch version of the waveshare 2.8" yellow board
extern const tt::hal::Configuration cyd_e32r28t_config;

View File

@ -0,0 +1,41 @@
#include "Display.h"
#include <Xpt2046SoftSpi.h>
#include <Ili934xDisplay.h>
#include <PwmBacklight.h>
#include <Tactility/hal/touch/TouchDevice.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto config = std::make_unique<Xpt2046SoftSpi::Configuration>(
CYD_TOUCH_MOSI_PIN,
CYD_TOUCH_MISO_PIN,
CYD_TOUCH_SCK_PIN,
CYD_TOUCH_CS_PIN,
CYD_DISPLAY_HORIZONTAL_RESOLUTION,
CYD_DISPLAY_VERTICAL_RESOLUTION,
false,
true,
false
);
return std::make_shared<Xpt2046SoftSpi>(std::move(config));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto configuration = std::make_unique<Ili934xDisplay::Configuration>(
CYD_DISPLAY_SPI_HOST,
CYD_DISPLAY_PIN_CS,
CYD_DISPLAY_PIN_DC,
CYD_DISPLAY_HORIZONTAL_RESOLUTION,
CYD_DISPLAY_VERTICAL_RESOLUTION,
createTouch(),
false,
true,
false,
false,
0,
LCD_RGB_ELEMENT_ORDER_BGR
);
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
return std::make_shared<Ili934xDisplay>(std::move(configuration));
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <memory>
// Display
#define CYD_DISPLAY_SPI_HOST SPI2_HOST
#define CYD_DISPLAY_PIN_CS GPIO_NUM_15
#define CYD_DISPLAY_PIN_DC GPIO_NUM_2
#define CYD_DISPLAY_HORIZONTAL_RESOLUTION 240
#define CYD_DISPLAY_VERTICAL_RESOLUTION 320
#define CYD_DISPLAY_DRAW_BUFFER_HEIGHT (CYD_DISPLAY_VERTICAL_RESOLUTION / 10)
#define CYD_DISPLAY_DRAW_BUFFER_SIZE (CYD_DISPLAY_HORIZONTAL_RESOLUTION * CYD_DISPLAY_DRAW_BUFFER_HEIGHT)
// 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
// Backlight
#define CYD_BACKLIGHT_PIN GPIO_NUM_21
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

View File

@ -0,0 +1,21 @@
#include "SdCard.h"
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
using tt::hal::sdcard::SpiSdCardDevice;
std::shared_ptr<SdCardDevice> createSdCard() {
auto configuration = std::make_unique<SpiSdCardDevice::Config>(
GPIO_NUM_5,
GPIO_NUM_NC,
GPIO_NUM_NC,
GPIO_NUM_NC,
SdCardDevice::MountBehaviour::AtBoot,
std::make_shared<tt::Mutex>(),
std::vector<gpio_num_t>(),
SPI3_HOST
);
return std::make_shared<SpiSdCardDevice>(
std::move(configuration)
);
}

View File

@ -0,0 +1,7 @@
#pragma once
#include <Tactility/hal/sdcard/SdCardDevice.h>
using tt::hal::sdcard::SdCardDevice;
std::shared_ptr<SdCardDevice> createSdCard();

0
Buildscripts/Flashing/flash.ps1 Normal file → Executable file
View File

View File

@ -24,7 +24,9 @@ function(INIT_TACTILITY_GLOBALS SDKCONFIG_FILE)
if (board_id STREQUAL "cyd-2432s024c")
set(TACTILITY_BOARD_PROJECT CYD-2432S024C)
elseif (board_id STREQUAL "cyd-2432s028r")
set(TACTILITY_BOARD_PROJECT CYD-2432S028R)
set(TACTILITY_BOARD_PROJECT CYD-2432S028R)
elseif (board_id STREQUAL "cyd-e32r28t")
set(TACTILITY_BOARD_PROJECT CYD-E32R28T)
elseif (board_id STREQUAL "cyd-2432s032c")
set(TACTILITY_BOARD_PROJECT CYD-2432S032C)
elseif (board_id STREQUAL "cyd-4848s040c")

0
Buildscripts/build.ps1 Normal file → Executable file
View File

0
Buildscripts/release.ps1 Normal file → Executable file
View File

View File

@ -5,14 +5,17 @@
- Fix Development service: when no SD card is present, the app fails to install. Consider installing to `/data`
Note: Change app install to "transfer file" functionality. We can have a proper install when we have app packaging.
Note: Consider installation path option in interface
- Update ILI934x to v2.0.1
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility.
- Make a URL handler. Use it for handling local files. Match file types with apps.
Create some kind of "intent" handler like on Android.
The intent can have an action (e.g. view), a URL and an optional bundle.
The manifest can provide the intent handler
- App packaging
- Bug: GraphicsDemo should check if display supports the DisplayDriver interface (and same for touch) and show an AlertDialog error if there's a problem
- Update ILI934x to v2.0.1
- App packaging
- Create an "app install paths" settings app to add/remove paths.
Scan these paths on startup.
Make the AppList use the scan results.
## Lower Priority

View File

@ -8,7 +8,7 @@
#include <esp_lvgl_port_disp.h>
#include <Tactility/Check.h>
class EspLcdDisplay : tt::hal::display::DisplayDevice {
class EspLcdDisplay : public tt::hal::display::DisplayDevice {
esp_lcd_panel_io_handle_t _Nullable ioHandle = nullptr;
esp_lcd_panel_handle_t _Nullable panelHandle = nullptr;
@ -56,7 +56,7 @@ public:
// endregion
// region NativeDisplay
// region DisplayDriver
bool supportsDisplayDriver() const override { return true; }

View File

@ -5,22 +5,55 @@
#include <esp_log.h>
#include <tt_app.h>
#include <tt_app_alertdialog.h>
#include <tt_lvgl.h>
constexpr auto TAG = "Main";
static void onCreate(AppHandle appHandle, void* data) {
/** Find a DisplayDevice that supports the DisplayDriver interface */
static bool findUsableDisplay(DeviceId& deviceId) {
uint16_t display_count = 0;
if (!tt_hal_device_find(DEVICE_TYPE_DISPLAY, &deviceId, &display_count, 1)) {
ESP_LOGE(TAG, "No display device found");
return false;
}
if (!tt_hal_display_driver_supported(deviceId)) {
ESP_LOGE(TAG, "Display doesn't support driver mode");
return false;
}
return true;
}
/** Find a TouchDevice that supports the TouchDriver interface */
static bool findUsableTouch(DeviceId& deviceId) {
uint16_t touch_count = 0;
if (!tt_hal_device_find(DEVICE_TYPE_TOUCH, &deviceId, &touch_count, 1)) {
ESP_LOGE(TAG, "No touch device found");
return false;
}
if (!tt_hal_touch_driver_supported(deviceId)) {
ESP_LOGE(TAG, "Touch doesn't support driver mode");
return false;
}
return true;
}
static void onCreate(AppHandle appHandle, void* data) {
DeviceId display_id;
if (!tt_hal_device_find(DEVICE_TYPE_DISPLAY, &display_id, &display_count, 1)) {
ESP_LOGI(TAG, "No display device found");
if (!findUsableDisplay(display_id)) {
tt_app_stop();
tt_app_alertdialog_start("Error", "The display doesn't support the required features.", nullptr, 0);
return;
}
uint16_t touch_count = 0;
DeviceId touch_id;
if (!tt_hal_device_find(DEVICE_TYPE_TOUCH, &touch_id, &touch_count, 1)) {
ESP_LOGI(TAG, "No touch device found");
if (!findUsableTouch(touch_id)) {
tt_app_stop();
tt_app_alertdialog_start("Error", "The touch driver doesn't support the required features.", nullptr, 0);
return;
}

View File

@ -251,7 +251,7 @@ esp_err_t DevelopmentService::handleAppInstall(httpd_req_t* request) {
content_left -= content_read;
// Write file
auto file_path = std::format("/sdcard/{}", filename_entry->second);
auto file_path = std::format("/data/{}", filename_entry->second);
auto* file = fopen(file_path.c_str(), "wb");
auto file_bytes_written = fwrite(buffer.get(), 1, file_size, file);
fclose(file);

View File

@ -29,7 +29,7 @@ bool tt_app_has_result(AppHandle handle);
* @param[out] buffer the output buffer (recommended size is 256 bytes)
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
*/
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t& size);
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t* size);
/** Get the path to the data directory of this app, with LVGL drive letter prefix applied.
* The recommended buffer size is 256 bytes.
@ -37,7 +37,7 @@ void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t& size
* @param[out] buffer the output buffer (recommended size is 256 bytes)
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
*/
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t& size);
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t* size);
/**
* Start an app by id.

View File

@ -8,6 +8,8 @@ extern "C" {
typedef unsigned long TickType;
#define MAX_TICKS INT32_MAX
/**
* Stall the current task for the specified amount of time.
* @param milliseconds the time in milliseconds to stall.

View File

@ -33,38 +33,40 @@ void tt_app_stop() {
tt::app::stop();
}
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t& size) {
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t* size) {
assert(buffer != nullptr);
assert(size > 0);
assert(size != nullptr);
assert(*size > 0);
auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
auto data_path = paths->getDataDirectory();
auto expected_length = data_path.length() + 1;
if (size < expected_length) {
if (*size < expected_length) {
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", size, expected_length);
size = 0;
*size = 0;
buffer[0] = 0;
return;
}
strcpy(buffer, data_path.c_str());
size = data_path.length();
*size = data_path.length();
}
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t& size) {
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t* size) {
assert(buffer != nullptr);
assert(size > 0);
assert(size != nullptr);
assert(*size > 0);
auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
auto data_path = paths->getDataDirectoryLvgl();
auto expected_length = data_path.length() + 1;
if (size < expected_length) {
if (*size < expected_length) {
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", size, expected_length);
size = 0;
*size = 0;
buffer[0] = 0;
return;
}
strcpy(buffer, data_path.c_str());
size = data_path.length();
*size = data_path.length();
}
}

View File

@ -105,6 +105,7 @@ const esp_elfsym elf_symbols[] {
ESP_ELFSYM_EXPORT(tolower),
ESP_ELFSYM_EXPORT(toupper),
// ESP-IDF
ESP_ELFSYM_EXPORT(esp_log),
ESP_ELFSYM_EXPORT(esp_log_write),
ESP_ELFSYM_EXPORT(esp_log_timestamp),
// Tactility

View File

@ -0,0 +1,56 @@
# Software defaults
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
CONFIG_LV_USE_FS_STDIO=y
CONFIG_LV_FS_STDIO_LETTER=65
CONFIG_LV_FS_STDIO_PATH=""
CONFIG_LV_FS_STDIO_CACHE_SIZE=4096
CONFIG_LV_USE_LODEPNG=y
CONFIG_LV_USE_BUILTIN_MALLOC=n
CONFIG_LV_USE_CLIB_MALLOC=y
CONFIG_LV_USE_MSGBOX=n
CONFIG_LV_USE_SPINNER=n
CONFIG_LV_USE_WIN=n
CONFIG_LV_USE_SNAPSHOT=y
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3
# Hardware: Main
CONFIG_TT_BOARD_CYD_E32R28T=y
CONFIG_TT_BOARD_NAME="CYD E32R28T"
CONFIG_TT_BOARD_ID="cyd-e32r28t"
CONFIG_IDF_TARGET="esp32"
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_FLASHMODE_QIO=y
# LVGL
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
CONFIG_LV_DPI_DEF=130 # Adjusted for 2.8" 240x320 (~130 DPI)
CONFIG_LVGL_BUFFER_WIDTH=240
CONFIG_LVGL_BUFFER_HEIGHT=40
CONFIG_LVGL_COLOR_DEPTH=16
# Drivers
CONFIG_DISPLAY_DRIVER_ILI9341=y
CONFIG_TOUCH_DRIVER_XPT2046=y
CONFIG_TOUCH_CALIBRATION=y
CONFIG_SD_CARD_ENABLE=y
# Fix for IRAM
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y