From 652891c91ab038539100aff07ed2edbdec3da5e7 Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Wed, 18 Sep 2024 14:16:35 +0200 Subject: [PATCH] bsp: New BSP for ESP32-P4-BOX --- .github/workflows/upload_component.yml | 2 +- .github/workflows/upload_component_noglib.yml | 3 +- bsp/esp32_p4_box/CMakeLists.txt | 8 + bsp/esp32_p4_box/Kconfig | 100 +++ bsp/esp32_p4_box/LICENSE | 202 ++++++ bsp/esp32_p4_box/README.md | 20 + bsp/esp32_p4_box/esp32_p4_box.c | 656 ++++++++++++++++++ bsp/esp32_p4_box/esp32_p4_box_idf5.c | 95 +++ bsp/esp32_p4_box/idf_component.yml | 28 + bsp/esp32_p4_box/include/bsp/config.h | 16 + bsp/esp32_p4_box/include/bsp/display.h | 172 +++++ bsp/esp32_p4_box/include/bsp/esp-bsp.h | 8 + bsp/esp32_p4_box/include/bsp/esp32_p4_box.h | 471 +++++++++++++ bsp/esp32_p4_box/include/bsp/touch.h | 51 ++ bsp/esp32_p4_box/priv_include/bsp_err_check.h | 58 ++ examples/bsp_ext.py | 3 +- examples/display/sdkconfig.bsp.esp32_p4_box | 35 + .../sdkconfig.bsp.esp32_p4_box | 36 + .../sdkconfig.bsp.esp32_p4_box | 45 ++ 19 files changed, 2006 insertions(+), 3 deletions(-) create mode 100644 bsp/esp32_p4_box/CMakeLists.txt create mode 100644 bsp/esp32_p4_box/Kconfig create mode 100644 bsp/esp32_p4_box/LICENSE create mode 100644 bsp/esp32_p4_box/README.md create mode 100644 bsp/esp32_p4_box/esp32_p4_box.c create mode 100644 bsp/esp32_p4_box/esp32_p4_box_idf5.c create mode 100644 bsp/esp32_p4_box/idf_component.yml create mode 100644 bsp/esp32_p4_box/include/bsp/config.h create mode 100644 bsp/esp32_p4_box/include/bsp/display.h create mode 100644 bsp/esp32_p4_box/include/bsp/esp-bsp.h create mode 100644 bsp/esp32_p4_box/include/bsp/esp32_p4_box.h create mode 100644 bsp/esp32_p4_box/include/bsp/touch.h create mode 100644 bsp/esp32_p4_box/priv_include/bsp_err_check.h create mode 100644 examples/display/sdkconfig.bsp.esp32_p4_box create mode 100644 examples/display_audio_photo/sdkconfig.bsp.esp32_p4_box create mode 100644 examples/display_lvgl_demos/sdkconfig.bsp.esp32_p4_box diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml index b8985005..990024aa 100644 --- a/.github/workflows/upload_component.yml +++ b/.github/workflows/upload_component.yml @@ -17,7 +17,7 @@ jobs: uses: espressif/upload-components-ci-action@v1 with: directories: > - bsp/esp32_azure_iot_kit;bsp/esp32_s2_kaluga_kit;bsp/esp_wrover_kit;bsp/esp-box;bsp/esp32_s3_usb_otg;bsp/esp32_s3_eye;bsp/esp32_s3_lcd_ev_board;bsp/esp32_s3_korvo_2;bsp/esp-box-lite;bsp/esp32_lyrat;bsp/esp32_c3_lcdkit;bsp/esp-box-3;bsp/esp_bsp_generic;bsp/esp32_s3_korvo_1;bsp/esp32_p4_function_ev_board;bsp/m5stack_core_s3;bsp/m5dial;bsp/m5stack_core_2; + bsp/esp32_azure_iot_kit;bsp/esp32_s2_kaluga_kit;bsp/esp_wrover_kit;bsp/esp-box;bsp/esp32_s3_usb_otg;bsp/esp32_s3_eye;bsp/esp32_s3_lcd_ev_board;bsp/esp32_s3_korvo_2;bsp/esp-box-lite;bsp/esp32_lyrat;bsp/esp32_c3_lcdkit;bsp/esp-box-3;bsp/esp_bsp_generic;bsp/esp32_s3_korvo_1;bsp/esp32_p4_function_ev_board;bsp/m5stack_core_s3;bsp/m5dial;bsp/m5stack_core_2;bsp/esp32_p4_box; components/bh1750;components/ds18b20;components/es8311;components/es7210;components/fbm320;components/hts221;components/mag3110;components/mpu6050;components/esp_lvgl_port;components/icm42670; components/lcd_touch/esp_lcd_touch;components/lcd_touch/esp_lcd_touch_ft5x06;components/lcd_touch/esp_lcd_touch_gt911;components/lcd_touch/esp_lcd_touch_tt21100;components/lcd_touch/esp_lcd_touch_gt1151;components/lcd_touch/esp_lcd_touch_cst816s; components/lcd/esp_lcd_gc9a01;components/lcd/esp_lcd_ili9341;components/lcd/esp_lcd_ra8875;components/lcd_touch/esp_lcd_touch_stmpe610;components/lcd/esp_lcd_sh1107;components/lcd/esp_lcd_st7796;components/lcd/esp_lcd_gc9503;components/lcd/esp_lcd_ssd1681;components/lcd/esp_lcd_ili9881c; diff --git a/.github/workflows/upload_component_noglib.yml b/.github/workflows/upload_component_noglib.yml index 9c09bcc9..66b0fe5b 100644 --- a/.github/workflows/upload_component_noglib.yml +++ b/.github/workflows/upload_component_noglib.yml @@ -16,7 +16,7 @@ jobs: - name: Upload noglib version of BSPs # TODO: Extend this part to all BSPs env: - BSPs: "bsp/esp_wrover_kit bsp/esp32_s3_eye bsp/esp32_p4_function_ev_board bsp/m5stack_core_s3 bsp/m5stack_core_2 bsp/m5dial" + BSPs: "bsp/esp_wrover_kit bsp/esp32_s3_eye bsp/esp32_p4_function_ev_board bsp/m5stack_core_s3 bsp/m5stack_core_2 bsp/m5dial bsp/esp32_p4_box" run: | pip install idf-component-manager==1.* py-markdown-table --upgrade python .github/ci/bsp_noglib.py ${BSPs} @@ -28,6 +28,7 @@ jobs: bsp/m5stack_core_s3_noglib; bsp/m5dial_noglib; bsp/esp_wrover_kit_noglib; + bsp/esp32_p4_box_noglib; namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} dry_run: ${{ github.ref_name != 'master' || github.repository_owner != 'espressif' }} diff --git a/bsp/esp32_p4_box/CMakeLists.txt b/bsp/esp32_p4_box/CMakeLists.txt new file mode 100644 index 00000000..e6a1c963 --- /dev/null +++ b/bsp/esp32_p4_box/CMakeLists.txt @@ -0,0 +1,8 @@ + +idf_component_register( + SRCS "esp32_p4_box.c" "esp32_p4_box_idf5.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "priv_include" + REQUIRES driver + PRIV_REQUIRES esp_lcd usb spiffs fatfs +) diff --git a/bsp/esp32_p4_box/Kconfig b/bsp/esp32_p4_box/Kconfig new file mode 100644 index 00000000..f5fa0658 --- /dev/null +++ b/bsp/esp32_p4_box/Kconfig @@ -0,0 +1,100 @@ +menu "Board Support Package(ESP32-P4)" + + config BSP_ERROR_CHECK + bool "Enable error check in BSP" + default y + help + Error check assert the application before returning the error code. + + menu "I2C" + config BSP_I2C_NUM + int "I2C peripheral index" + default 1 + range 0 1 + help + ESP32P4 has two I2C peripherals, pick the one you want to use. + + config BSP_I2C_FAST_MODE + bool "Enable I2C fast mode" + default y + help + I2C has two speed modes: normal (100kHz) and fast (400kHz). + + config BSP_I2C_CLK_SPEED_HZ + int + default 400000 if BSP_I2C_FAST_MODE + default 100000 + endmenu + + menu "uSD card - Virtual File System" + config BSP_SD_FORMAT_ON_MOUNT_FAIL + bool "Format uSD card if mounting fails" + default n + help + The SDMMC host will format (FAT) the uSD card if it fails to mount the filesystem. + + config BSP_SD_MOUNT_POINT + string "uSD card mount point" + default "/sdcard" + help + Mount point of the uSD card in the Virtual File System + + endmenu + + menu "SPIFFS - Virtual File System" + config BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL + bool "Format SPIFFS if mounting fails" + default n + help + Format SPIFFS if it fails to mount the filesystem. + + config BSP_SPIFFS_MOUNT_POINT + string "SPIFFS mount point" + default "/spiffs" + help + Mount point of SPIFFS in the Virtual File System. + + config BSP_SPIFFS_PARTITION_LABEL + string "Partition label of SPIFFS" + default "storage" + help + Partition label which stores SPIFFS. + + config BSP_SPIFFS_MAX_FILES + int "Max files supported for SPIFFS VFS" + default 5 + help + Supported max files for SPIFFS in the Virtual File System. + endmenu + + menu "Display" + config BSP_DISPLAY_BRIGHTNESS_LEDC_CH + int "LEDC channel index" + default 1 + range 0 7 + help + LEDC channel is used to generate PWM signal that controls display brightness. + Set LEDC index that should be used. + + choice BSP_LCD_COLOR_FORMAT + prompt "Select LCD color format" + default BSP_LCD_COLOR_FORMAT_RGB565 + help + Select the LCD color format RGB565/RGB888. + + config BSP_LCD_COLOR_FORMAT_RGB565 + bool "RGB565" + config BSP_LCD_COLOR_FORMAT_RGB888 + bool "RGB888" + endchoice + + endmenu + + config BSP_I2S_NUM + int "I2S peripheral index" + default 1 + range 0 1 + help + ESP32S3 has two I2S peripherals, pick the one you want to use. + +endmenu diff --git a/bsp/esp32_p4_box/LICENSE b/bsp/esp32_p4_box/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/bsp/esp32_p4_box/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bsp/esp32_p4_box/README.md b/bsp/esp32_p4_box/README.md new file mode 100644 index 00000000..7a8bc356 --- /dev/null +++ b/bsp/esp32_p4_box/README.md @@ -0,0 +1,20 @@ +# BSP: ESP32-P4-BOX + +[![Component Registry](https://components.espressif.com/components/espressif/esp32_p4_box/badge.svg)](https://components.espressif.com/components/espressif/esp32_p4_box) + +ESP32-P4-BOX ... + + +### Capabilities and dependencies +| Capability | Available | Component |Version| +|-------------|------------------|----------------------------------------------------------------------------------------------------------|-------| +| DISPLAY |:heavy_check_mark:| [espressif/esp_lcd_st7701](https://components.espressif.com/components/espressif/esp_lcd_st7701) | ^1 | +| LVGL_PORT |:heavy_check_mark:| [espressif/esp_lvgl_port](https://components.espressif.com/components/espressif/esp_lvgl_port) | ^2 | +| TOUCH |:heavy_check_mark:|[espressif/esp_lcd_touch_gt911](https://components.espressif.com/components/espressif/esp_lcd_touch_gt911)| ^1 | +| BUTTONS |:heavy_check_mark:| [espressif/button](https://components.espressif.com/components/espressif/button) | >=2.5 | +| AUDIO |:heavy_check_mark:| [espressif/esp_codec_dev](https://components.espressif.com/components/espressif/esp_codec_dev) |^1,<1.2| +|AUDIO_SPEAKER|:heavy_check_mark:| | | +| AUDIO_MIC |:heavy_check_mark:| | | +| SDCARD |:heavy_check_mark:| idf | >=5.3 | +| IMU | :x: | | | + diff --git a/bsp/esp32_p4_box/esp32_p4_box.c b/bsp/esp32_p4_box/esp32_p4_box.c new file mode 100644 index 00000000..9e476ad0 --- /dev/null +++ b/bsp/esp32_p4_box/esp32_p4_box.c @@ -0,0 +1,656 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "driver/gpio.h" +#include "driver/ledc.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_spiffs.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_mipi_dsi.h" +#include "esp_ldo_regulator.h" +#include "esp_vfs_fat.h" +#include "usb/usb_host.h" +#include "sd_pwr_ctrl_by_on_chip_ldo.h" + +#include "esp_lcd_st7701.h" + +#include "bsp/esp32_p4_box.h" +#include "bsp/display.h" +#include "bsp/touch.h" +#include "esp_lcd_touch_gt911.h" +#include "bsp_err_check.h" +#include "esp_codec_dev_defaults.h" + +static const char *TAG = "ESP32_P4_BOX"; + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static lv_indev_t *disp_indev = NULL; +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) + +static esp_lcd_touch_handle_t tp; // LCD touch handle +sdmmc_card_t *bsp_sdcard = NULL; // Global uSD card handler +static bool i2c_initialized = false; +static TaskHandle_t usb_host_task; // USB Host Library task + +// This is just a wrapper to get function signature for espressif/button API callback +static uint8_t bsp_get_main_button(void *param); +static esp_err_t bsp_init_main_button(void *param); + +static const button_config_t bsp_button_config[BSP_BUTTON_NUM] = { + { + .type = BUTTON_TYPE_GPIO, + .gpio_button_config.gpio_num = BSP_BUTTON_CONFIG_IO, + .gpio_button_config.active_level = 0, + }, + { + .type = BUTTON_TYPE_GPIO, + .gpio_button_config.gpio_num = BSP_BUTTON_MUTE_IO, + .gpio_button_config.active_level = 0, + }, + { + .type = BUTTON_TYPE_CUSTOM, + .custom_button_config.button_custom_init = bsp_init_main_button, + .custom_button_config.button_custom_get_key_value = bsp_get_main_button, + .custom_button_config.button_custom_deinit = NULL, + .custom_button_config.active_level = 1, + .custom_button_config.priv = (void *) BSP_BUTTON_MAIN, + } +}; + +esp_err_t bsp_i2c_init(void) +{ + /* I2C was initialized before */ + if (i2c_initialized) { + return ESP_OK; + } + + const i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = BSP_I2C_SDA, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_io_num = BSP_I2C_SCL, + .scl_pullup_en = GPIO_PULLUP_DISABLE, + .master.clk_speed = CONFIG_BSP_I2C_CLK_SPEED_HZ + }; + BSP_ERROR_CHECK_RETURN_ERR(i2c_param_config(BSP_I2C_NUM, &i2c_conf)); + BSP_ERROR_CHECK_RETURN_ERR(i2c_driver_install(BSP_I2C_NUM, i2c_conf.mode, 0, 0, 0)); + + i2c_initialized = true; + + return ESP_OK; +} + +esp_err_t bsp_i2c_deinit(void) +{ + BSP_ERROR_CHECK_RETURN_ERR(i2c_driver_delete(BSP_I2C_NUM)); + i2c_initialized = false; + return ESP_OK; +} + +esp_err_t bsp_sdcard_mount(void) +{ + esp_ldo_channel_handle_t ldo_mipi_phy = NULL; + esp_ldo_channel_config_t ldo_sd_probe_config = { + .chan_id = BSP_LDO_PROBE_SD_CHAN, + .voltage_mv = BSP_LDO_PROBE_SD_VOLTAGE_MV, + }; + ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_sd_probe_config, &ldo_mipi_phy)); + + + const esp_vfs_fat_sdmmc_mount_config_t mount_config = { +#ifdef CONFIG_BSP_SD_FORMAT_ON_MOUNT_FAIL + .format_if_mount_failed = true, +#else + .format_if_mount_failed = false, +#endif + .max_files = 5, + .allocation_unit_size = 64 * 1024 + }; + + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; + + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = 4, + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + esp_err_t ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver"); + return ret; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; + + const sdmmc_slot_config_t slot_config = { + .clk = BSP_SD_CLK, + .cmd = BSP_SD_CMD, + .d0 = BSP_SD_D0, + .d1 = BSP_SD_D1, + .d2 = BSP_SD_D2, + .d3 = BSP_SD_D3, + .d4 = GPIO_NUM_NC, + .d5 = GPIO_NUM_NC, + .d6 = GPIO_NUM_NC, + .d7 = GPIO_NUM_NC, + .cd = SDMMC_SLOT_NO_CD, + .wp = SDMMC_SLOT_NO_WP, + .width = 4, + .flags = 0, + }; + + return esp_vfs_fat_sdmmc_mount(BSP_SD_MOUNT_POINT, &host, &slot_config, &mount_config, &bsp_sdcard); +} + +esp_err_t bsp_sdcard_unmount(void) +{ + return esp_vfs_fat_sdcard_unmount(BSP_SD_MOUNT_POINT, bsp_sdcard); +} + +esp_err_t bsp_spiffs_mount(void) +{ + esp_vfs_spiffs_conf_t conf = { + .base_path = CONFIG_BSP_SPIFFS_MOUNT_POINT, + .partition_label = CONFIG_BSP_SPIFFS_PARTITION_LABEL, + .max_files = CONFIG_BSP_SPIFFS_MAX_FILES, +#ifdef CONFIG_BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL + .format_if_mount_failed = true, +#else + .format_if_mount_failed = false, +#endif + }; + + esp_err_t ret_val = esp_vfs_spiffs_register(&conf); + + BSP_ERROR_CHECK_RETURN_ERR(ret_val); + + size_t total = 0, used = 0; + ret_val = esp_spiffs_info(conf.partition_label, &total, &used); + if (ret_val != ESP_OK) { + ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret_val)); + } else { + ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); + } + + return ret_val; +} + +esp_err_t bsp_spiffs_unmount(void) +{ + return esp_vfs_spiffs_unregister(CONFIG_BSP_SPIFFS_PARTITION_LABEL); +} + +esp_codec_dev_handle_t bsp_audio_codec_speaker_init(void) +{ + const audio_codec_data_if_t *i2s_data_if = bsp_audio_get_codec_itf(); + if (i2s_data_if == NULL) { + /* Initilize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); + /* Configure I2S peripheral and Power Amplifier */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_audio_init(NULL)); + i2s_data_if = bsp_audio_get_codec_itf(); + } + assert(i2s_data_if); + + const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio(); + + audio_codec_i2c_cfg_t i2c_cfg = { + .port = BSP_I2C_NUM, + .addr = ES8311_CODEC_DEFAULT_ADDR, + }; + const audio_codec_ctrl_if_t *i2c_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg); + BSP_NULL_CHECK(i2c_ctrl_if, NULL); + + esp_codec_dev_hw_gain_t gain = { + .pa_voltage = 5.0, + .codec_dac_voltage = 3.3, + }; + + es8311_codec_cfg_t es8311_cfg = { + .ctrl_if = i2c_ctrl_if, + .gpio_if = gpio_if, + .codec_mode = ESP_CODEC_DEV_WORK_MODE_DAC, + .pa_pin = BSP_POWER_AMP_IO, + .pa_reverted = false, + .master_mode = false, + .use_mclk = true, + .digital_mic = false, + .invert_mclk = false, + .invert_sclk = false, + .hw_gain = gain, + }; + const audio_codec_if_t *es8311_dev = es8311_codec_new(&es8311_cfg); + BSP_NULL_CHECK(es8311_dev, NULL); + + esp_codec_dev_cfg_t codec_dev_cfg = { + .dev_type = ESP_CODEC_DEV_TYPE_OUT, + .codec_if = es8311_dev, + .data_if = i2s_data_if, + }; + return esp_codec_dev_new(&codec_dev_cfg); +} + +esp_codec_dev_handle_t bsp_audio_codec_microphone_init(void) +{ + const audio_codec_data_if_t *i2s_data_if = bsp_audio_get_codec_itf(); + if (i2s_data_if == NULL) { + /* Initilize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); + /* Configure I2S peripheral and Power Amplifier */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_audio_init(NULL)); + i2s_data_if = bsp_audio_get_codec_itf(); + } + assert(i2s_data_if); + + audio_codec_i2c_cfg_t i2c_cfg = { + .port = BSP_I2C_NUM, + .addr = ES7210_CODEC_DEFAULT_ADDR, + }; + const audio_codec_ctrl_if_t *i2c_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg); + BSP_NULL_CHECK(i2c_ctrl_if, NULL); + + es7210_codec_cfg_t es7210_cfg = { + .ctrl_if = i2c_ctrl_if, + }; + const audio_codec_if_t *es7210_dev = es7210_codec_new(&es7210_cfg); + BSP_NULL_CHECK(es7210_dev, NULL); + + esp_codec_dev_cfg_t codec_es7210_dev_cfg = { + .dev_type = ESP_CODEC_DEV_TYPE_IN, + .codec_if = es7210_dev, + .data_if = i2s_data_if, + }; + return esp_codec_dev_new(&codec_es7210_dev_cfg); +} + +// Bit number used to represent command and parameter +#define LCD_LEDC_CH CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH + +esp_err_t bsp_display_brightness_init(void) +{ + // Setup LEDC peripheral for PWM backlight control + const ledc_channel_config_t LCD_backlight_channel = { + .gpio_num = BSP_LCD_BACKLIGHT, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LCD_LEDC_CH, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = 1, + .duty = 0, + .hpoint = 0 + }; + const ledc_timer_config_t LCD_backlight_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .duty_resolution = LEDC_TIMER_10_BIT, + .timer_num = 1, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK + }; + + BSP_ERROR_CHECK_RETURN_ERR(ledc_timer_config(&LCD_backlight_timer)); + BSP_ERROR_CHECK_RETURN_ERR(ledc_channel_config(&LCD_backlight_channel)); + return ESP_OK; +} + +esp_err_t bsp_display_brightness_set(int brightness_percent) +{ + if (brightness_percent > 100) { + brightness_percent = 100; + } + if (brightness_percent < 0) { + brightness_percent = 0; + } + + ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent); + uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023 + BSP_ERROR_CHECK_RETURN_ERR(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle)); + BSP_ERROR_CHECK_RETURN_ERR(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH)); + return ESP_OK; +} + +esp_err_t bsp_display_backlight_off(void) +{ + return bsp_display_brightness_set(0); +} + +esp_err_t bsp_display_backlight_on(void) +{ + return bsp_display_brightness_set(100); +} + +static esp_err_t bsp_enable_dsi_phy_power(void) +{ +#if BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 + // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state + esp_ldo_channel_handle_t phy_pwr_chan = NULL; + esp_ldo_channel_config_t ldo_cfg = { + .chan_id = BSP_MIPI_DSI_PHY_PWR_LDO_CHAN, + .voltage_mv = BSP_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, + }; + ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan), TAG, "Acquire LDO channel for DPHY failed"); + ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); +#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 + + return ESP_OK; +} + +esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) +{ + esp_err_t ret = ESP_OK; + bsp_lcd_handles_t handles; + ret = bsp_display_new_with_handles(config, &handles); + + *ret_panel = handles.panel; + *ret_io = handles.io; + + return ret; +} + +esp_err_t bsp_display_new_with_handles(const bsp_display_config_t *config, bsp_lcd_handles_t *ret_handles) +{ + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed"); + ESP_RETURN_ON_ERROR(bsp_enable_dsi_phy_power(), TAG, "DSI PHY power failed"); + + /* create MIPI DSI bus first, it will initialize the DSI PHY as well */ + esp_lcd_dsi_bus_handle_t mipi_dsi_bus; + esp_lcd_dsi_bus_config_t bus_config = ST7701_PANEL_BUS_DSI_2CH_CONFIG(); + ESP_RETURN_ON_ERROR(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus), TAG, "New DSI bus init failed"); + + ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); + // we use DBI interface to send LCD commands and parameters + esp_lcd_panel_io_handle_t io; + esp_lcd_dbi_io_config_t dbi_config = ST7701_PANEL_IO_DBI_CONFIG(); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io), err, TAG, "New panel IO failed"); + + esp_lcd_panel_handle_t disp_panel = NULL; + + // create st7701 control panel + ESP_LOGI(TAG, "Install st7701 LCD control panel"); + +#if CONFIG_BSP_LCD_COLOR_FORMAT_RGB888 + const esp_lcd_dpi_panel_config_t dpi_config = ST7701_480_360_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB888); +#else + const esp_lcd_dpi_panel_config_t dpi_config = ST7701_480_360_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB565); +#endif + st7701_vendor_config_t vendor_config = { + .flags.use_mipi_interface = 1, + .mipi_config = { + .dsi_bus = mipi_dsi_bus, + .dpi_config = &dpi_config, + }, + }; + esp_lcd_panel_dev_config_t lcd_dev_config = { + .bits_per_pixel = 16, + .rgb_ele_order = BSP_LCD_COLOR_SPACE, + .reset_gpio_num = -1,//BSP_LCD_RST, + .vendor_config = &vendor_config, + .flags = { + .reset_active_high = 0, + } + }; + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7701(io, &lcd_dev_config, &disp_panel), err, TAG, "New LCD panel st7701 failed"); + ESP_GOTO_ON_ERROR(esp_lcd_panel_reset(disp_panel), err, TAG, "LCD panel reset failed"); + ESP_GOTO_ON_ERROR(esp_lcd_panel_init(disp_panel), err, TAG, "LCD panel init failed"); + ESP_GOTO_ON_ERROR(esp_lcd_panel_disp_on_off(disp_panel, true), err, TAG, "LCD panel ON failed"); + + /* Return all handles */ + ret_handles->io = io; + ret_handles->mipi_dsi_bus = mipi_dsi_bus; + ret_handles->panel = disp_panel; + ret_handles->control = NULL; + + ESP_LOGI(TAG, "Display initialized"); + + return ret; + +err: + if (disp_panel) { + esp_lcd_panel_del(disp_panel); + } + if (io) { + esp_lcd_panel_io_del(io); + } + if (mipi_dsi_bus) { + esp_lcd_del_dsi_bus(mipi_dsi_bus); + } + return ret; +} + +esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch) +{ + /* Initilize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); + + /* Initialize touch */ + const esp_lcd_touch_config_t tp_cfg = { + .x_max = BSP_LCD_H_RES, + .y_max = BSP_LCD_V_RES, + .rst_gpio_num = BSP_LCD_TOUCH_RST, // Shared with LCD reset + .int_gpio_num = BSP_LCD_TOUCH_INT, + .levels = { + .reset = 0, + .interrupt = 0, + }, + .flags = { + .swap_xy = 0, + .mirror_x = 0, + .mirror_y = 0, + }, + }; + esp_lcd_panel_io_handle_t tp_io_handle = NULL; + const esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); + ESP_RETURN_ON_ERROR(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)BSP_I2C_NUM, &tp_io_config, &tp_io_handle), TAG, ""); + return esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, ret_touch); +} + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static lv_display_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg) +{ + assert(cfg != NULL); + bsp_lcd_handles_t lcd_panels; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new_with_handles(NULL, &lcd_panels)); + + /* Add LCD screen */ + ESP_LOGD(TAG, "Add LCD screen"); + const lvgl_port_display_cfg_t disp_cfg = { + .io_handle = lcd_panels.io, + .panel_handle = lcd_panels.panel, + .control_handle = lcd_panels.control, + .buffer_size = cfg->buffer_size, + .double_buffer = cfg->double_buffer, + .hres = BSP_LCD_H_RES, + .vres = BSP_LCD_V_RES, + .monochrome = false, + /* Rotation values must be same as used in esp_lcd for initial settings of the screen */ + .rotation = { + .swap_xy = false, + .mirror_x = true, + .mirror_y = true, + }, +#if LVGL_VERSION_MAJOR >= 9 +#if CONFIG_BSP_LCD_COLOR_FORMAT_RGB888 + .color_format = LV_COLOR_FORMAT_RGB888, +#else + .color_format = LV_COLOR_FORMAT_RGB565, +#endif +#endif + .flags = { + .buff_dma = cfg->flags.buff_dma, + .buff_spiram = cfg->flags.buff_spiram, +#if LVGL_VERSION_MAJOR >= 9 + .swap_bytes = (BSP_LCD_BIGENDIAN ? true : false), +#endif + .sw_rotate = cfg->flags.sw_rotate, /* Only SW rotation is supported for 90° and 270° */ + } + }; + + return lvgl_port_add_disp_dsi(&disp_cfg, NULL); +} + +static lv_indev_t *bsp_display_indev_init(lv_display_t *disp) +{ + BSP_ERROR_CHECK_RETURN_NULL(bsp_touch_new(NULL, &tp)); + assert(tp); + + /* Add touch input (for selected screen) */ + const lvgl_port_touch_cfg_t touch_cfg = { + .disp = disp, + .handle = tp, + }; + + return lvgl_port_add_touch(&touch_cfg); +} + +lv_display_t *bsp_display_start(void) +{ + bsp_display_cfg_t cfg = { + .lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(), + .buffer_size = BSP_LCD_DRAW_BUFF_SIZE, + .double_buffer = BSP_LCD_DRAW_BUFF_DOUBLE, + .flags = { +#if CONFIG_BSP_LCD_COLOR_FORMAT_RGB888 + .buff_dma = false, +#else + .buff_dma = true, +#endif + .buff_spiram = false, + .sw_rotate = true, + } + }; + return bsp_display_start_with_config(&cfg); +} + +lv_display_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg) +{ + lv_display_t *disp; + + assert(cfg != NULL); + BSP_ERROR_CHECK_RETURN_NULL(lvgl_port_init(&cfg->lvgl_port_cfg)); + + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); + + BSP_NULL_CHECK(disp = bsp_display_lcd_init(cfg), NULL); + + BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL); + + return disp; +} + +lv_indev_t *bsp_display_get_input_dev(void) +{ + return disp_indev; +} + +void bsp_display_rotate(lv_display_t *disp, lv_disp_rotation_t rotation) +{ + lv_disp_set_rotation(disp, rotation); +} + +bool bsp_display_lock(uint32_t timeout_ms) +{ + return lvgl_port_lock(timeout_ms); +} + +void bsp_display_unlock(void) +{ + lvgl_port_unlock(); +} + +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) + +static void usb_lib_task(void *arg) +{ + while (1) { + // Start handling system events + uint32_t event_flags; + usb_host_lib_handle_events(portMAX_DELAY, &event_flags); + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { + ESP_ERROR_CHECK(usb_host_device_free_all()); + } + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + ESP_LOGI(TAG, "USB: All devices freed"); + // Continue handling USB events to allow device reconnection + // The only way this task can be stopped is by calling bsp_usb_host_stop() + } + } +} + +esp_err_t bsp_usb_host_start(bsp_usb_host_power_mode_t mode, bool limit_500mA) +{ + //Install USB Host driver. Should only be called once in entire application + ESP_LOGI(TAG, "Installing USB Host"); + const usb_host_config_t host_config = { + .skip_phy_setup = false, + .intr_flags = ESP_INTR_FLAG_LEVEL1, + }; + BSP_ERROR_CHECK_RETURN_ERR(usb_host_install(&host_config)); + + // Create a task that will handle USB library events + if (xTaskCreate(usb_lib_task, "usb_lib", 4096, NULL, 10, &usb_host_task) != pdTRUE) { + ESP_LOGE(TAG, "Creating USB host lib task failed"); + abort(); + } + + return ESP_OK; +} + +esp_err_t bsp_usb_host_stop(void) +{ + usb_host_uninstall(); + if (usb_host_task) { + vTaskSuspend(usb_host_task); + vTaskDelete(usb_host_task); + } + return ESP_OK; +} + +static uint8_t bsp_get_main_button(void *param) +{ + assert(tp); +#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0) + uint8_t home_btn_val = 0x00; + esp_lcd_touch_get_button_state(tp, 0, &home_btn_val); + return home_btn_val ? true : false; +#else + ESP_LOGE(TAG, "Button main is inaccessible"); + return false; +#endif +} + +static esp_err_t bsp_init_main_button(void *param) +{ + if (tp == NULL) { + BSP_ERROR_CHECK_RETURN_ERR(bsp_touch_new(NULL, &tp)); + } + return ESP_OK; +} + +esp_err_t bsp_iot_button_create(button_handle_t btn_array[], int *btn_cnt, int btn_array_size) +{ + esp_err_t ret = ESP_OK; + if ((btn_array_size < BSP_BUTTON_NUM) || + (btn_array == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + if (btn_cnt) { + *btn_cnt = 0; + } + for (int i = 0; i < BSP_BUTTON_NUM; i++) { + btn_array[i] = iot_button_create(&bsp_button_config[i]); + if (btn_array[i] == NULL) { + ret = ESP_FAIL; + break; + } + if (btn_cnt) { + (*btn_cnt)++; + } + } + return ret; +} diff --git a/bsp/esp32_p4_box/esp32_p4_box_idf5.c b/bsp/esp32_p4_box/esp32_p4_box_idf5.c new file mode 100644 index 00000000..e47bf7a4 --- /dev/null +++ b/bsp/esp32_p4_box/esp32_p4_box_idf5.c @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_err.h" +#include "bsp/esp32_p4_box.h" +#include "bsp_err_check.h" +#include "esp_codec_dev_defaults.h" + +static const char *TAG = "ESP32_P4_BOX"; + +static i2s_chan_handle_t i2s_tx_chan = NULL; +static i2s_chan_handle_t i2s_rx_chan = NULL; +static const audio_codec_data_if_t *i2s_data_if = NULL; /* Codec data interface */ + + +/* Can be used for i2s_std_gpio_config_t and/or i2s_std_config_t initialization */ +#define BSP_I2S_GPIO_CFG \ + { \ + .mclk = BSP_I2S_MCLK, \ + .bclk = BSP_I2S_SCLK, \ + .ws = BSP_I2S_LCLK, \ + .dout = BSP_I2S_DOUT, \ + .din = BSP_I2S_DSIN, \ + .invert_flags = { \ + .mclk_inv = false, \ + .bclk_inv = false, \ + .ws_inv = false, \ + }, \ + } + +/* This configuration is used by default in bsp_audio_init() */ +#define BSP_I2S_DUPLEX_MONO_CFG(_sample_rate) \ + { \ + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(_sample_rate), \ + .slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), \ + .gpio_cfg = BSP_I2S_GPIO_CFG, \ + } + +esp_err_t bsp_audio_init(const i2s_std_config_t *i2s_config) +{ + esp_err_t ret = ESP_FAIL; + if (i2s_tx_chan && i2s_rx_chan) { + /* Audio was initialized before */ + return ESP_OK; + } + + /* Setup I2S peripheral */ + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(CONFIG_BSP_I2S_NUM, I2S_ROLE_MASTER); + chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer + BSP_ERROR_CHECK_RETURN_ERR(i2s_new_channel(&chan_cfg, &i2s_tx_chan, &i2s_rx_chan)); + + /* Setup I2S channels */ + const i2s_std_config_t std_cfg_default = BSP_I2S_DUPLEX_MONO_CFG(22050); + const i2s_std_config_t *p_i2s_cfg = &std_cfg_default; + if (i2s_config != NULL) { + p_i2s_cfg = i2s_config; + } + + if (i2s_tx_chan != NULL) { + ESP_GOTO_ON_ERROR(i2s_channel_init_std_mode(i2s_tx_chan, p_i2s_cfg), err, TAG, "I2S channel initialization failed"); + ESP_GOTO_ON_ERROR(i2s_channel_enable(i2s_tx_chan), err, TAG, "I2S enabling failed"); + } + if (i2s_rx_chan != NULL) { + ESP_GOTO_ON_ERROR(i2s_channel_init_std_mode(i2s_rx_chan, p_i2s_cfg), err, TAG, "I2S channel initialization failed"); + ESP_GOTO_ON_ERROR(i2s_channel_enable(i2s_rx_chan), err, TAG, "I2S enabling failed"); + } + + audio_codec_i2s_cfg_t i2s_cfg = { + .port = CONFIG_BSP_I2S_NUM, + .rx_handle = i2s_rx_chan, + .tx_handle = i2s_tx_chan, + }; + i2s_data_if = audio_codec_new_i2s_data(&i2s_cfg); + BSP_NULL_CHECK_GOTO(i2s_data_if, err); + + return ESP_OK; + +err: + if (i2s_tx_chan) { + i2s_del_channel(i2s_tx_chan); + } + if (i2s_rx_chan) { + i2s_del_channel(i2s_rx_chan); + } + + return ret; +} + +const audio_codec_data_if_t *bsp_audio_get_codec_itf(void) +{ + return i2s_data_if; +} diff --git a/bsp/esp32_p4_box/idf_component.yml b/bsp/esp32_p4_box/idf_component.yml new file mode 100644 index 00000000..7ead3460 --- /dev/null +++ b/bsp/esp32_p4_box/idf_component.yml @@ -0,0 +1,28 @@ +version: "1.0.0" +description: Board Support Package (BSP) for ESP32-P4-BOX +url: https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_p4_box + +targets: + - esp32p4 + +tags: + - bsp + +dependencies: + idf: ">=5.3" + esp_lcd_st7701: "^1" + esp_lcd_touch_gt911: "^1" + lvgl/lvgl: ">=8,<10" + + espressif/esp_lvgl_port: + version: "^2" + public: true + override_path: "../../components/esp_lvgl_port" + + esp_codec_dev: + version: "^1,<1.2" + public: true + + button: + version: ">=2.5" + public: true diff --git a/bsp/esp32_p4_box/include/bsp/config.h b/bsp/esp32_p4_box/include/bsp/config.h new file mode 100644 index 00000000..f3cb5ebe --- /dev/null +++ b/bsp/esp32_p4_box/include/bsp/config.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/************************************************************************************************** + * BSP configuration + **************************************************************************************************/ +// By default, this BSP is shipped with LVGL graphical library. Enabling this option will exclude it. +// If you want to use BSP without LVGL, select BSP version with 'noglib' suffix. +#if !defined(BSP_CONFIG_NO_GRAPHIC_LIB) // Check if the symbol is not coming from compiler definitions (-D...) +#define BSP_CONFIG_NO_GRAPHIC_LIB (0) +#endif diff --git a/bsp/esp32_p4_box/include/bsp/display.h b/bsp/esp32_p4_box/include/bsp/display.h new file mode 100644 index 00000000..2343d55f --- /dev/null +++ b/bsp/esp32_p4_box/include/bsp/display.h @@ -0,0 +1,172 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" +#include "esp_lcd_mipi_dsi.h" +#include "sdkconfig.h" + +/* LCD color formats */ +#define ESP_LCD_COLOR_FORMAT_RGB565 (1) +#define ESP_LCD_COLOR_FORMAT_RGB888 (2) + +/* LCD display color format */ +#if CONFIG_BSP_LCD_COLOR_FORMAT_RGB888 +#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB888) +#else +#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB565) +#endif +/* LCD display color bytes endianess */ +#define BSP_LCD_BIGENDIAN (0) +/* LCD display color bits */ +#define BSP_LCD_BITS_PER_PIXEL (16) +/* LCD display color space */ +#define BSP_LCD_COLOR_SPACE (ESP_LCD_COLOR_SPACE_RGB) + +/* LCD display definition */ +#define BSP_LCD_H_RES (480) +#define BSP_LCD_V_RES (360) + +#define BSP_LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes +#define BSP_LCD_MIPI_DSI_LANE_BITRATE_MBPS (1000) // 1Gbps + +#define BSP_MIPI_DSI_PHY_PWR_LDO_CHAN (3) // LDO_VO3 is connected to VDD_MIPI_DPHY +#define BSP_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief BSP display configuration structure + * + */ +typedef struct { + int dummy; +} bsp_display_config_t; + +/** + * @brief BSP display return handles + * + */ +typedef struct { + esp_lcd_dsi_bus_handle_t mipi_dsi_bus; /*!< MIPI DSI bus handle */ + esp_lcd_panel_io_handle_t io; /*!< ESP LCD IO handle */ + esp_lcd_panel_handle_t panel; /*!< ESP LCD panel (color) handle */ + esp_lcd_panel_handle_t control; /*!< ESP LCD panel (control) handle */ +} bsp_lcd_handles_t; + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * esp_lcd_del_dsi_bus(mipi_dsi_bus); + * \endcode + * + * @param[in] config display configuration + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_del(control); + * esp_lcd_panel_io_del(io); + * esp_lcd_del_dsi_bus(mipi_dsi_bus); + * \endcode + * + * @param[in] config display configuration + * @param[out] ret_handles all esp_lcd handles in one structure + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new_with_handles(const bsp_display_config_t *config, bsp_lcd_handles_t *ret_handles); + +/** + * @brief Initialize display's brightness + * + * Brightness is controlled with PWM signal to a pin controlling backlight. + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t bsp_display_brightness_init(void); + +/** + * @brief Set display's brightness + * + * Brightness is controlled with PWM signal to a pin controlling backlight. + * Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new() + * + * @param[in] brightness_percent Brightness in [%] + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t bsp_display_brightness_set(int brightness_percent); + +/** + * @brief Turn on display backlight + * + * Brightness is controlled with PWM signal to a pin controlling backlight. + * Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new() + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t bsp_display_backlight_on(void); + +/** + * @brief Turn off display backlight + * + * Brightness is controlled with PWM signal to a pin controlling backlight. + * Brightness must be already initialized by calling bsp_display_brightness_init() or bsp_display_new() + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t bsp_display_backlight_off(void); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/esp32_p4_box/include/bsp/esp-bsp.h b/bsp/esp32_p4_box/include/bsp/esp-bsp.h new file mode 100644 index 00000000..8fd2b89b --- /dev/null +++ b/bsp/esp32_p4_box/include/bsp/esp-bsp.h @@ -0,0 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include "bsp/esp32_p4_box.h" diff --git a/bsp/esp32_p4_box/include/bsp/esp32_p4_box.h b/bsp/esp32_p4_box/include/bsp/esp32_p4_box.h new file mode 100644 index 00000000..77c32909 --- /dev/null +++ b/bsp/esp32_p4_box/include/bsp/esp32_p4_box.h @@ -0,0 +1,471 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ESP BSP: ESP32-P4-BOX + */ + +#pragma once + +#include "sdkconfig.h" +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "driver/sdmmc_host.h" +#include "bsp/config.h" +#include "bsp/display.h" +#include "sdkconfig.h" +#include "esp_codec_dev.h" + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) +#include "driver/i2s.h" +#else +#include "driver/i2s_std.h" +#endif + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +#include "lvgl.h" +#include "esp_lvgl_port.h" +#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0 + +/************************************************************************************************** + * BSP Capabilities + **************************************************************************************************/ + +#define BSP_CAPS_DISPLAY 1 +#define BSP_CAPS_TOUCH 1 +#define BSP_CAPS_BUTTONS 1 +#define BSP_CAPS_AUDIO 1 +#define BSP_CAPS_AUDIO_SPEAKER 1 +#define BSP_CAPS_AUDIO_MIC 1 +#define BSP_CAPS_SDCARD 1 +#define BSP_CAPS_IMU 0 + +/************************************************************************************************** + * ESP-BOX pinout + **************************************************************************************************/ +/* I2C */ +#define BSP_I2C_SCL (GPIO_NUM_14) +#define BSP_I2C_SDA (GPIO_NUM_15) + +/* Audio */ +#define BSP_I2S_SCLK (GPIO_NUM_29) +#define BSP_I2S_MCLK (GPIO_NUM_30) +#define BSP_I2S_LCLK (GPIO_NUM_27) +#define BSP_I2S_DOUT (GPIO_NUM_26) // To Codec ES8311 +#define BSP_I2S_DSIN (GPIO_NUM_28) // From ADC ES7210 +#define BSP_POWER_AMP_IO (GPIO_NUM_10) +#define BSP_MUTE_STATUS (GPIO_NUM_46) + +/* Display */ +#define BSP_LCD_BACKLIGHT (GPIO_NUM_48) +#define BSP_LCD_RST (GPIO_NUM_11) +#define BSP_LCD_TOUCH_RST (GPIO_NUM_12) +#define BSP_LCD_TOUCH_INT (GPIO_NUM_13) + +/* Buttons */ +#define BSP_BUTTON_CONFIG_IO (GPIO_NUM_35) +#define BSP_BUTTON_MUTE_IO (GPIO_NUM_46) + +/* uSD card */ +#define BSP_SD_D0 (GPIO_NUM_39) +#define BSP_SD_D1 (GPIO_NUM_40) +#define BSP_SD_D2 (GPIO_NUM_41) +#define BSP_SD_D3 (GPIO_NUM_42) +#define BSP_SD_CMD (GPIO_NUM_44) +#define BSP_SD_CLK (GPIO_NUM_43) + +/* LDO */ +#define BSP_LDO_PROBE_SD_CHAN 4 +#define BSP_LDO_PROBE_SD_VOLTAGE_MV 3300 + +/* PCIE connector */ +/* + * |------------| + * | IO1 IO12 | + * | IO2 IO13 | + * | IO3 IO14 | + * | IO4 IO15 | + * | IO5 IO16 | + * | IO6 IO17 | + * | GND IO18 | + * | GND IO19 | + * | IO7 IO20 | + * | IO8 IO21 | + * | IO9 IO22 | + * |------------| + * | GND GND | + * | IO10 IO23 | + * | GND GND | + * | IO11 IO24 | + * | GND GND | + * | 3V3 3V3 | + * | 5V 5V | + * |------------| + */ +#define BSP_PCIE_IO1 GPIO_NUM_49 // ADC +#define BSP_PCIE_IO2 GPIO_NUM_40 // SD1_D1 +#define BSP_PCIE_IO3 GPIO_NUM_44 // SD1_CMD +#define BSP_PCIE_IO4 GPIO_NUM_39 // SD1_D0 +#define BSP_PCIE_IO5 GPIO_NUM_41 // SD1_D2 +#define BSP_PCIE_IO6 GPIO_NUM_2 +#define BSP_PCIE_IO7 GPIO_NUM_4 +#define BSP_PCIE_IO8 GPIO_NUM_51 +#define BSP_PCIE_IO9 GPIO_NUM_53 +#define BSP_PCIE_IO10 GPIO_NUM_6 +#define BSP_PCIE_IO11 GPIO_NUM_32 +#define BSP_PCIE_IO12 GPIO_NUM_43 // SD1_CLK +#define BSP_PCIE_IO13 GPIO_NUM_42 // SD1_D3 +#define BSP_PCIE_IO14 GPIO_NUM_37 // U0TXD +#define BSP_PCIE_IO15 GPIO_NUM_38 // U0RXD +#define BSP_PCIE_IO16 GPIO_NUM_50 +#define BSP_PCIE_IO17 GPIO_NUM_3 +#define BSP_PCIE_IO18 BSP_USB_NEG +#define BSP_PCIE_IO19 BSP_USB_POS +#define BSP_PCIE_IO20 GPIO_NUM_5 +#define BSP_PCIE_IO21 GPIO_NUM_52 // I2C_SCL +#define BSP_PCIE_IO22 GPIO_NUM_54 // I2C_SDA + +/* Buttons */ +typedef enum { + BSP_BUTTON_CONFIG = 0, + BSP_BUTTON_MUTE, + BSP_BUTTON_MAIN, + BSP_BUTTON_NUM +} bsp_button_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + * + * I2S audio interface + * + * There are two devices connected to the I2S peripheral: + * - Codec ES8311 for output (playback) path + * - ADC ES7210 for input (recording) path + * + * For speaker initialization use bsp_audio_codec_speaker_init() which is inside initialize I2S with bsp_audio_init(). + * For microphone initialization use bsp_audio_codec_microphone_init() which is inside initialize I2S with bsp_audio_init(). + * After speaker or microphone initialization, use functions from esp_codec_dev for play/record audio. + * Example audio play: + * \code{.c} + * esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME); + * esp_codec_dev_open(spk_codec_dev, &fs); + * esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read_from_spiffs); + * esp_codec_dev_close(spk_codec_dev); + * \endcode + **************************************************************************************************/ + +/** + * @brief Init audio + * + * @note There is no deinit audio function. Users can free audio resources by calling i2s_del_channel() + * @warning The type of i2s_config param is depending on IDF version. + * @param[in] i2s_config I2S configuration. Pass NULL to use default values (Mono, duplex, 16bit, 22050 Hz) + * @return + * - ESP_OK On success + * - ESP_ERR_NOT_SUPPORTED The communication mode is not supported on the current chip + * - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration + * - ESP_ERR_NOT_FOUND No available I2S channel found + * - ESP_ERR_NO_MEM No memory for storing the channel information + * - ESP_ERR_INVALID_STATE This channel has not initialized or already started + */ +esp_err_t bsp_audio_init(const i2s_std_config_t *i2s_config); + +/** + * @brief Get codec I2S interface (initialized in bsp_audio_init) + * + * @return + * - Pointer to codec I2S interface handle or NULL when error occurred + */ +const audio_codec_data_if_t *bsp_audio_get_codec_itf(void); + +/** + * @brief Initialize speaker codec device + * + * @return Pointer to codec device handle or NULL when error occurred + */ +esp_codec_dev_handle_t bsp_audio_codec_speaker_init(void); + +/** + * @brief Initialize microphone codec device + * + * @return Pointer to codec device handle or NULL when error occurred + */ +esp_codec_dev_handle_t bsp_audio_codec_microphone_init(void); + +/************************************************************************************************** + * + * I2C interface + * + * There are multiple devices connected to I2C peripheral: + * - Codec ES8311 (configuration only) + * - LCD Touch controller + **************************************************************************************************/ +#define BSP_I2C_NUM CONFIG_BSP_I2C_NUM + +/** + * @brief Init I2C driver + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG I2C parameter error + * - ESP_FAIL I2C driver installation error + * + */ +esp_err_t bsp_i2c_init(void); + +/** + * @brief Deinit I2C driver and free its resources + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG I2C parameter error + * + */ +esp_err_t bsp_i2c_deinit(void); + +/************************************************************************************************** + * + * SPIFFS + * + * After mounting the SPIFFS, it can be accessed with stdio functions ie.: + * \code{.c} + * FILE* f = fopen(BSP_SPIFFS_MOUNT_POINT"/hello.txt", "w"); + * fprintf(f, "Hello World!\n"); + * fclose(f); + * \endcode + **************************************************************************************************/ +#define BSP_SPIFFS_MOUNT_POINT CONFIG_BSP_SPIFFS_MOUNT_POINT + +/** + * @brief Mount SPIFFS to virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_register was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes + */ +esp_err_t bsp_spiffs_mount(void); + +/** + * @brief Unmount SPIFFS from virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain SPIFFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_unregister was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes + */ +esp_err_t bsp_spiffs_unmount(void); + +/************************************************************************************************** + * + * uSD card + * + * After mounting the uSD card, it can be accessed with stdio functions ie.: + * \code{.c} + * FILE* f = fopen(BSP_MOUNT_POINT"/hello.txt", "w"); + * fprintf(f, "Hello %s!\n", bsp_sdcard->cid.name); + * fclose(f); + * \endcode + **************************************************************************************************/ +#define BSP_SD_MOUNT_POINT CONFIG_BSP_SD_MOUNT_POINT +extern sdmmc_card_t *bsp_sdcard; + +/** + * @brief Mount microSD card to virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called + * - ESP_ERR_NO_MEM if memory cannot be allocated + * - ESP_FAIL if partition cannot be mounted + * - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers + */ +esp_err_t bsp_sdcard_mount(void); + +/** + * @brief Unmount microSD card from virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from wear levelling library, SPI flash driver, or FATFS drivers + */ +esp_err_t bsp_sdcard_unmount(void); + +/************************************************************************************************** + * + * LCD interface + * + * ESP-BOX is shipped with 2.4inch ST7789 display controller. + * It features 16-bit colors, 320x240 resolution and capacitive touch controller. + * + * LVGL is used as graphics library. LVGL is NOT thread safe, therefore the user must take LVGL mutex + * by calling bsp_display_lock() before calling and LVGL API (lv_...) and then give the mutex with + * bsp_display_unlock(). + * + * Display's backlight must be enabled explicitly by calling bsp_display_backlight_on() + **************************************************************************************************/ + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) + +#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * 50) // Frame buffer size in pixels +#define BSP_LCD_DRAW_BUFF_DOUBLE (0) + +/** + * @brief BSP display configuration structure + * + */ +typedef struct { + lvgl_port_cfg_t lvgl_port_cfg; /*!< LVGL port configuration */ + uint32_t buffer_size; /*!< Size of the buffer for the screen in pixels */ + bool double_buffer; /*!< True, if should be allocated two buffers */ + struct { + unsigned int buff_dma: 1; /*!< Allocated LVGL buffer will be DMA capable */ + unsigned int buff_spiram: 1; /*!< Allocated LVGL buffer will be in PSRAM */ + unsigned int sw_rotate: 1; /*!< Use software rotation (slower) */ + } flags; +} bsp_display_cfg_t; + +/** + * @brief Initialize display + * + * This function initializes SPI, display controller and starts LVGL handling task. + * LCD backlight must be enabled separately by calling bsp_display_brightness_set() + * + * @return Pointer to LVGL display or NULL when error occured + */ +lv_display_t *bsp_display_start(void); + +/** + * @brief Initialize display + * + * This function initializes SPI, display controller and starts LVGL handling task. + * LCD backlight must be enabled separately by calling bsp_display_brightness_set() + * + * @param cfg display configuration + * + * @return Pointer to LVGL display or NULL when error occured + */ +lv_display_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg); + +/** + * @brief Get pointer to input device (touch, buttons, ...) + * + * @note The LVGL input device is initialized in bsp_display_start() function. + * + * @return Pointer to LVGL input device or NULL when not initialized + */ +lv_indev_t *bsp_display_get_input_dev(void); + +/** + * @brief Take LVGL mutex + * + * @param timeout_ms Timeout in [ms]. 0 will block indefinitely. + * @return true Mutex was taken + * @return false Mutex was NOT taken + */ +bool bsp_display_lock(uint32_t timeout_ms); + +/** + * @brief Give LVGL mutex + * + */ +void bsp_display_unlock(void); + +/** + * @brief Rotate screen + * + * Display must be already initialized by calling bsp_display_start() + * + * @param[in] disp Pointer to LVGL display + * @param[in] rotation Angle of the display rotation + */ +void bsp_display_rotate(lv_display_t *disp, lv_disp_rotation_t rotation); +#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0 + +/************************************************************************************************** + * + * Button + * + * There are three buttons on ESP-BOX: + * - Reset: Not programable + * - Config: Controls boot mode during reset. Can be programmed after application starts + * - Mute: This button is wired to Logic Gates and its result is mapped to GPIO_NUM_1 + **************************************************************************************************/ + +/** + * @brief Initialize all buttons + * + * Returned button handlers must be used with espressif/button component API + * + * @note For LCD panel button which is defined as BSP_BUTTON_MAIN, bsp_display_start should + * be called before call this function. + * + * @param[out] btn_array Output button array + * @param[out] btn_cnt Number of button handlers saved to btn_array, can be NULL + * @param[in] btn_array_size Size of output button array. Must be at least BSP_BUTTON_NUM + * @return + * - ESP_OK All buttons initialized + * - ESP_ERR_INVALID_ARG btn_array is too small or NULL + * - ESP_FAIL Underlaying iot_button_create failed + */ +esp_err_t bsp_iot_button_create(button_handle_t btn_array[], int *btn_cnt, int btn_array_size); + +/************************************************************************************************** + * + * USB + * + **************************************************************************************************/ + + +/** + * @brief Power modes of USB Host connector + */ +typedef enum bsp_usb_host_power_mode_t { + BSP_USB_HOST_POWER_MODE_USB_DEV, //!< Power from USB DEV port +} bsp_usb_host_power_mode_t; + +/** + * @brief Start USB host + * + * This is a one-stop-shop function that will configure the board for USB Host mode + * and start USB Host library + * + * @param[in] mode USB Host connector power mode (Not used on this board) + * @param[in] limit_500mA Limit output current to 500mA (Not used on this board) + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Memory cannot be allocated + */ +esp_err_t bsp_usb_host_start(bsp_usb_host_power_mode_t mode, bool limit_500mA); + +/** + * @brief Stop USB host + * + * USB Host lib will be uninstalled and power from connector removed. + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t bsp_usb_host_stop(void); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/esp32_p4_box/include/bsp/touch.h b/bsp/esp32_p4_box/include/bsp/touch.h new file mode 100644 index 00000000..095e8ce1 --- /dev/null +++ b/bsp/esp32_p4_box/include/bsp/touch.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief BSP Touchscreen + * + * This file offers API for basic touchscreen initialization. + * It is useful for users who want to use the touchscreen without the default Graphical Library LVGL. + * + * For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_touch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief BSP touch configuration structure + * + */ +typedef struct { + void *dummy; /*!< Prepared for future use. */ +} bsp_touch_config_t; + +/** + * @brief Create new touchscreen + * + * If you want to free resources allocated by this function, you can use esp_lcd_touch API, ie.: + * + * \code{.c} + * esp_lcd_touch_del(tp); + * \endcode + * + * @param[in] config touch configuration + * @param[out] ret_touch esp_lcd_touch touchscreen handle + * @return + * - ESP_OK On success + * - Else esp_lcd_touch failure + */ +esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/esp32_p4_box/priv_include/bsp_err_check.h b/bsp/esp32_p4_box/priv_include/bsp_err_check.h new file mode 100644 index 00000000..cf2f36eb --- /dev/null +++ b/bsp/esp32_p4_box/priv_include/bsp_err_check.h @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_check.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Assert on error, if selected in menuconfig. Otherwise return error code. */ +#if CONFIG_BSP_ERROR_CHECK +#define BSP_ERROR_CHECK_RETURN_ERR(x) ESP_ERROR_CHECK(x) +#define BSP_ERROR_CHECK_RETURN_NULL(x) ESP_ERROR_CHECK(x) +#define BSP_ERROR_CHECK(x, ret) ESP_ERROR_CHECK(x) +#define BSP_NULL_CHECK(x, ret) assert(x) +#define BSP_NULL_CHECK_GOTO(x, goto_tag) assert(x) +#else +#define BSP_ERROR_CHECK_RETURN_ERR(x) do { \ + esp_err_t err_rc_ = (x); \ + if (unlikely(err_rc_ != ESP_OK)) { \ + return err_rc_; \ + } \ + } while(0) + +#define BSP_ERROR_CHECK_RETURN_NULL(x) do { \ + if (unlikely((x) != ESP_OK)) { \ + return NULL; \ + } \ + } while(0) + +#define BSP_NULL_CHECK(x, ret) do { \ + if ((x) == NULL) { \ + return ret; \ + } \ + } while(0) + +#define BSP_ERROR_CHECK(x, ret) do { \ + if (unlikely((x) != ESP_OK)) { \ + return ret; \ + } \ + } while(0) + +#define BSP_NULL_CHECK_GOTO(x, goto_tag) do { \ + if ((x) == NULL) { \ + goto goto_tag; \ + } \ + } while(0) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/examples/bsp_ext.py b/examples/bsp_ext.py index c135cea2..79ffaba5 100644 --- a/examples/bsp_ext.py +++ b/examples/bsp_ext.py @@ -60,7 +60,8 @@ def set_bsp_callback(action: str, ctx: Context, args: PropertyDict, **kwargs: st 'esp32_p4_function_ev_board', 'm5stack_core_s3', 'm5dial', - 'm5stack_core_2' + 'm5stack_core_2', + 'esp32_p4_box' } if bsp == '': diff --git a/examples/display/sdkconfig.bsp.esp32_p4_box b/examples/display/sdkconfig.bsp.esp32_p4_box new file mode 100644 index 00000000..e3d4fd25 --- /dev/null +++ b/examples/display/sdkconfig.bsp.esp32_p4_box @@ -0,0 +1,35 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32p4" + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_COMPILER_OPTIMIZATION_PERF=y +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +CONFIG_FREERTOS_HZ=1000 + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +## LVGL8 ## +CONFIG_LV_MEM_SIZE_KILOBYTES=48 +CONFIG_LV_USE_PERF_MONITOR=y + +## LVGL9 ## +CONFIG_LV_CONF_SKIP=y +CONFIG_LV_DEF_REFR_PERIOD=10 + +#CLIB default +CONFIG_LV_USE_CLIB_MALLOC=y +CONFIG_LV_USE_CLIB_SPRINTF=y +CONFIG_LV_USE_CLIB_STRING=y + +# Performance monitor +CONFIG_LV_USE_OBSERVER=y +CONFIG_LV_USE_SYSMON=y +CONFIG_LV_USE_PERF_MONITOR=y + + +# CONFIG_LV_BUILD_EXAMPLES is not set diff --git a/examples/display_audio_photo/sdkconfig.bsp.esp32_p4_box b/examples/display_audio_photo/sdkconfig.bsp.esp32_p4_box new file mode 100644 index 00000000..c612ce2c --- /dev/null +++ b/examples/display_audio_photo/sdkconfig.bsp.esp32_p4_box @@ -0,0 +1,36 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32p4" + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_COMPILER_OPTIMIZATION_PERF=y +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +CONFIG_FREERTOS_HZ=1000 + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +## LVGL8 ## +CONFIG_LV_MEM_SIZE_KILOBYTES=48 +CONFIG_LV_USE_PERF_MONITOR=y + +## LVGL9 ## +CONFIG_LV_CONF_SKIP=y +CONFIG_LV_DEF_REFR_PERIOD=10 + +#CLIB default +CONFIG_LV_USE_CLIB_MALLOC=y +CONFIG_LV_USE_CLIB_SPRINTF=y +CONFIG_LV_USE_CLIB_STRING=y + +# Performance monitor +CONFIG_LV_USE_OBSERVER=y +CONFIG_LV_USE_SYSMON=y +CONFIG_LV_USE_PERF_MONITOR=y + + +# CONFIG_LV_BUILD_EXAMPLES is not set diff --git a/examples/display_lvgl_demos/sdkconfig.bsp.esp32_p4_box b/examples/display_lvgl_demos/sdkconfig.bsp.esp32_p4_box new file mode 100644 index 00000000..bc8d98fc --- /dev/null +++ b/examples/display_lvgl_demos/sdkconfig.bsp.esp32_p4_box @@ -0,0 +1,45 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32p4" + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_COMPILER_OPTIMIZATION_PERF=y +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_FREERTOS_HZ=1000 + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +CONFIG_LV_FONT_MONTSERRAT_12=y +CONFIG_LV_FONT_MONTSERRAT_16=y +CONFIG_LV_USE_DEMO_WIDGETS=y +CONFIG_LV_USE_DEMO_BENCHMARK=y +CONFIG_LV_USE_DEMO_STRESS=y +CONFIG_LV_USE_DEMO_MUSIC=y +CONFIG_LV_DEMO_MUSIC_AUTO_PLAY=y +CONFIG_LV_DEMO_MUSIC_SQUARE=y + +## LVGL8 ## +CONFIG_LV_MEM_SIZE_KILOBYTES=48 +CONFIG_LV_USE_PERF_MONITOR=y + +## LVGL9 ## +CONFIG_LV_CONF_SKIP=y +CONFIG_LV_DEF_REFR_PERIOD=10 + +#CLIB default +CONFIG_LV_USE_CLIB_MALLOC=y +CONFIG_LV_USE_CLIB_SPRINTF=y +CONFIG_LV_USE_CLIB_STRING=y + +# Performance monitor +CONFIG_LV_USE_OBSERVER=y +CONFIG_LV_USE_SYSMON=y +CONFIG_LV_USE_PERF_MONITOR=y + + +# CONFIG_LV_BUILD_EXAMPLES is not set