From d58f131033453f43f54ebcdbbc9c059a19418b48 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Thu, 22 Feb 2024 18:26:11 +0100 Subject: [PATCH] M5Stack Core2 support (#48) --- .github/workflows/esp.yml | 21 +++- .gitmodules | 6 ++ CMakeLists.txt | 15 ++- README.md | 10 ++ app-esp/CMakeLists.txt | 11 +- app-esp/Kconfig | 2 + app-esp/src/board_config.h | 3 + boards/m5stack_core2/CMakeLists.txt | 8 ++ boards/m5stack_core2/include/m5stack_core2.h | 13 +++ boards/m5stack_core2/private/bootstrap.h | 11 ++ boards/m5stack_core2/private/config.h | 37 +++++++ boards/m5stack_core2/private/display_i.hpp | 15 +++ boards/m5stack_core2/private/lvgl_i.h | 13 +++ boards/m5stack_core2/private/touch_i.hpp | 11 ++ boards/m5stack_core2/source/bootstrap.cpp | 105 +++++++++++++++++++ boards/m5stack_core2/source/display.cpp | 93 ++++++++++++++++ boards/m5stack_core2/source/lvgl.c | 42 ++++++++ boards/m5stack_core2/source/m5stack_core2.c | 14 +++ boards/m5stack_core2/source/sdcard.c | 79 ++++++++++++++ boards/m5stack_core2/source/touch.cpp | 32 ++++++ libs/M5GFX | 1 + libs/M5Unified | 1 + sdkconfig.board.m5stack_core2 | 33 ++++++ 23 files changed, 566 insertions(+), 10 deletions(-) create mode 100644 .gitmodules create mode 100644 boards/m5stack_core2/CMakeLists.txt create mode 100644 boards/m5stack_core2/include/m5stack_core2.h create mode 100644 boards/m5stack_core2/private/bootstrap.h create mode 100644 boards/m5stack_core2/private/config.h create mode 100644 boards/m5stack_core2/private/display_i.hpp create mode 100644 boards/m5stack_core2/private/lvgl_i.h create mode 100644 boards/m5stack_core2/private/touch_i.hpp create mode 100644 boards/m5stack_core2/source/bootstrap.cpp create mode 100644 boards/m5stack_core2/source/display.cpp create mode 100644 boards/m5stack_core2/source/lvgl.c create mode 100644 boards/m5stack_core2/source/m5stack_core2.c create mode 100644 boards/m5stack_core2/source/sdcard.c create mode 100644 boards/m5stack_core2/source/touch.cpp create mode 160000 libs/M5GFX create mode 160000 libs/M5Unified create mode 100644 sdkconfig.board.m5stack_core2 diff --git a/.github/workflows/esp.yml b/.github/workflows/esp.yml index 55a32766..c8594e95 100644 --- a/.github/workflows/esp.yml +++ b/.github/workflows/esp.yml @@ -10,7 +10,7 @@ jobs: submodules: recursive - name: Board select run: cp sdkconfig.board.yellow_board sdkconfig - - name: esp32 build + - name: build uses: espressif/esp-idf-ci-action@main with: esp_idf_version: v5.1.2 @@ -25,7 +25,7 @@ jobs: submodules: recursive - name: board select run: cp sdkconfig.board.lilygo_tdeck sdkconfig - - name: esp32s3 build + - name: build uses: espressif/esp-idf-ci-action@main with: esp_idf_version: v5.1.2 @@ -40,9 +40,24 @@ jobs: submodules: recursive - name: board select run: cp sdkconfig.board.waveshare_s3_touch sdkconfig - - name: esp32s3 build + - name: build uses: espressif/esp-idf-ci-action@main with: esp_idf_version: v5.1.2 target: esp32s3 path: './' + build-m5stack-core2: + runs-on: ubuntu-latest + steps: + - name: checkout repo + uses: actions/checkout@v2 + with: + submodules: recursive + - name: board select + run: cp sdkconfig.board.m5stack_core2 sdkconfig + - name: build + uses: espressif/esp-idf-ci-action@main + with: + esp_idf_version: v5.1.2 + target: esp32 + path: './' diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..96188fec --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "libs/M5GFX"] + path = libs/M5GFX + url = https://github.com/m5stack/M5GFX.git +[submodule "libs/M5Unified"] + path = libs/M5Unified + url = https://github.com/m5stack/M5Unified.git diff --git a/CMakeLists.txt b/CMakeLists.txt index efeba640..f3e77541 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,9 @@ if (DEFINED ENV{ESP_IDF_VERSION}) add_definitions(-DESP_TARGET) add_compile_definitions(ESP_TARGET) + add_definitions(-DARDUINO_M5STACK_CORE2) + add_compile_definitions(ARDUINO_M5STACK_CORE2) + set(COMPONENTS app-esp) set(EXTRA_COMPONENT_DIRS "boards" @@ -16,14 +19,17 @@ if (DEFINED ENV{ESP_IDF_VERSION}) "app-esp" "libs/esp_lvgl_port" "libs/lvgl" + "libs/M5Unified" + "libs/M5GFX" ) - # Yellow Board only runs on ESP32 + # ESP32 boards if(NOT "${IDF_TARGET}" STREQUAL "esp32") set(EXCLUDE_COMPONENTS "yellow_board_2432s024") + set(EXCLUDE_COMPONENTS "m5stack_core2") endif() - # T-Deck is an S3 platform + # ESP32-S3 boards if(NOT "${IDF_TARGET}" STREQUAL "esp32s3") set(EXCLUDE_COMPONENTS "lilygo_tdeck") set(EXCLUDE_COMPONENTS "waveshare_s3_touch") @@ -34,11 +40,12 @@ endif() project(tactility-root) -add_subdirectory(libs/mlib) -add_subdirectory(libs/lv_screenshot) add_subdirectory(tactility) add_subdirectory(tactility-core) +add_subdirectory(libs/mlib) +add_subdirectory(libs/lv_screenshot) + if (NOT DEFINED ENV{ESP_IDF_VERSION}) add_subdirectory(libs/freertos-kernel) target_include_directories(freertos-kernel diff --git a/README.md b/README.md index 10045fe6..26981ce3 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ Predefined configurations are available for: | [LilyGo T-Deck][tdeck] | ✅ | ✅ | Keyboard | | [Waveshare S3 Touch][waveshare_s3_touch] | ✅ | ⏳ | | | Yellow Board 2432S024C (\*) | ✅ | ✅ | | +| [M5Stack Core2][m5stack] | ✅ | ✅ | | - ✅: Capable and implemented - ⏳: Capable but not yet implemented @@ -89,9 +90,18 @@ Predefined configurations are available for: [waveshare_s3_touch]: https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-4.3 [2432s024c_1]: https://www.aliexpress.com/item/1005005902429049.html [2432s024c_2]: https://www.aliexpress.com/item/1005005865107357.html +[m5stack]: https://m5stack.com/ ## Guide +### Cloning from git + +Ensure you clone the repository including the submodules! For example: + +```bash +git clone --recurse-submodules -j8 https://github.com/ByteWelder/Tactility.git +``` + ### Build environment setup Ensure you have [esp-idf 5.1.2](https://docs.espressif.com/projects/esp-idf/en/v5.1.2/esp32/get-started/index.html) installed, then select the correct device: diff --git a/app-esp/CMakeLists.txt b/app-esp/CMakeLists.txt index 5e578440..4949ae44 100644 --- a/app-esp/CMakeLists.txt +++ b/app-esp/CMakeLists.txt @@ -3,13 +3,18 @@ cmake_minimum_required(VERSION 3.16) set(BOARD_COMPONENTS tactility-esp) if("${IDF_TARGET}" STREQUAL "esp32") - list(APPEND BOARD_COMPONENTS yellow_board) + list(APPEND BOARD_COMPONENTS + yellow_board + m5stack_core2 + ) endif() # T-Deck is an S3 platform if("${IDF_TARGET}" STREQUAL "esp32s3") - list(APPEND BOARD_COMPONENTS lilygo_tdeck) - list(APPEND BOARD_COMPONENTS waveshare_s3_touch) + list(APPEND BOARD_COMPONENTS + lilygo_tdeck + waveshare_s3_touch + ) endif() idf_component_register( diff --git a/app-esp/Kconfig b/app-esp/Kconfig index a374bf2d..f6477465 100644 --- a/app-esp/Kconfig +++ b/app-esp/Kconfig @@ -10,6 +10,8 @@ menu "Tactility App" bool "Yellow Board (2.4\" capacitive)" config TT_BOARD_LILYGO_TDECK bool "LilyGo T-Deck" + config TT_BOARD_M5STACK_CORE2 + bool "M5Stack Core2" config TT_BOARD_WAVESHARE_S3_TOUCH bool "Waveshare S3 Touch LCD 4.3\"" endchoice diff --git a/app-esp/src/board_config.h b/app-esp/src/board_config.h index 05c86028..0184abe6 100644 --- a/app-esp/src/board_config.h +++ b/app-esp/src/board_config.h @@ -9,6 +9,9 @@ #elif defined(CONFIG_TT_BOARD_YELLOW_BOARD_24_CAP) #include "yellow_board.h" #define TT_BOARD_HARDWARE &yellow_board_24inch_cap +#elif defined(CONFIG_TT_BOARD_M5STACK_CORE2) +#include "m5stack_core2.h" +#define TT_BOARD_HARDWARE &m5stack_core2 #elif defined(CONFIG_TT_BOARD_WAVESHARE_S3_TOUCH) #include "waveshare_s3_touch.h" #define TT_BOARD_HARDWARE &waveshare_s3_touch diff --git a/boards/m5stack_core2/CMakeLists.txt b/boards/m5stack_core2/CMakeLists.txt new file mode 100644 index 00000000..2e0eec03 --- /dev/null +++ b/boards/m5stack_core2/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register( + SRC_DIRS "source" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private" + REQUIRES esp_lvgl_port esp_lcd_ili9341 driver vfs fatfs M5Unified +) + +target_link_libraries(${COMPONENT_LIB} ${IDF_TARGET_NAME} tactility) diff --git a/boards/m5stack_core2/include/m5stack_core2.h b/boards/m5stack_core2/include/m5stack_core2.h new file mode 100644 index 00000000..dac57a84 --- /dev/null +++ b/boards/m5stack_core2/include/m5stack_core2.h @@ -0,0 +1,13 @@ +#pragma once + +#include "hardware_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const HardwareConfig m5stack_core2; + +#ifdef __cplusplus +} +#endif diff --git a/boards/m5stack_core2/private/bootstrap.h b/boards/m5stack_core2/private/bootstrap.h new file mode 100644 index 00000000..70c1b355 --- /dev/null +++ b/boards/m5stack_core2/private/bootstrap.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +bool core2_bootstrap(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/m5stack_core2/private/config.h b/boards/m5stack_core2/private/config.h new file mode 100644 index 00000000..a882213f --- /dev/null +++ b/boards/m5stack_core2/private/config.h @@ -0,0 +1,37 @@ +#pragma once + +#include "driver/spi_common.h" +#include "driver/i2c.h" +#include "driver/gpio.h" + +// I2C +#define CORE2_I2C_PIN_SDA 21 +#define CORE2_I2C_PIN_SCL 22 + +// SPI2 - Display, SD +#define CORE2_SPI2_PIN_SCLK GPIO_NUM_18 +#define CORE2_SPI2_PIN_MOSI GPIO_NUM_23 +#define CORE2_SPI2_PIN_MISO GPIO_NUM_38 +#define CORE2_SPI2_TRANSACTION_LIMIT CORE2_LCD_DRAW_BUFFER_SIZE + +// Display +#define CORE2_LCD_SPI_HOST SPI2_HOST +#define CORE2_LCD_HORIZONTAL_RESOLUTION 320 +#define CORE2_LCD_VERTICAL_RESOLUTION 240 +#define CORE2_LCD_BITS_PER_PIXEL 16 +#define CORE2_LCD_DRAW_BUFFER_HEIGHT (CORE2_LCD_VERTICAL_RESOLUTION / 10) +#define CORE2_LCD_DRAW_BUFFER_SIZE (CORE2_LCD_HORIZONTAL_RESOLUTION * CORE2_LCD_DRAW_BUFFER_HEIGHT * (CORE2_LCD_BITS_PER_PIXEL / 8)) +#define CORE2_LCD_PIN_CS GPIO_NUM_5 +#define CORE2_LCD_PIN_DC GPIO_NUM_15 + +// Touch +#define CORE2_TOUCH_I2C_PORT I2C_NUM_0 + +// SD Card +#define CORE2_SDCARD_SPI_HOST SPI2_HOST +#define CORE2_SDCARD_PIN_CS GPIO_NUM_4 +#define CORE2_SDCARD_SPI_FREQUENCY 800000U +#define CORE2_SDCARD_FORMAT_ON_MOUNT_FAILED false +#define CORE2_SDCARD_MAX_OPEN_FILES 4 +#define CORE2_SDCARD_ALLOC_UNIT_SIZE (16 * 1024) +#define CORE2_SDCARD_STATUS_CHECK_ENABLED false diff --git a/boards/m5stack_core2/private/display_i.hpp b/boards/m5stack_core2/private/display_i.hpp new file mode 100644 index 00000000..ea846ce1 --- /dev/null +++ b/boards/m5stack_core2/private/display_i.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include "lvgl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +lv_disp_t* core2_display_init(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/m5stack_core2/private/lvgl_i.h b/boards/m5stack_core2/private/lvgl_i.h new file mode 100644 index 00000000..cb4713e9 --- /dev/null +++ b/boards/m5stack_core2/private/lvgl_i.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool core2_lvgl_init(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/m5stack_core2/private/touch_i.hpp b/boards/m5stack_core2/private/touch_i.hpp new file mode 100644 index 00000000..412016c5 --- /dev/null +++ b/boards/m5stack_core2/private/touch_i.hpp @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +bool core2_touch_init(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/m5stack_core2/source/bootstrap.cpp b/boards/m5stack_core2/source/bootstrap.cpp new file mode 100644 index 00000000..dea8dad5 --- /dev/null +++ b/boards/m5stack_core2/source/bootstrap.cpp @@ -0,0 +1,105 @@ +#include "bootstrap.h" + +#include "M5Unified.hpp" +#include "config.h" +#include "log.h" + +m5::IMU_Class& Imu = M5.Imu; +m5::Power_Class& Power = M5.Power; +m5::RTC8563_Class& Rtc = M5.Rtc; +m5::Touch_Class& Touch = M5.Touch; + +m5::Speaker_Class& Speaker = M5.Speaker; + +m5::Button_Class& BtnPWR = M5.BtnPWR; + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG "core2_bootstrap" + +static bool init_i2c() { + const i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = CORE2_I2C_PIN_SDA, + .scl_io_num = CORE2_I2C_PIN_SCL, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_pullup_en = GPIO_PULLUP_DISABLE, + .master = { + .clk_speed = 100000 + }, + .clk_flags = 0 + }; + + if (i2c_param_config(CORE2_TOUCH_I2C_PORT, &i2c_conf) != ESP_OK) { + TT_LOG_E(TAG, "i2c config failed"); + return false; + } + + if (i2c_driver_install(CORE2_TOUCH_I2C_PORT, i2c_conf.mode, 0, 0, 0) != ESP_OK) { + TT_LOG_E(TAG, "i2c driver install failed"); + return false; + } + + return true; +} + +static bool init_spi2() { + const spi_bus_config_t bus_config = { + .mosi_io_num = CORE2_SPI2_PIN_MOSI, + .miso_io_num = CORE2_SPI2_PIN_MISO, + .sclk_io_num = CORE2_SPI2_PIN_SCLK, + .data2_io_num = GPIO_NUM_NC, + .data3_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, + .max_transfer_sz = CORE2_SPI2_TRANSACTION_LIMIT, + .flags = 0, + .isr_cpu_id = INTR_CPU_ID_AUTO, + .intr_flags = 0 + }; + + if (spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) { + TT_LOG_E(TAG, "SPI bus init failed"); + return false; + } + + return true; +} + +static void log_power_status() { + TT_LOG_I( + TAG, + "Battery: level = %ld, voltage = %.1f, charging = %s", + M5.Power.getBatteryLevel(), + (float)M5.Power.getBatteryVoltage() / 1000.0f, + M5.Power.isCharging() ? "true" : "false" + ); +} + +bool core2_bootstrap() { + TT_LOG_I(TAG, "Initializing M5Unified"); + M5.begin(); + // For models with EPD : refresh control + M5.Display.setEpdMode(epd_mode_t::epd_fastest); // fastest but very-low quality. + log_power_status(); + + TT_LOG_I(TAG, "Initializing I2C"); + if (!init_i2c()) { + return false; + } + + TT_LOG_I(TAG, "Initializing SPI"); + if (!init_spi2()) { + return false; + } + + return true; +} + +#ifdef __cplusplus +} +#endif diff --git a/boards/m5stack_core2/source/display.cpp b/boards/m5stack_core2/source/display.cpp new file mode 100644 index 00000000..df866f7a --- /dev/null +++ b/boards/m5stack_core2/source/display.cpp @@ -0,0 +1,93 @@ +#include "config.h" +#include "tactility_core.h" + +#include "esp_err.h" +#include "esp_lcd_ili9341.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lvgl_port.h" + +#define TAG "core2" + +#ifdef __cplusplus +extern "C" { +#endif + +lv_disp_t* core2_display_init() { + TT_LOG_I(TAG, "Display init"); + + const esp_lcd_panel_io_spi_config_t panel_io_config = ILI9341_PANEL_IO_SPI_CONFIG( + CORE2_LCD_PIN_CS, + CORE2_LCD_PIN_DC, + nullptr, + nullptr + ); + + esp_lcd_panel_io_handle_t io_handle; + if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)CORE2_LCD_SPI_HOST, &panel_io_config, &io_handle) != ESP_OK) { + TT_LOG_E(TAG, "Failed to create panel"); + return nullptr; + } + + const esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = GPIO_NUM_NC, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR, + .bits_per_pixel = CORE2_LCD_BITS_PER_PIXEL, + }; + + esp_lcd_panel_handle_t panel_handle; + if (esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle) != ESP_OK) { + TT_LOG_E(TAG, "Failed to create ili9341"); + return nullptr; + } + + if (esp_lcd_panel_reset(panel_handle) != ESP_OK) { + TT_LOG_E(TAG, "Failed to reset panel"); + return nullptr; + } + + if (esp_lcd_panel_init(panel_handle) != ESP_OK) { + TT_LOG_E(TAG, "Failed to init panel"); + return nullptr; + } + + if (esp_lcd_panel_invert_color(panel_handle, true) != ESP_OK) { + TT_LOG_E(TAG, "Failed to invert panel colours"); + return nullptr; + } + + if (esp_lcd_panel_disp_on_off(panel_handle, true) != ESP_OK) { + TT_LOG_E(TAG, "Failed to turn display on"); + return nullptr; + } + + const lvgl_port_display_cfg_t disp_cfg = { + .io_handle = io_handle, + .panel_handle = panel_handle, + .buffer_size = CORE2_LCD_DRAW_BUFFER_SIZE, + .double_buffer = false, + .trans_size = CORE2_SPI2_TRANSACTION_LIMIT, + .hres = CORE2_LCD_HORIZONTAL_RESOLUTION, + .vres = CORE2_LCD_VERTICAL_RESOLUTION, + .monochrome = false, + .rotation = { + .swap_xy = false, + .mirror_x = false, + .mirror_y = false, + }, + .flags = { + .buff_dma = false, + .buff_spiram = true, + .sw_rotate = false, + .swap_bytes = true + } + }; + + lv_display_t* display = lvgl_port_add_disp(&disp_cfg); + + return display; +} + +#ifdef __cplusplus +} +#endif diff --git a/boards/m5stack_core2/source/lvgl.c b/boards/m5stack_core2/source/lvgl.c new file mode 100644 index 00000000..f31965c1 --- /dev/null +++ b/boards/m5stack_core2/source/lvgl.c @@ -0,0 +1,42 @@ +#include "display_i.hpp" +#include "esp_lvgl_port.h" +#include "log.h" +#include "thread.h" +#include "touch_i.hpp" +#include "ui/lvgl_sync.h" + +#define TAG "core2_lvgl" + +bool core2_lvgl_init() { + static lv_display_t* display = NULL; + + const lvgl_port_cfg_t lvgl_cfg = { + .task_priority = ThreadPriorityHigh, + .task_stack = 8096, + .task_affinity = -1, // core pinning + .task_max_sleep_ms = 500, + .timer_period_ms = 5 + }; + + if (lvgl_port_init(&lvgl_cfg) != ESP_OK) { + TT_LOG_E(TAG, "lvgl port init failed"); + return false; + } + + // Add display + display = core2_display_init(); + if (display == NULL) { + TT_LOG_E(TAG, "failed to add display"); + return false; + } + + // Add touch + if (!core2_touch_init()) { + return false; + } + + // Set syncing functions + tt_lvgl_sync_set(&lvgl_port_lock, &lvgl_port_unlock); + + return true; +} diff --git a/boards/m5stack_core2/source/m5stack_core2.c b/boards/m5stack_core2/source/m5stack_core2.c new file mode 100644 index 00000000..f5f71e59 --- /dev/null +++ b/boards/m5stack_core2/source/m5stack_core2.c @@ -0,0 +1,14 @@ +#include "m5stack_core2.h" +#include "bootstrap.h" +#include "lvgl_i.h" + +extern const SdCard core2_sdcard; + +const HardwareConfig m5stack_core2 = { + .bootstrap = &core2_bootstrap, + .display = { + .set_backlight_duty = NULL + }, + .init_lvgl = &core2_lvgl_init, + .sdcard = &core2_sdcard +}; diff --git a/boards/m5stack_core2/source/sdcard.c b/boards/m5stack_core2/source/sdcard.c new file mode 100644 index 00000000..16b8d799 --- /dev/null +++ b/boards/m5stack_core2/source/sdcard.c @@ -0,0 +1,79 @@ +#include "sdcard.h" +#include "check.h" +#include "log.h" +#include "config.h" + +#include "esp_vfs_fat.h" +#include "sdmmc_cmd.h" + +#define TAG "core2_sdcard" + +typedef struct { + const char* mount_point; + sdmmc_card_t* card; +} MountData; + +static void* sdcard_mount(const char* mount_point) { + TT_LOG_I(TAG, "Mounting %s", mount_point); + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = CORE2_SDCARD_FORMAT_ON_MOUNT_FAILED, + .max_files = CORE2_SDCARD_MAX_OPEN_FILES, + .allocation_unit_size = CORE2_SDCARD_ALLOC_UNIT_SIZE, + .disk_status_check_enable = CORE2_SDCARD_STATUS_CHECK_ENABLED + }; + + sdmmc_card_t* card; + + // Init without card detect (CD) and write protect (WD) + sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + slot_config.gpio_cs = CORE2_SDCARD_PIN_CS; + slot_config.host_id = CORE2_SDCARD_SPI_HOST; + + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + host.max_freq_khz = CORE2_SDCARD_SPI_FREQUENCY; + esp_err_t ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card); + + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + TT_LOG_E(TAG, "Mounting failed. Ensure the card is formatted with FAT."); + } else { + TT_LOG_E(TAG, "Mounting failed (%s)", esp_err_to_name(ret)); + } + return NULL; + } + + MountData* data = malloc(sizeof(MountData)); + *data = (MountData) { + .card = card, + .mount_point = mount_point + }; + + sdmmc_card_print_info(stdout, data->card); + + return data; +} + +static void sdcard_unmount(void* context) { + MountData* data = (MountData*)context; + TT_LOG_I(TAG, "Unmounting %s", data->mount_point); + + tt_assert(data != NULL); + if (esp_vfs_fat_sdcard_unmount(data->mount_point, data->card) != ESP_OK) { + TT_LOG_E(TAG, "Unmount failed for %s", data->mount_point); + } + + free(data); +} + +static bool sdcard_is_mounted(void* context) { + MountData* data = (MountData*)context; + return (data != NULL) && (sdmmc_get_status(data->card) == ESP_OK); +} + +const SdCard core2_sdcard = { + .mount = &sdcard_mount, + .unmount = &sdcard_unmount, + .is_mounted = &sdcard_is_mounted, + .mount_behaviour = SdcardMountBehaviourAnytime +}; diff --git a/boards/m5stack_core2/source/touch.cpp b/boards/m5stack_core2/source/touch.cpp new file mode 100644 index 00000000..847e5b03 --- /dev/null +++ b/boards/m5stack_core2/source/touch.cpp @@ -0,0 +1,32 @@ +#include "tactility_core.h" +#include "lvgl.h" +#include "M5Unified.hpp" + +#define TAG "core2_touch" + +#ifdef __cplusplus +extern "C" { +#endif + +static void read_touch(TT_UNUSED lv_indev_t* indev, lv_indev_data_t* data) { + static lgfx::touch_point_t point; + bool touched = M5.Lcd.getTouch(&point) > 0; + if (touched) { + data->point.x = point.x; + data->point.y = point.y; + data->state = LV_INDEV_STATE_PRESSED; + } else { + data->state = LV_INDEV_STATE_RELEASED; + } +} + +bool core2_touch_init() { + lv_indev_t _Nullable* touch_indev = lv_indev_create(); + lv_indev_set_type(touch_indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(touch_indev, read_touch); + return true; +} + +#ifdef __cplusplus +} +#endif diff --git a/libs/M5GFX b/libs/M5GFX new file mode 160000 index 00000000..33d7d313 --- /dev/null +++ b/libs/M5GFX @@ -0,0 +1 @@ +Subproject commit 33d7d3135e816a86a008fae8ab3757938cee95d2 diff --git a/libs/M5Unified b/libs/M5Unified new file mode 160000 index 00000000..d7f880a2 --- /dev/null +++ b/libs/M5Unified @@ -0,0 +1 @@ +Subproject commit d7f880a293badd54958a6da2403855da4245aefc diff --git a/sdkconfig.board.m5stack_core2 b/sdkconfig.board.m5stack_core2 new file mode 100644 index 00000000..52890959 --- /dev/null +++ b/sdkconfig.board.m5stack_core2 @@ -0,0 +1,33 @@ +# Software defaults +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_FREERTOS_HZ=1000 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" + +# Hardware: Main +CONFIG_TT_BOARD_M5STACK_CORE2=y +CONFIG_IDF_TARGET="esp32" +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_FLASHMODE_QIO=y +# Hardware: SPI RAM +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +# LVGL +CONFIG_LV_DISP_DEF_REFR_PERIOD=17 +CONFIG_LV_INDEV_DEF_READ_PERIOD=17 +CONFIG_LV_DPI_DEF=139