diff --git a/docs/esp-idf-6-migration.md b/docs/esp-idf-6-migration.md index d0f7944..46b5cbc 100644 --- a/docs/esp-idf-6-migration.md +++ b/docs/esp-idf-6-migration.md @@ -82,8 +82,8 @@ Espressif's current chip-identification table lists v0.0, v1.0, v1.3, v3.0, v3.1 | `espressif/mqtt` | `1.0.0` | ✅ Upstream support | MQTT moved from a built-in SDK component to a Component Manager dependency in IDF 6 | | `78/esp-ml307` | `3.6.6` + project-level `espressif/mqtt` | ✅ Builds in CI | The upstream source compiles under IDF 6.0.1 when the project supplies the MQTT component moved out of IDF | | `espressif/esp_hosted` / `esp_wifi_remote` | `2.12.11` / `1.6.2` | ✅ Upstream support | Used for ESP32-P4 Hosted Wi-Fi | -| `espressif/esp_video` | `^2.0.1` | ✅ Upstream support | Currently resolves to 2.3.0 on S3 and 2.0.1 on P4 due to BSP constraints | -| P4 BSP / LCD drivers | BSP `5.2.3`, EK79007/ST7701 `2.0.x` | ✅ Upstream support | Resolves IDF 6 DPI, color-field, and split-driver-component issues | +| `espressif/esp_video` | `^2.3.0` | ✅ Upstream support | Requires the current 2.3 API baseline and accepts future compatible 2.x releases on S3 and P4 | +| P4 LCD drivers | EK79007/ST7701 `2.0.x` | ✅ Upstream support | ESP32-P4-Function-EV-Board initializes its hardware directly so its former BSP cannot constrain `esp_video`; the LCD drivers resolve IDF 6 DPI, color-field, and split-driver-component issues | | `espressif/esp_lcd_st77916` | `2.0.2` | ✅ Upstream support | Major version 2 uses the IDF 6 panel I/O definitions | | `espressif/esp_lcd_spd2010` | `^2.0.0` (resolved `2.0.0~1`) | ✅ Upstream support | Major version 2 declares ESP-IDF 6 compatibility | | `espressif/esp_lcd_co5300` | `2.1.0` | ✅ Upstream support | Used with explicit IDF 6-compatible QSPI I/O configuration in board code | diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index ab873b8..0635a41 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1023,6 +1023,12 @@ if(CONFIG_BOARD_TYPE_ESP_VOCAT AND IDF_VERSION_MAJOR LESS 6) espressif__touch_button_sensor ) endif() +if(CONFIG_BOARD_TYPE_ESP32_P4_FUNCTION_EV_BOARD) + list(APPEND MAIN_PRIV_REQUIRES_EXTRA + esp_driver_sdmmc + sdmmc + ) +endif() idf_component_register(SRCS ${SOURCES} EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS} INCLUDE_DIRS ${INCLUDE_DIRS} diff --git a/main/boards/common/camera.h b/main/boards/common/camera.h index 09a6a3e..d15c1a3 100644 --- a/main/boards/common/camera.h +++ b/main/boards/common/camera.h @@ -5,6 +5,8 @@ class Camera { public: + virtual ~Camera() = default; + virtual void SetExplainUrl(const std::string& url, const std::string& token) = 0; virtual bool Capture() = 0; virtual bool SetHMirror(bool enabled) = 0; @@ -13,4 +15,4 @@ public: virtual std::string Explain(const std::string& question) = 0; }; -#endif // CAMERA_H +#endif // CAMERA_H diff --git a/main/boards/common/esp_video.h b/main/boards/common/esp_video.h index 063276e..6ac8702 100644 --- a/main/boards/common/esp_video.h +++ b/main/boards/common/esp_video.h @@ -2,16 +2,16 @@ #include "sdkconfig.h" #include -#include #include +#include #include #include #include #include "camera.h" -#include "jpg/image_to_jpeg.h" #include "esp_video_init.h" +#include "jpg/image_to_jpeg.h" struct JpegChunk { uint8_t* data; @@ -21,7 +21,7 @@ struct JpegChunk { class EspVideo : public Camera { private: struct FrameBuffer { - uint8_t *data = nullptr; + uint8_t* data = nullptr; size_t len = 0; uint16_t width = 0; uint16_t height = 0; @@ -34,7 +34,10 @@ private: #endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE int video_fd_ = -1; bool streaming_on_ = false; - struct MmapBuffer { void *start = nullptr; size_t length = 0; }; + struct MmapBuffer { + void* start = nullptr; + size_t length = 0; + }; std::vector mmap_buffers_; std::string explain_url_; std::string explain_token_; @@ -42,7 +45,7 @@ private: public: EspVideo(const esp_video_init_config_t& config); - ~EspVideo(); + ~EspVideo() override; virtual void SetExplainUrl(const std::string& url, const std::string& token); virtual bool Capture(); diff --git a/main/boards/espressif/esp32-p4-function-ev-board/README.md b/main/boards/espressif/esp32-p4-function-ev-board/README.md index 39c8035..3db81ee 100644 --- a/main/boards/espressif/esp32-p4-function-ev-board/README.md +++ b/main/boards/espressif/esp32-p4-function-ev-board/README.md @@ -10,7 +10,7 @@ LCD is supported via the official MIPI‑DSI LCD adapter. - Audio: ES8311 codec with speaker and microphone support - Touch: GT911 capacitive touch controller - SD Card: MicroSD card support (MMC mode) -- Camera: MIPI-CSI camera interface with fallback DVP configuration (OV5647, SC2336 sensors supported) +- Camera: MIPI-CSI camera interface (OV5647 and SC2336 sensors supported) - USB: USB host/device support - SPIFFS: Built-in flash filesystem support - Fonts: Custom font support with Unicode characters (Vietnamese, Chinese, etc.) @@ -24,13 +24,19 @@ Ensure these are set (auto-set when building via config.json): - `CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y` - `CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y` +The board initializes I2C, LCD, touch, audio, SDMMC, and camera hardware directly +from the board implementation. It does not depend on the +`espressif/esp32_p4_function_ev_board` BSP, allowing the project-wide +`esp_video` dependency to resolve independently. + ## LCD Connection (from Espressif user guide) - Connect the LCD adapter board J3 to the board’s MIPI DSI connector (reverse ribbon). - Wire `RST_LCD` (adapter J6) to `GPIO27` (board J1). - Wire `PWM` (adapter J6) to `GPIO26` (board J1). - Optionally power the LCD adapter via its USB or provide `5V` and `GND` from the board. -These pins are pre-configured in `config.h` as `PIN_NUM_LCD_RST=GPIO27` and `DISPLAY_BACKLIGHT_PIN=GPIO26`. Resolution is set to 1024×600. +These pins are configured in `config.h` as `DISPLAY_RESET_PIN=GPIO27` and +`DISPLAY_BACKLIGHT_PIN=GPIO26`. Resolution is set to 1024×600. ## Build (example) ```powershell diff --git a/main/boards/espressif/esp32-p4-function-ev-board/config.h b/main/boards/espressif/esp32-p4-function-ev-board/config.h index aca0c93..40461af 100644 --- a/main/boards/espressif/esp32-p4-function-ev-board/config.h +++ b/main/boards/espressif/esp32-p4-function-ev-board/config.h @@ -1,11 +1,44 @@ #ifndef _BOARD_CONFIG_H_ #define _BOARD_CONFIG_H_ -#include "bsp/esp32_p4_function_ev_board.h" // Library for board configs and pins +#include +#include -#define AUDIO_INPUT_SAMPLE_RATE 24000 +#define AUDIO_INPUT_SAMPLE_RATE 24000 #define AUDIO_OUTPUT_SAMPLE_RATE 24000 +#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 +#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 +#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 +#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 +#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 +#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 +#define AUDIO_CODEC_I2C_PORT I2C_NUM_1 +#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 +#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 + +#define BOOT_BUTTON_GPIO GPIO_NUM_0 + +#define DISPLAY_WIDTH 1024 +#define DISPLAY_HEIGHT 600 +#define DISPLAY_OFFSET_X 0 +#define DISPLAY_OFFSET_Y 0 +#define DISPLAY_MIRROR_X true +#define DISPLAY_MIRROR_Y true +#define DISPLAY_SWAP_XY false +#define DISPLAY_RESET_PIN GPIO_NUM_27 +#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_26 #define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif // _BOARD_CONFIG_H_ \ No newline at end of file +#define LCD_MIPI_DSI_LANE_NUM 2 +#define LCD_MIPI_DSI_LANE_BITRATE_MBPS 1000 +#define MIPI_DSI_PHY_PWR_LDO_CHAN 3 +#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500 + +#define CAMERA_RESET_PIN GPIO_NUM_NC +#define CAMERA_PWDN_PIN GPIO_NUM_NC + +#define SD_CARD_MOUNT_POINT "/sdcard" +#define SD_CARD_PWR_LDO_CHAN 4 + +#endif // _BOARD_CONFIG_H_ diff --git a/main/boards/espressif/esp32-p4-function-ev-board/config.json b/main/boards/espressif/esp32-p4-function-ev-board/config.json index 20e5f12..f4e0553 100644 --- a/main/boards/espressif/esp32-p4-function-ev-board/config.json +++ b/main/boards/espressif/esp32-p4-function-ev-board/config.json @@ -11,7 +11,6 @@ "CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y", "CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y", "CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y", - "CONFIG_BSP_LCD_TYPE_1024_600=y", "CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y", "CONFIG_ESP32P4_REV_MIN_100=y" ] @@ -23,8 +22,7 @@ "CONFIG_ESP_HOSTED_P4_DEV_BOARD_FUNC_BOARD=y", "CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y", "CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y", - "CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y", - "CONFIG_BSP_LCD_TYPE_1024_600=y" + "CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y" ] } ] diff --git a/main/boards/espressif/esp32-p4-function-ev-board/esp32-p4-function-ev-board.cc b/main/boards/espressif/esp32-p4-function-ev-board/esp32-p4-function-ev-board.cc index d473fd4..e97580f 100644 --- a/main/boards/espressif/esp32-p4-function-ev-board/esp32-p4-function-ev-board.cc +++ b/main/boards/espressif/esp32-p4-function-ev-board/esp32-p4-function-ev-board.cc @@ -1,84 +1,119 @@ -#include "wifi_board.h" -#include "audio/codecs/es8311_audio_codec.h" -// Display -#include "display/display.h" -#include "display/lcd_display.h" -#include "lvgl_theme.h" -// Backlight -// PwmBacklight is declared in backlight headers pulled by display/lcd_display includes via lvgl stack - #include "application.h" +#include "audio/codecs/es8311_audio_codec.h" #include "button.h" #include "config.h" +#include "display/display.h" +#include "display/lcd_display.h" #include "esp_video.h" +#include "lvgl_theme.h" +#include "wifi_board.h" -#include -#include #include +#include +#include +#include +#include +#include +#include #include -#include -// SD card #include #include -#include -#include -// SD power control (on-chip LDO) -#include "sd_pwr_ctrl_by_on_chip_ldo.h" -// MIPI-DSI / LCD vendor includes (library may replace some) -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" #include "esp_lcd_ek79007.h" #include "esp_lcd_touch_gt911.h" - -// Library includes -#include "bsp/esp32_p4_function_ev_board.h" -#include "bsp/touch.h" +#include "sd_pwr_ctrl_by_on_chip_ldo.h" #define TAG "ESP32P4FuncEV" -class ESP32P4FunctionEvBoard : public WifiBoard -{ +class ESP32P4FunctionEvBoard : public WifiBoard { private: i2c_master_bus_handle_t codec_i2c_bus_ = nullptr; Button boot_button_; - LcdDisplay *display_ = nullptr; + LcdDisplay* display_ = nullptr; + esp_lcd_dsi_bus_handle_t dsi_bus_ = nullptr; + esp_ldo_channel_handle_t dsi_phy_power_ = nullptr; esp_lcd_touch_handle_t tp_ = nullptr; + esp_lcd_panel_io_handle_t touch_io_ = nullptr; + lv_indev_t* touch_indev_ = nullptr; EspVideo* camera_ = nullptr; + sdmmc_card_t* sd_card_ = nullptr; + sd_pwr_ctrl_handle_t sd_power_ = nullptr; + bool sd_card_mounted_ = false; - void InitializeI2cBuses() - { - ESP_ERROR_CHECK(bsp_i2c_init()); - codec_i2c_bus_ = bsp_i2c_get_handle(); - } - - // Touch I2C bus initialization is not required for this board (handled elsewhere) - void InitializeTouchI2cBus() - { - // No implementation needed - } - - void InitializeLCD() - { - bsp_display_config_t config = { - .hdmi_resolution = BSP_HDMI_RES_NONE, - .dsi_bus = { - .phy_clk_src = (mipi_dsi_phy_clock_source_t)SOC_MOD_CLK_PLL_F20M, - .lane_bit_rate_mbps = 1000, - }, + void InitializeI2cBus() { + i2c_master_bus_config_t i2c_bus_config = { + .i2c_port = AUDIO_CODEC_I2C_PORT, + .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, + .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .intr_priority = 0, + .trans_queue_depth = 0, + .flags = + { + .enable_internal_pullup = 1, + }, }; - - bsp_lcd_handles_t handles; - ESP_ERROR_CHECK(bsp_display_new_with_handles(&config, &handles)); - - display_ = new MipiLcdDisplay(handles.io, handles.panel, 1024, 600, 0, 0, true, true, false); + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &codec_i2c_bus_)); } - void InitializeButtons() - { - boot_button_.OnClick([this]() - { + void InitializeLcd() { + esp_ldo_channel_config_t ldo_config = { + .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, + .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, + }; + ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_config, &dsi_phy_power_)); + + esp_lcd_dsi_bus_config_t bus_config = { + .bus_id = 0, + .num_data_lanes = LCD_MIPI_DSI_LANE_NUM, + .lane_bit_rate_mbps = LCD_MIPI_DSI_LANE_BITRATE_MBPS, + }; + ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &dsi_bus_)); + + esp_lcd_panel_io_handle_t panel_io = nullptr; + esp_lcd_dbi_io_config_t dbi_config = { + .virtual_channel = 0, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(dsi_bus_, &dbi_config, &panel_io)); + + esp_lcd_dpi_panel_config_t dpi_config = + EK79007_1024_600_PANEL_60HZ_CONFIG_CF(LCD_COLOR_FMT_RGB565); + dpi_config.num_fbs = 1; +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) + dpi_config.flags.use_dma2d = true; +#endif + + ek79007_vendor_config_t vendor_config = { + .mipi_config = + { + .dsi_bus = dsi_bus_, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = DISPLAY_RESET_PIN; + panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; + panel_config.bits_per_pixel = 16; + panel_config.vendor_config = &vendor_config; + + esp_lcd_panel_handle_t panel = nullptr; + ESP_ERROR_CHECK(esp_lcd_new_panel_ek79007(panel_io, &panel_config, &panel)); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + ESP_ERROR_CHECK(esp_lcd_dpi_panel_enable_dma2d(panel)); +#endif + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); + + display_ = new MipiLcdDisplay(panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, + DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, + DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); + } + + void InitializeButtons() { + boot_button_.OnClick([this]() { auto& app = Application::GetInstance(); if (app.GetDeviceState() == kDeviceStateStarting) { EnterWifiConfigMode(); @@ -88,91 +123,113 @@ private: }); } - void InitializeTouch() - { - ESP_ERROR_CHECK(bsp_touch_new(NULL, &tp_)); + void InitializeTouch() { + esp_lcd_touch_config_t touch_config = { + .x_max = DISPLAY_WIDTH, + .y_max = DISPLAY_HEIGHT, + .rst_gpio_num = GPIO_NUM_NC, + .int_gpio_num = GPIO_NUM_NC, + .levels = + { + .reset = 0, + .interrupt = 0, + }, + .flags = + { + .swap_xy = 0, + .mirror_x = 1, + .mirror_y = 1, + }, + }; + esp_lcd_panel_io_i2c_config_t touch_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); + touch_io_config.scl_speed_hz = 400000; + + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(codec_i2c_bus_, &touch_io_config, &touch_io_)); + ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(touch_io_, &touch_config, &tp_)); + + lv_display_t* lv_display = lv_display_get_default(); + if (lv_display == nullptr) { + ESP_LOGE(TAG, "Cannot register touch input without an LVGL display"); + return; + } + const lvgl_port_touch_cfg_t lv_touch_config = { + .disp = lv_display, + .handle = tp_, + }; + touch_indev_ = lvgl_port_add_touch(&lv_touch_config); + if (touch_indev_ == nullptr) { + ESP_LOGE(TAG, "Failed to register GT911 touch input"); + } } - void InitializeSdCard() - { + void InitializeSdCard() { ESP_LOGI(TAG, "Initializing SD card"); - esp_err_t ret = bsp_sdcard_mount(); + + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.slot = SDMMC_HOST_SLOT_0; + host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; + + sdmmc_slot_config_t slot = {}; + slot.cd = SDMMC_SLOT_NO_CD; + slot.wp = SDMMC_SLOT_NO_WP; + slot.width = 4; + + const esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = 5, + .allocation_unit_size = 64 * 1024, + }; + + sd_pwr_ctrl_ldo_config_t power_config = { + .ldo_chan_id = SD_CARD_PWR_LDO_CHAN, + }; + esp_err_t ret = sd_pwr_ctrl_new_on_chip_ldo(&power_config, &sd_power_); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to enable SD card power: %s", esp_err_to_name(ret)); + return; + } + host.pwr_ctrl_handle = sd_power_; + + ret = esp_vfs_fat_sdmmc_mount(SD_CARD_MOUNT_POINT, &host, &slot, &mount_config, &sd_card_); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to mount SD card: %s", esp_err_to_name(ret)); + sd_pwr_ctrl_del_on_chip_ldo(sd_power_); + sd_power_ = nullptr; } else { + sd_card_mounted_ = true; ESP_LOGI(TAG, "SD card mounted successfully"); } } - void InitializeCamera() - { + void InitializeCamera() { ESP_LOGI(TAG, "Initializing camera"); - // Use BSP camera initialization for ESP-P4 - bsp_camera_cfg_t camera_cfg = {0}; - esp_err_t ret = bsp_camera_start(&camera_cfg); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize BSP camera: %s", esp_err_to_name(ret)); - ESP_LOGI(TAG, "Attempting alternative camera initialization"); - - // Alternative: Direct EspVideo initialization if BSP fails - // This provides more control over camera configuration - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = BSP_I2C_SDA, // Reuse I2C pins if camera pins not defined - [1] = BSP_I2C_SCL, - [2] = GPIO_NUM_NC, - [3] = GPIO_NUM_NC, - [4] = GPIO_NUM_NC, - [5] = GPIO_NUM_NC, - [6] = GPIO_NUM_NC, - [7] = GPIO_NUM_NC, + esp_video_init_csi_config_t csi_config = { + .sccb_config = + { + .init_sccb = false, + .i2c_handle = codec_i2c_bus_, + .freq = 400000, }, - .vsync_io = GPIO_NUM_NC, - .de_io = GPIO_NUM_NC, - .pclk_io = GPIO_NUM_NC, - .xclk_io = GPIO_NUM_NC, - }; + .reset_pin = CAMERA_RESET_PIN, + .pwdn_pin = CAMERA_PWDN_PIN, + }; + esp_video_init_config_t video_config = { + .csi = &csi_config, + }; - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // Use existing I2C bus - .i2c_handle = codec_i2c_bus_, // Reuse the existing I2C bus - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - .dvp_pin = dvp_pin_config, - .xclk_freq = 20000000, // 20MHz typical for cameras - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - // Try to create camera with direct configuration - camera_ = new EspVideo(video_config); - ESP_LOGI(TAG, "Camera initialized with direct configuration"); - } else { - ESP_LOGI(TAG, "Camera initialized successfully via BSP"); - } + camera_ = new EspVideo(video_config); } - void InitializeFonts() - { + void InitializeFonts() { ESP_LOGI(TAG, "Initializing font support"); - // Font initialization is handled by the Assets system - // The board supports loading fonts from assets partition - // Verify that fonts are properly loaded by checking theme auto& theme_manager = LvglThemeManager::GetInstance(); auto current_theme = theme_manager.GetTheme("light"); if (current_theme != nullptr) { auto text_font = current_theme->text_font(); if (text_font != nullptr && text_font->font() != nullptr) { - ESP_LOGI(TAG, "Custom font loaded successfully: line_height=%d", text_font->font()->line_height); + ESP_LOGI(TAG, "Custom font loaded successfully: line_height=%d", + text_font->font()->line_height); } else { ESP_LOGW(TAG, "Custom font not loaded, using built-in font"); } @@ -180,12 +237,9 @@ private: } public: - - ESP32P4FunctionEvBoard() : boot_button_(0) - { - InitializeI2cBuses(); - // Audio is initialized by Es8311AudioCodec - InitializeLCD(); + ESP32P4FunctionEvBoard() : boot_button_(BOOT_BUTTON_GPIO) { + InitializeI2cBus(); + InitializeLcd(); InitializeButtons(); InitializeTouch(); InitializeSdCard(); @@ -194,40 +248,65 @@ public: GetBacklight()->RestoreBrightness(); } - ~ESP32P4FunctionEvBoard() - { - // Clean up display pointer + ~ESP32P4FunctionEvBoard() { + delete camera_; + camera_ = nullptr; + + if (sd_card_mounted_) { + esp_err_t ret = esp_vfs_fat_sdcard_unmount(SD_CARD_MOUNT_POINT, sd_card_); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to unmount SD card: %s", esp_err_to_name(ret)); + } + sd_card_mounted_ = false; + sd_card_ = nullptr; + } + if (sd_power_ != nullptr) { + sd_pwr_ctrl_del_on_chip_ldo(sd_power_); + sd_power_ = nullptr; + } + + if (touch_indev_ != nullptr) { + lvgl_port_remove_touch(touch_indev_); + touch_indev_ = nullptr; + } + if (tp_ != nullptr) { + esp_lcd_touch_del(tp_); + tp_ = nullptr; + } + if (touch_io_ != nullptr) { + esp_lcd_panel_io_del(touch_io_); + touch_io_ = nullptr; + } + delete display_; display_ = nullptr; - // Unmount SD card - esp_err_t ret = bsp_sdcard_unmount(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to unmount SD card: %s", esp_err_to_name(ret)); + + if (dsi_bus_ != nullptr) { + esp_lcd_del_dsi_bus(dsi_bus_); + dsi_bus_ = nullptr; + } + if (dsi_phy_power_ != nullptr) { + esp_ldo_release_channel(dsi_phy_power_); + dsi_phy_power_ = nullptr; } - // If other resources need cleanup, add here } - virtual AudioCodec *GetAudioCodec() override - { + virtual AudioCodec* GetAudioCodec() override { static Es8311AudioCodec audio_codec( - codec_i2c_bus_, (i2c_port_t)BSP_I2C_NUM, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - BSP_I2S_MCLK, BSP_I2S_SCLK, BSP_I2S_LCLK, BSP_I2S_DOUT, BSP_I2S_DSIN, - BSP_POWER_AMP_IO, ES8311_CODEC_DEFAULT_ADDR, true, false); + codec_i2c_bus_, AUDIO_CODEC_I2C_PORT, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, + AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, + AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, ES8311_CODEC_DEFAULT_ADDR, true, false); return &audio_codec; } - virtual Display *GetDisplay() override { return display_; } + virtual Display* GetDisplay() override { return display_; } - virtual Backlight *GetBacklight() override - { - static PwmBacklight backlight(BSP_LCD_BACKLIGHT, DISPLAY_BACKLIGHT_OUTPUT_INVERT); + virtual Backlight* GetBacklight() override { + static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); return &backlight; } - virtual Camera *GetCamera() override - { - return camera_; - } + virtual Camera* GetCamera() override { return camera_; } }; DECLARE_BOARD(ESP32P4FunctionEvBoard); diff --git a/main/idf_component.yml b/main/idf_component.yml index 2013c3f..8c92ff6 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -45,7 +45,7 @@ dependencies: rules: - if: target in [esp32s3] espressif/esp_video: - version: ^2.0.1 + version: ^2.3.0 rules: - if: target in [esp32p4, esp32s3] @@ -91,10 +91,6 @@ dependencies: version: '*' rules: - if: target in [esp32p4] - espressif/esp32_p4_function_ev_board: - version: ^5.2.3 - rules: - - if: target in [esp32p4] espressif/esp_lcd_ili9881c: version: ^1.0.1 rules: