diff --git a/.github/workflows/build-firmware.yml b/.github/workflows/build-firmware.yml index cc1a7966..9db63343 100644 --- a/.github/workflows/build-firmware.yml +++ b/.github/workflows/build-firmware.yml @@ -45,6 +45,15 @@ jobs: with: board_id: elecrow-crowpanel-basic-28 arch: esp32 + elecrow-crowpanel-basic-35: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Build" + uses: ./.github/actions/build-firmware + with: + board_id: elecrow-crowpanel-basic-35 + arch: esp32 lilygo-tdeck: runs-on: ubuntu-latest steps: diff --git a/App/CMakeLists.txt b/App/CMakeLists.txt index c1f67917..f543f439 100644 --- a/App/CMakeLists.txt +++ b/App/CMakeLists.txt @@ -7,6 +7,7 @@ if (DEFINED ENV{ESP_IDF_VERSION}) list(APPEND BOARD_COMPONENTS CYD-2432S024C ElecrowCrowpanelBasic28 + ElecrowCrowpanelBasic35 M5stackCore2 ) endif() diff --git a/App/Source/Boards.h b/App/Source/Boards.h index da92fe94..6c023c66 100644 --- a/App/Source/Boards.h +++ b/App/Source/Boards.h @@ -19,6 +19,9 @@ #elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_28)) #define TT_BOARD_HARDWARE &crowpanel_basic_28 #include "CrowPanelBasic28.h" +#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_35)) +#define TT_BOARD_HARDWARE &crowpanel_basic_35 +#include "CrowPanelBasic35.h" #elif defined(CONFIG_TT_BOARD_M5STACK_CORE2) #include "M5stackCore2.h" #define TT_BOARD_HARDWARE &m5stack_core2 diff --git a/Boards/ElecrowCrowpanelBasic35/CMakeLists.txt b/Boards/ElecrowCrowpanelBasic35/CMakeLists.txt new file mode 100644 index 00000000..fd619a22 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/CMakeLists.txt @@ -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 ILI9488 XPT2046 PwmBacklight driver +) diff --git a/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.cpp b/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.cpp new file mode 100644 index 00000000..f70287e2 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.cpp @@ -0,0 +1,126 @@ +#include "PwmBacklight.h" +#include "Tactility/lvgl/LvglSync.h" +#include "hal/CrowPanelDisplay.h" +#include "hal/CrowPanelDisplayConstants.h" +#include "hal/CrowPanelSdCard.h" + +#include +#include + +#define CROWPANEL_SPI_TRANSFER_SIZE_LIMIT (CROWPANEL_LCD_HORIZONTAL_RESOLUTION * CROWPANEL_LCD_SPI_TRANSFER_HEIGHT * (LV_COLOR_DEPTH / 8)) + +using namespace tt::hal; + +bool initBoot() { + return driver::pwmbacklight::init(GPIO_NUM_27); +} + +extern const Configuration crowpanel_basic_35 = { + .initBoot = initBoot, + .createDisplay = createDisplay, + .sdcard = createSdCard(), + .power = getOrCreatePower, + .i2c = { + // There is only 1 (internal for touch, and also serves as "I2C-OUT" port) + // Note: You could repurpose 1 or more UART interfaces as I2C interfaces + i2c::Configuration { + .name = "Main", + .port = I2C_NUM_0, + .initMode = i2c::InitMode::ByTactility, + .canReinit = false, + .hasMutableConfiguration = false, + .config = (i2c_config_t) { + .mode = I2C_MODE_MASTER, + .sda_io_num = GPIO_NUM_22, + .scl_io_num = GPIO_NUM_21, + .sda_pullup_en = true, + .scl_pullup_en = true, + .master = { + .clk_speed = 400000 + }, + .clk_flags = 0 + } + } + }, + .spi { + // Display + spi::Configuration { + .device = SPI2_HOST, + .dma = SPI_DMA_DISABLED, + .config = { + .mosi_io_num = GPIO_NUM_13, + .miso_io_num = GPIO_NUM_33, + .sclk_io_num = GPIO_NUM_14, + .quadwp_io_num = GPIO_NUM_NC, + .quadhd_io_num = GPIO_NUM_NC, + .data4_io_num = 0, + .data5_io_num = 0, + .data6_io_num = 0, + .data7_io_num = 0, + .data_io_default_level = false, + .max_transfer_sz = CROWPANEL_SPI_TRANSFER_SIZE_LIMIT, + .flags = 0, + .isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO, + .intr_flags = 0 + }, + .initMode = spi::InitMode::ByTactility, + .canReinit = false, + .hasMutableConfiguration = false, + .lock = tt::lvgl::getSyncLock() // esp_lvgl_port owns the lock for the display + }, + // SD card + 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 = 0, + .data5_io_num = 0, + .data6_io_num = 0, + .data7_io_num = 0, + .data_io_default_level = false, + .max_transfer_sz = 32768, + .flags = 0, + .isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO, + .intr_flags = 0 + }, + .initMode = spi::InitMode::ByTactility, + .canReinit = false, + .hasMutableConfiguration = false, + .lock = nullptr // No custom lock needed + } + }, + .uart { + // "UART1" + uart::Configuration { + .port = UART_NUM_1, + .initMode = uart::InitMode::Disabled, // Manual init + .canReinit = true, + .hasMutableConfiguration = false, + .rxPin = GPIO_NUM_3, + .txPin = GPIO_NUM_1, + .rtsPin = GPIO_NUM_NC, + .ctsPin = GPIO_NUM_NC, + .rxBufferSize = 1024, + .txBufferSize = 1024, + .config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 0, + .source_clk = UART_SCLK_DEFAULT, + .flags = { + .allow_pd = 0, + .backup_before_sleep = 0, + } + } + } + }, + .gps = {} +}; diff --git a/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.h b/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.h new file mode 100644 index 00000000..bbd3ab01 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/CrowPanelBasic35.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern const tt::hal::Configuration crowpanel_basic_35; diff --git a/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.cpp b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.cpp new file mode 100644 index 00000000..cc6cfc1b --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.cpp @@ -0,0 +1,46 @@ +#include "CrowPanelDisplay.h" +#include "CrowPanelDisplayConstants.h" + +#include +#include + +#include + +std::shared_ptr createTouch() { + auto configuration = std::make_unique( + CROWPANEL_LCD_SPI_HOST, + CROWPANEL_TOUCH_PIN_CS, + 320, + 480, + true, + true, + true + ); + + return std::make_shared(std::move(configuration)); +} + +std::shared_ptr createDisplay() { + auto touch = createTouch(); + + /** + * This display is mirrored on X, but that doesn't seem to work with the driver. + * Instead, we swap XY, which does work. That results in a landscape image. + */ + auto configuration = std::make_unique( + CROWPANEL_LCD_SPI_HOST, + CROWPANEL_LCD_PIN_CS, + CROWPANEL_LCD_PIN_DC, + 480, + 320, + touch, + true, + false, + false + ); + + configuration->mirrorX = true; + configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty; + + return std::make_shared(std::move(configuration)); +} diff --git a/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.h b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.h new file mode 100644 index 00000000..6c0fde39 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplay.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Tactility/hal/display/DisplayDevice.h" +#include +#include + +class CrowPanelDisplay : public tt::hal::display::DisplayDevice { + +private: + + esp_lcd_panel_io_handle_t ioHandle = nullptr; + esp_lcd_panel_handle_t panelHandle = nullptr; + lv_display_t* displayHandle = nullptr; + bool poweredOn = false; + +public: + + std::string getName() const final { return "ST7789"; } + std::string getDescription() const final { return "SPI display"; } + + bool start() override; + + bool stop() override; + + void setPowerOn(bool turnOn) override; + bool isPoweredOn() const override { return poweredOn; }; + bool supportsPowerControl() const override { return true; } + + std::shared_ptr _Nullable createTouch() override; + + void setBacklightDuty(uint8_t backlightDuty) override; + bool supportsBacklightDuty() const override { return true; } + + void setGammaCurve(uint8_t index) override; + uint8_t getGammaCurveCount() const override { return 4; }; + + lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; } +}; + +std::shared_ptr createDisplay(); diff --git a/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplayConstants.h b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplayConstants.h new file mode 100644 index 00000000..09e8d858 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelDisplayConstants.h @@ -0,0 +1,9 @@ +#pragma once + +#define CROWPANEL_LCD_SPI_HOST SPI2_HOST +#define CROWPANEL_LCD_PIN_CS GPIO_NUM_15 +#define CROWPANEL_TOUCH_PIN_CS GPIO_NUM_12 +#define CROWPANEL_LCD_PIN_DC GPIO_NUM_2 // RS +#define CROWPANEL_LCD_HORIZONTAL_RESOLUTION 320 +#define CROWPANEL_LCD_VERTICAL_RESOLUTION 240 +#define CROWPANEL_LCD_SPI_TRANSFER_HEIGHT (CROWPANEL_LCD_VERTICAL_RESOLUTION / 10) diff --git a/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.cpp b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.cpp new file mode 100644 index 00000000..0959c55c --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.cpp @@ -0,0 +1,27 @@ +#include "CrowPanelSdCard.h" + +#include +#include + +#include + +using tt::hal::sdcard::SpiSdCardDevice; + +std::shared_ptr createSdCard() { + auto* configuration = new SpiSdCardDevice::Config( + GPIO_NUM_5, + GPIO_NUM_NC, + GPIO_NUM_NC, + GPIO_NUM_NC, + SdCardDevice::MountBehaviour::AtBoot, + tt::lvgl::getSyncLock(), + {}, + SPI3_HOST + ); + + auto* sdcard = (SdCardDevice*) new SpiSdCardDevice( + std::unique_ptr(configuration) + ); + + return std::shared_ptr(sdcard); +} diff --git a/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.h b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.h new file mode 100644 index 00000000..5cb65a73 --- /dev/null +++ b/Boards/ElecrowCrowpanelBasic35/Source/hal/CrowPanelSdCard.h @@ -0,0 +1,7 @@ +#pragma once + +#include "Tactility/hal/sdcard/SdCardDevice.h" + +using tt::hal::sdcard::SdCardDevice; + +std::shared_ptr createSdCard(); diff --git a/Buildscripts/build-and-release-all.sh b/Buildscripts/build-and-release-all.sh index b8f65485..2fb598c4 100755 --- a/Buildscripts/build-and-release-all.sh +++ b/Buildscripts/build-and-release-all.sh @@ -23,6 +23,9 @@ release elecrow-crowpanel-advance-35 build elecrow-crowpanel-basic-28 release elecrow-crowpanel-basic-28 +build elecrow-crowpanel-basic-35 +release elecrow-crowpanel-basic-35 + build lilygo-tdeck release lilygo-tdeck diff --git a/CMakeLists.txt b/CMakeLists.txt index b8adf595..4169e5fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ if (DEFINED ENV{ESP_IDF_VERSION}) if(NOT "${IDF_TARGET}" STREQUAL "esp32") set(EXCLUDE_COMPONENTS "CYD-2432S024C") set(EXCLUDE_COMPONENTS "ElecrowCrowpanelBasic28") + set(EXCLUDE_COMPONENTS "ElecrowCrowpanelBasic35") set(EXCLUDE_COMPONENTS "M5stackCore2") endif() diff --git a/sdkconfig.board.elecrow-crowpanel-basic-35 b/sdkconfig.board.elecrow-crowpanel-basic-35 new file mode 100644 index 00000000..49630aaf --- /dev/null +++ b/sdkconfig.board.elecrow-crowpanel-basic-35 @@ -0,0 +1,47 @@ +# Software defaults +# Increase stack size for WiFi (fixes crash after scan) +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_ELF_LOADER_CUSTOMER_SYMBOLS=y +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_VOLUME_COUNT=3 + +# Hardware: Main +CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_35=y +CONFIG_TT_BOARD_NAME="CrowPanel Basic 3.5" +CONFIG_TT_BOARD_ID="crowpanel-basic-35" +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=143 +# 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 \ No newline at end of file