diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml
index 0ff5e419b..10f10349f 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_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/m5stack_core_s3;
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 dadcc8c08..adcee6c7e 100644
--- a/.github/workflows/upload_component_noglib.yml
+++ b/.github/workflows/upload_component_noglib.yml
@@ -16,14 +16,15 @@ jobs:
- name: Upload noglib version of BSPs
# TODO: Extend this part to all BSPs
env:
- BSPs: "bsp/esp32_s3_eye"
+ BSPs: "bsp/esp32_s3_eye bsp/m5stack_core_s3"
run: |
pip install idf-component-manager py-markdown-table --upgrade
python .github/ci/bsp_noglib.py ${BSPs}
- uses: espressif/upload-components-ci-action@v1
with:
directories: >
- bsp/esp32_s3_eye_noglib
+ bsp/esp32_s3_eye_noglib;
+ bsp/m5stack_core_s3_noglib;
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
dry_run: ${{ github.ref_name != 'master' || github.repository_owner != 'espressif' }}
diff --git a/README.md b/README.md
index 89083c2e8..f3e3c2229 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,8 @@ Board support packages for development boards using Espressif's SoCs, written in
| [ESP32-LyraT](bsp/esp32_lyrat) | ESP32 | uSD card slot, microphone, audio codec + power amplifier | |
| [ESP32-C3-LCDKit](bsp/esp32_c3_lcdkit) | ESP32-C3 | LCD display with encoder, IR, PDM audio| |
| [ESP-BOX-3](bsp/esp-box-3) | ESP32-S3 | LCD display with touch, audio codec + power amplifier,
accelerometer and gyroscope | |
-| [ESP32-S3-KORVO-1](bsp/esp32_s3_korvo_1) | ESP32-S3-KORVO-1 | uSD card slot, microphone, audio codec + power amplifier, RGB led strip | |
+| [ESP32-S3-KORVO-1](bsp/esp32_s3_korvo_1) | ESP32-S3 | uSD card slot, microphone, audio codec + power amplifier, RGB led strip | |
+| [M5Stack CoreS3](bsp/m5stack_core_s3) | ESP32-S3 | LCD display with touch, uSD card slot, microphone, audio codec | |
## LCD displays and TOUCH
| [LVGL port](components/esp_lvgl_port) | [LCD drivers](LCD.md) |
diff --git a/bsp/m5stack_core_s3/.component_hash b/bsp/m5stack_core_s3/.component_hash
new file mode 100644
index 000000000..f60cd698f
--- /dev/null
+++ b/bsp/m5stack_core_s3/.component_hash
@@ -0,0 +1 @@
+b598e81f0914a656e18e9fa2f691cd8f32fa84da5f9e8c09fbe47975e085b81e
\ No newline at end of file
diff --git a/bsp/m5stack_core_s3/CMakeLists.txt b/bsp/m5stack_core_s3/CMakeLists.txt
new file mode 100644
index 000000000..93927aa3e
--- /dev/null
+++ b/bsp/m5stack_core_s3/CMakeLists.txt
@@ -0,0 +1,14 @@
+#IDF version is less than IDF5.0
+if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_LESS "5.0")
+ set(SRC_VER "m5stack_core_s3_idf4.c")
+else()
+ set(SRC_VER "m5stack_core_s3_idf5.c")
+endif()
+
+idf_component_register(
+ SRCS "m5stack_core_s3.c" ${SRC_VER}
+ INCLUDE_DIRS "include"
+ PRIV_INCLUDE_DIRS "priv_include"
+ REQUIRES driver spiffs
+ PRIV_REQUIRES fatfs esp_lcd
+)
diff --git a/bsp/m5stack_core_s3/Kconfig b/bsp/m5stack_core_s3/Kconfig
new file mode 100644
index 000000000..699b43868
--- /dev/null
+++ b/bsp/m5stack_core_s3/Kconfig
@@ -0,0 +1,86 @@
+menu "Board Support Package"
+
+ 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
+ ESP32S3 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 "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 "SD card - Virtual File System"
+ config BSP_SD_FORMAT_ON_MOUNT_FAIL
+ bool "Format SD card if mounting fails"
+ default n
+ help
+ The SDMMC host will format (FAT) the SD card if it fails to mount the filesystem.
+
+ config BSP_SD_MOUNT_POINT
+ string "SD card mount point"
+ default "/sdcard"
+ help
+ Mount point of the SD card 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.
+ 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/m5stack_core_s3/LICENSE b/bsp/m5stack_core_s3/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/bsp/m5stack_core_s3/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/m5stack_core_s3/README.md b/bsp/m5stack_core_s3/README.md
new file mode 100644
index 000000000..34975ba0e
--- /dev/null
+++ b/bsp/m5stack_core_s3/README.md
@@ -0,0 +1,25 @@
+# BSP: M5Stack CoreS3
+
+[![Component Registry](https://components.espressif.com/components/espressif/m5stack_core_s3/badge.svg)](https://components.espressif.com/components/espressif/m5stack_core_s3)
+
+* [Hardware Reference](https://docs.m5stack.com/en/core/CoreS3)
+
+![image](pic.webp)
+
+CoreS3 is the third generation of the M5Stack Core series. Powered by the ESP32-S3 solution, this kit features a dual-core Xtensa LX7 processor running at 240MHz. CoreS3 comes equipped with built-in Wi-Fi functionality, enabling seamless connectivity. It boasts 16MB of onboard flash memory and 8MB of PSRAM, providing ample space for program storage.
+
+CoreS3 offers convenient programming options through its TYPE-C interface, supporting OTG and CDC functions. This allows for easy connection with external USB devices and hassle-free firmware flashing. CoreS3 features a 2.0-inch capacitive touch IPS screen, protected by high-strength glass material. Additionally, a 30W pixel camera GC0308 is integrated at the bottom of the screen, accompanied by a proximity sensor LTR-553ALS-WA for enhanced functionality. Power management is handled by the AXP2101 power management core chip, employing a 4-way power flow control loop for efficient power distribution. The overall design emphasizes low power consumption. CoreS3 also features a 6-axis attitude sensor BMI270 and a magnetometer BMM150 for precise motion detection. With the onboard TF-card (microSD) card slot and BM8563 RTC chip, accurate timing and sleep-timer wake-up functions are readily available.
+
+Sound output on CoreS3 is optimized with the high-fidelity 16-bit I2S power amplifier chip AW88298, accompanied by a built-in 1W speaker for clear audio playback. For sound input, the kit incorporates the ES7210 audio decoding chip and dual-microphone input. The side of the device includes an independent power button and restart (RST) button, complemented by a self-built delay circuit. By long-pressing the reset button, users can easily enter the program download mode. The CoreS3 kit comes with the DinBase Base, providing convenient options for Din rail, wall, and screw fixing. It can be powered by an external DC 12V (supports 9~24V) or an internal 500mAh lithium battery. The DinBase also offers multiple proto locations for users to customize and expand their projects. CoreS3 is an ideal choice for IoT development, various DIY project development, smart home control systems, and industrial automation control systems.
+
+
+### Dependencies
+| component |version|
+|------------------------------------------------------------------------------------------------------------|-------|
+| [espressif/esp32-camera](https://components.espressif.com/components/espressif/esp32-camera) | ^2.0.2|
+| [espressif/esp_codec_dev](https://components.espressif.com/components/espressif/esp_codec_dev) | ^1.1 |
+| [espressif/esp_lcd_ili9341](https://components.espressif.com/components/espressif/esp_lcd_ili9341) | ^1 |
+|[espressif/esp_lcd_touch_ft5x06](https://components.espressif.com/components/espressif/esp_lcd_touch_ft5x06)| ^1 |
+| [espressif/esp_lvgl_port](https://components.espressif.com/components/espressif/esp_lvgl_port) | ^1.3 |
+| idf |>=4.4.5|
+
diff --git a/bsp/m5stack_core_s3/idf_component.yml b/bsp/m5stack_core_s3/idf_component.yml
new file mode 100644
index 000000000..2d96c0a51
--- /dev/null
+++ b/bsp/m5stack_core_s3/idf_component.yml
@@ -0,0 +1,23 @@
+version: "1.0.0"
+description: Board Support Package for M5Stack CoreS3
+url: https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_s3
+
+targets:
+ - esp32s3
+
+dependencies:
+ idf: ">=4.4.5"
+ esp_lcd_ili9341: "^1"
+ esp_lcd_touch_ft5x06: "^1"
+
+ espressif/esp_lvgl_port:
+ version: "^1.3"
+ public: true
+
+ esp_codec_dev:
+ version: "^1.1"
+ public: true
+
+ esp32-camera:
+ version: "^2.0.2"
+ public: true
diff --git a/bsp/m5stack_core_s3/include/bsp/config.h b/bsp/m5stack_core_s3/include/bsp/config.h
new file mode 100644
index 000000000..f3cb5ebe7
--- /dev/null
+++ b/bsp/m5stack_core_s3/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/m5stack_core_s3/include/bsp/display.h b/bsp/m5stack_core_s3/include/bsp/display.h
new file mode 100644
index 000000000..ef6b0edc6
--- /dev/null
+++ b/bsp/m5stack_core_s3/include/bsp/display.h
@@ -0,0 +1,109 @@
+/*
+ * SPDX-FileCopyrightText: 2023 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"
+
+/* LCD color formats */
+#define ESP_LCD_COLOR_FORMAT_RGB565 (1)
+#define ESP_LCD_COLOR_FORMAT_RGB888 (2)
+
+/* LCD display color format */
+#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB565)
+/* LCD display color bytes endianess */
+#define BSP_LCD_BIGENDIAN (1)
+/* LCD display color bits */
+#define BSP_LCD_BITS_PER_PIXEL (16)
+/* LCD display color space */
+#define BSP_LCD_COLOR_SPACE (ESP_LCD_COLOR_SPACE_BGR)
+/* LCD definition */
+#define BSP_LCD_H_RES (320)
+#define BSP_LCD_V_RES (240)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief BSP display configuration structure
+ *
+ */
+typedef struct {
+ int max_transfer_sz; /*!< Maximum transfer size, in bytes. */
+} bsp_display_config_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);
+ * spi_bus_free(spi_num_from_configuration);
+ * \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 Set display's brightness
+ *
+ * Brightness is controlled with PWM signal to a pin controling backlight.
+ *
+ * @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
+ *
+ * Display must be already initialized by calling bsp_display_start()
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t bsp_display_backlight_on(void);
+
+/**
+ * @brief Turn off display backlight
+ *
+ * Display must be already initialized by calling bsp_display_start()
+ *
+ * @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/m5stack_core_s3/include/bsp/esp-bsp.h b/bsp/m5stack_core_s3/include/bsp/esp-bsp.h
new file mode 100644
index 000000000..f4698137b
--- /dev/null
+++ b/bsp/m5stack_core_s3/include/bsp/esp-bsp.h
@@ -0,0 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include "bsp/m5stack_core_s3.h"
diff --git a/bsp/m5stack_core_s3/include/bsp/m5stack_core_s3.h b/bsp/m5stack_core_s3/include/bsp/m5stack_core_s3.h
new file mode 100644
index 000000000..9f64c29ff
--- /dev/null
+++ b/bsp/m5stack_core_s3/include/bsp/m5stack_core_s3.h
@@ -0,0 +1,426 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief ESP BSP: M5Stack CoreS3
+ */
+
+#pragma once
+
+#include "sdkconfig.h"
+#include "driver/gpio.h"
+#include "driver/i2c.h"
+#include "driver/sdmmc_host.h"
+#include "soc/usb_pins.h"
+#include "esp_codec_dev.h"
+#include "bsp/config.h"
+#include "bsp/display.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 0
+#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_11)
+#define BSP_I2C_SDA (GPIO_NUM_12)
+
+/* Audio */
+#define BSP_I2S_SCLK (GPIO_NUM_34)
+#define BSP_I2S_MCLK (GPIO_NUM_0)
+#define BSP_I2S_LCLK (GPIO_NUM_33)
+#define BSP_I2S_DOUT (GPIO_NUM_13) // To Codec AW88298
+#define BSP_I2S_DSIN (GPIO_NUM_14) // From ADC ES7210
+#define BSP_POWER_AMP_IO (GPIO_NUM_NC)
+#define BSP_MUTE_STATUS (GPIO_NUM_NC)
+
+/* Display */
+#define BSP_LCD_MOSI (GPIO_NUM_37)
+#define BSP_LCD_MISO (GPIO_NUM_35)
+#define BSP_LCD_PCLK (GPIO_NUM_36)
+#define BSP_LCD_CS (GPIO_NUM_3)
+#define BSP_LCD_DC (GPIO_NUM_35)
+#define BSP_LCD_RST (GPIO_NUM_NC)
+#define BSP_LCD_BACKLIGHT (GPIO_NUM_NC)
+#define BSP_LCD_TOUCH_INT (GPIO_NUM_NC)
+
+/* Camera */
+#define BSP_CAMERA_XCLK (GPIO_NUM_NC)
+#define BSP_CAMERA_PCLK (GPIO_NUM_45)
+#define BSP_CAMERA_VSYNC (GPIO_NUM_46)
+#define BSP_CAMERA_HSYNC (GPIO_NUM_38)
+#define BSP_CAMERA_D0 (GPIO_NUM_39)
+#define BSP_CAMERA_D1 (GPIO_NUM_40)
+#define BSP_CAMERA_D2 (GPIO_NUM_41)
+#define BSP_CAMERA_D3 (GPIO_NUM_42)
+#define BSP_CAMERA_D4 (GPIO_NUM_15)
+#define BSP_CAMERA_D5 (GPIO_NUM_16)
+#define BSP_CAMERA_D6 (GPIO_NUM_48)
+#define BSP_CAMERA_D7 (GPIO_NUM_47)
+
+/* SD card */
+#define BSP_SD_MOSI (GPIO_NUM_37)
+#define BSP_SD_MISO (GPIO_NUM_35)
+#define BSP_SD_SCK (GPIO_NUM_36)
+#define BSP_SD_CS (GPIO_NUM_4)
+
+/* USB */
+#define BSP_USB_POS USBPHY_DP_NUM
+#define BSP_USB_NEG USBPHY_DM_NUM
+
+
+#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
+ */
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
+esp_err_t bsp_audio_init(const i2s_config_t *i2s_config);
+#else
+esp_err_t bsp_audio_init(const i2s_std_config_t *i2s_config);
+#endif
+
+/**
+ * @brief Get codec I2S interface (initialized in bsp_audio_init)
+ *
+ * @return
+ * - Pointer to codec I2S interface handle or NULL when error occured
+ */
+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 occured
+ */
+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 occured
+ */
+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)
+ * - ADC ES7210 (configuration only)
+ * - Encryption chip ATECC608A (NOT populated on most boards)
+ * - LCD Touch controller
+ * - Inertial Measurement Unit ICM-42607-P
+ *
+ * After initialization of I2C, use BSP_I2C_NUM macro when creating I2C devices drivers ie.:
+ * \code{.c}
+ * es8311_handle_t es8311_dev = es8311_create(BSP_I2C_NUM, ES8311_ADDRRES_0);
+ * \endcode
+ **************************************************************************************************/
+#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);
+
+/**************************************************************************************************
+ *
+ * Camera interface
+ *
+ * ESP32-S3-EYE is shipped with OV2640 camera module.
+ * As a camera driver, esp32-camera component is used.
+ *
+ * Example configuration:
+ * \code{.c}
+ * const camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG;
+ * esp_err_t err = esp_camera_init(&camera_config);
+ * \endcode
+ **************************************************************************************************/
+/**
+ * @brief Camera default configuration
+ *
+ * In this configuration we select RGB565 color format and 320x240 image size - matching the display.
+ * We use double-buffering for the best performance.
+ * Since we don't want to waste internal SRAM, we allocate the framebuffers in external PSRAM.
+ * By setting XCLK to 16MHz, we configure the esp32-camera driver to use EDMA when accessing the PSRAM.
+ *
+ * @attention I2C must be enabled by bsp_i2c_init(), before camera is initialized
+ */
+#define BSP_CAMERA_DEFAULT_CONFIG \
+ { \
+ .pin_pwdn = GPIO_NUM_NC, \
+ .pin_reset = GPIO_NUM_NC, \
+ .pin_xclk = BSP_CAMERA_XCLK, \
+ .pin_sccb_sda = GPIO_NUM_NC, \
+ .pin_sccb_scl = GPIO_NUM_NC, \
+ .pin_d7 = BSP_CAMERA_D7, \
+ .pin_d6 = BSP_CAMERA_D6, \
+ .pin_d5 = BSP_CAMERA_D5, \
+ .pin_d4 = BSP_CAMERA_D4, \
+ .pin_d3 = BSP_CAMERA_D3, \
+ .pin_d2 = BSP_CAMERA_D2, \
+ .pin_d1 = BSP_CAMERA_D1, \
+ .pin_d0 = BSP_CAMERA_D0, \
+ .pin_vsync = BSP_CAMERA_VSYNC, \
+ .pin_href = BSP_CAMERA_HSYNC, \
+ .pin_pclk = BSP_CAMERA_PCLK, \
+ .xclk_freq_hz = 16000000, \
+ .ledc_timer = LEDC_TIMER_0, \
+ .ledc_channel = LEDC_CHANNEL_0, \
+ .pixel_format = PIXFORMAT_RGB565, \
+ .frame_size = FRAMESIZE_QVGA, \
+ .jpeg_quality = 12, \
+ .fb_count = 2, \
+ .fb_location = CAMERA_FB_IN_PSRAM,\
+ .sccb_i2c_port = BSP_I2C_NUM, \
+ }
+
+/**************************************************************************************************
+ *
+ * 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);
+
+/**************************************************************************************************
+ *
+ * SD card
+ *
+ * After mounting the SD card, it can be accessed with stdio functions ie.:
+ * \code{.c}
+ * FILE* f = fopen(BSP_SD_MOUNT_POINT"/hello.txt", "w");
+ * fprintf(f, "Hello %s!\n", bsp_sdcard->cid.name);
+ * fclose(f);
+ * \endcode
+ *
+ * @attention IO2 is also routed to RGB LED and push button
+ **************************************************************************************************/
+#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 can not be allocated
+ * - ESP_FAIL if partition can not be mounted
+ * - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
+ */
+esp_err_t bsp_sdcard_mount(void);
+
+/**
+ * @brief Unmount micorSD 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()
+ **************************************************************************************************/
+#define BSP_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
+#define BSP_LCD_SPI_NUM (SPI3_HOST)
+
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * BSP_LCD_V_RES)
+#define BSP_LCD_DRAW_BUFF_DOUBLE (1)
+
+/**
+ * @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 */
+ } 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_disp_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_disp_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_disp_t *disp, lv_disp_rot_t rotation);
+#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bsp/m5stack_core_s3/include/bsp/touch.h b/bsp/m5stack_core_s3/include/bsp/touch.h
new file mode 100644
index 000000000..3c9857ced
--- /dev/null
+++ b/bsp/m5stack_core_s3/include/bsp/touch.h
@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2023 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/m5stack_core_s3/m5stack_core_s3.c b/bsp/m5stack_core_s3/m5stack_core_s3.c
new file mode 100644
index 000000000..af6065003
--- /dev/null
+++ b/bsp/m5stack_core_s3/m5stack_core_s3.c
@@ -0,0 +1,521 @@
+/*
+ * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "driver/gpio.h"
+#include "driver/spi_master.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "esp_spiffs.h"
+#include "esp_lcd_panel_io.h"
+#include "esp_lcd_panel_vendor.h"
+#include "esp_lcd_panel_ops.h"
+#include "esp_vfs_fat.h"
+#include "driver/sdmmc_host.h"
+#include "driver/sdspi_host.h"
+#include "driver/i2c.h"
+
+#include "bsp/m5stack_core_s3.h"
+#include "bsp/display.h"
+#include "bsp/touch.h"
+#include "esp_lcd_ili9341.h"
+#include "esp_lcd_touch_ft5x06.h"
+#include "esp_lvgl_port.h"
+#include "bsp_err_check.h"
+#include "esp_codec_dev_defaults.h"
+
+static const char *TAG = "M5Stack";
+
+#define BSP_AXP2101_ADDR 0x34
+#define BSP_AW9523_ADDR 0x58
+
+/* Features */
+typedef enum {
+ BSP_FEATURE_LCD,
+ BSP_FEATURE_TOUCH,
+ BSP_FEATURE_SD,
+ BSP_FEATURE_SPEAKER,
+ BSP_FEATURE_CAMERA,
+} bsp_feature_t;
+
+static lv_disp_t *disp;
+static lv_indev_t *disp_indev = NULL;
+static esp_lcd_touch_handle_t tp; // LCD touch handle
+sdmmc_card_t *bsp_sdcard = NULL; // Global SD card handler
+static bool i2c_initialized = false;
+static bool spi_initialized = false;
+
+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;
+}
+
+static esp_err_t bsp_enable_feature(bsp_feature_t feature)
+{
+ esp_err_t err = ESP_OK;
+ static uint8_t aw9523_P0 = 0b10;
+ static uint8_t aw9523_P1 = 0b10100000;
+ uint8_t data[2];
+
+ /* Initilize I2C */
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init());
+
+ switch (feature) {
+ case BSP_FEATURE_LCD:
+ /* Enable LCD */
+ aw9523_P1 |= (1 << 1);
+ break;
+ case BSP_FEATURE_TOUCH:
+ /* Enable Touch */
+ aw9523_P0 |= (1);
+ break;
+ case BSP_FEATURE_SD:
+ /* AXP ALDO4 voltage / SD Card / 3V3 */
+ data[0] = 0x95;
+ data[1] = 0b00011100; //3V3
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+ /* Enable SD */
+ aw9523_P0 |= (1 << 4);
+ break;
+ case BSP_FEATURE_SPEAKER:
+ /* AXP ALDO1 voltage / PA PVDD / 1V8 */
+ data[0] = 0x92;
+ data[1] = 0b00001101; //1V8
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+ /* AXP ALDO2 voltage / Codec / 3V3 */
+ data[0] = 0x93;
+ data[1] = 0b00011100; //3V3
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+ /* AXP ALDO3 voltage / Codec+Mic / 3V3 */
+ data[0] = 0x94;
+ data[1] = 0b00011100; //3V3
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+ /* AW9523 P0 is in push-pull mode */
+ data[0] = 0x11;
+ data[1] = 0x10;
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AW9523_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+ /* Enable Codec AW88298 */
+ aw9523_P0 |= (1 << 2);
+ break;
+ case BSP_FEATURE_CAMERA:
+ /* Enable Camera */
+ aw9523_P1 |= (1);
+ break;
+ }
+
+ data[0] = 0x02;
+ data[1] = aw9523_P0;
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AW9523_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+
+ data[0] = 0x03;
+ data[1] = aw9523_P1;
+ err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AW9523_ADDR, data, sizeof(data), 1000 / portTICK_PERIOD_MS);
+
+ return err;
+}
+
+static esp_err_t bsp_spi_init(uint32_t max_transfer_sz)
+{
+ /* SPI was initialized before */
+ if (spi_initialized) {
+ return ESP_OK;
+ }
+
+ ESP_LOGD(TAG, "Initialize SPI bus");
+ const spi_bus_config_t buscfg = {
+ .sclk_io_num = BSP_LCD_PCLK,
+ .mosi_io_num = BSP_LCD_MOSI,
+ .miso_io_num = BSP_LCD_MISO,
+ .quadwp_io_num = GPIO_NUM_NC,
+ .quadhd_io_num = GPIO_NUM_NC,
+ .max_transfer_sz = max_transfer_sz,
+ };
+ ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed");
+
+ spi_initialized = true;
+
+ return ESP_OK;
+}
+
+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_err_t bsp_sdcard_mount(void)
+{
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_enable_feature(BSP_FEATURE_SD));
+
+ 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 = 16 * 1024
+ };
+
+ sdmmc_host_t host = SDSPI_HOST_DEFAULT();
+ host.slot = BSP_LCD_SPI_NUM;
+ sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
+ slot_config.gpio_cs = BSP_SD_CS;
+ slot_config.host_id = host.slot;
+
+ ESP_RETURN_ON_ERROR(bsp_spi_init((BSP_LCD_H_RES * BSP_LCD_V_RES) * sizeof(uint16_t)), TAG, "");
+
+ return esp_vfs_fat_sdspi_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_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_NULL(bsp_i2c_init());
+ /* Configure I2S peripheral and Power Amplifier */
+ BSP_ERROR_CHECK_RETURN_NULL(bsp_audio_init(NULL));
+ i2s_data_if = bsp_audio_get_codec_itf();
+ }
+ assert(i2s_data_if);
+
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_enable_feature(BSP_FEATURE_SPEAKER));
+
+ audio_codec_i2c_cfg_t i2c_cfg = {
+ .port = BSP_I2C_NUM,
+ .addr = AW88298_CODEC_DEFAULT_ADDR,
+ };
+ const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);
+
+ const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();
+
+ // New output codec interface
+ aw88298_codec_cfg_t aw88298_cfg = {
+ .ctrl_if = out_ctrl_if,
+ .gpio_if = gpio_if,
+ .hw_gain.pa_gain = 15,
+ // .reset_pin = -1,
+ };
+ const audio_codec_if_t *out_codec_if = aw88298_codec_new(&aw88298_cfg);
+
+ esp_codec_dev_cfg_t codec_dev_cfg = {
+ .dev_type = ESP_CODEC_DEV_TYPE_OUT,
+ .codec_if = out_codec_if,
+ .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_NULL(bsp_i2c_init());
+ /* Configure I2S peripheral and Power Amplifier */
+ BSP_ERROR_CHECK_RETURN_NULL(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_CMD_BITS 8
+#define LCD_PARAM_BITS 8
+#define LCD_LEDC_CH CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH
+
+static esp_err_t bsp_display_brightness_init(void)
+{
+ /* Initilize I2C */
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init());
+
+ const uint8_t lcd_bl_en[] = { 0x90, 0xBF }; // AXP DLDO1 Enable
+ ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, lcd_bl_en, sizeof(lcd_bl_en), 1000 / portTICK_PERIOD_MS), TAG, "I2C write failed");
+ const uint8_t lcd_bl_val[] = { 0x99, 0b00011000 }; // AXP DLDO1 voltage
+ ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, lcd_bl_val, sizeof(lcd_bl_val), 1000 / portTICK_PERIOD_MS), TAG, "I2C write failed");
+
+ 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);
+ const uint8_t reg_val = 20 + ((8 * brightness_percent) / 100); // 0b00000 ~ 0b11100; under 20, it is too dark
+ const uint8_t lcd_bl_val[] = { 0x99, reg_val }; // AXP DLDO1 voltage
+ ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, lcd_bl_val, sizeof(lcd_bl_val), 1000 / portTICK_PERIOD_MS), TAG, "I2C write failed");
+
+ 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);
+}
+
+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;
+ assert(config != NULL && config->max_transfer_sz > 0);
+
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_enable_feature(BSP_FEATURE_LCD));
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_enable_feature(BSP_FEATURE_CAMERA));
+
+ /* Initialize SPI */
+ ESP_RETURN_ON_ERROR(bsp_spi_init(config->max_transfer_sz), TAG, "");
+
+ ESP_LOGD(TAG, "Install panel IO");
+ const esp_lcd_panel_io_spi_config_t io_config = {
+ .dc_gpio_num = BSP_LCD_DC,
+ .cs_gpio_num = BSP_LCD_CS,
+ .pclk_hz = BSP_LCD_PIXEL_CLOCK_HZ,
+ .lcd_cmd_bits = LCD_CMD_BITS,
+ .lcd_param_bits = LCD_PARAM_BITS,
+ .spi_mode = 0,
+ .trans_queue_depth = 10,
+ };
+ ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed");
+
+ ESP_LOGD(TAG, "Install LCD driver");
+ const esp_lcd_panel_dev_config_t panel_config = {
+ .reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset
+ .color_space = BSP_LCD_COLOR_SPACE,
+ .bits_per_pixel = BSP_LCD_BITS_PER_PIXEL,
+ };
+ ESP_GOTO_ON_ERROR(esp_lcd_new_panel_ili9341(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed");
+
+ esp_lcd_panel_reset(*ret_panel);
+ esp_lcd_panel_init(*ret_panel);
+ esp_lcd_panel_mirror(*ret_panel, true, true);
+ esp_lcd_panel_invert_color(*ret_panel, true);
+ return ret;
+
+err:
+ if (*ret_panel) {
+ esp_lcd_panel_del(*ret_panel);
+ }
+ if (*ret_io) {
+ esp_lcd_panel_io_del(*ret_io);
+ }
+ spi_bus_free(BSP_LCD_SPI_NUM);
+ return ret;
+}
+
+esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch)
+{
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_enable_feature(BSP_FEATURE_TOUCH));
+
+ /* 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 = GPIO_NUM_NC, // Shared with LCD reset
+ .int_gpio_num = BSP_LCD_TOUCH_INT,
+ .levels = {
+ .reset = 0,
+ .interrupt = 0,
+ },
+ .flags = {
+ .swap_xy = 0,
+ .mirror_x = 1,
+ .mirror_y = 1,
+ },
+ };
+ 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_FT5x06_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_ft5x06(tp_io_handle, &tp_cfg, ret_touch);
+}
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+static lv_disp_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg)
+{
+ assert(cfg != NULL);
+ esp_lcd_panel_io_handle_t io_handle = NULL;
+ esp_lcd_panel_handle_t panel_handle = NULL;
+ const bsp_display_config_t bsp_disp_cfg = {
+ .max_transfer_sz = (BSP_LCD_H_RES * BSP_LCD_V_RES) * sizeof(uint16_t),
+ };
+ BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&bsp_disp_cfg, &panel_handle, &io_handle));
+
+ esp_lcd_panel_disp_on_off(panel_handle, true);
+
+ /* Add LCD screen */
+ ESP_LOGD(TAG, "Add LCD screen");
+ const lvgl_port_display_cfg_t disp_cfg = {
+ .io_handle = io_handle,
+ .panel_handle = panel_handle,
+ .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,
+ },
+ .flags = {
+ .buff_dma = cfg->flags.buff_dma,
+ .buff_spiram = cfg->flags.buff_spiram,
+ }
+ };
+
+ return lvgl_port_add_disp(&disp_cfg);
+}
+
+static lv_indev_t *bsp_display_indev_init(lv_disp_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_disp_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 = {
+ .buff_dma = true,
+ .buff_spiram = false,
+ }
+ };
+ return bsp_display_start_with_config(&cfg);
+}
+
+lv_disp_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg)
+{
+ 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_disp_t *disp, lv_disp_rot_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)
diff --git a/bsp/m5stack_core_s3/m5stack_core_s3_idf4.c b/bsp/m5stack_core_s3/m5stack_core_s3_idf4.c
new file mode 100644
index 000000000..d3aba76a0
--- /dev/null
+++ b/bsp/m5stack_core_s3/m5stack_core_s3_idf4.c
@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_err.h"
+#include "bsp/m5stack_core_s3.h"
+#include "bsp_err_check.h"
+#include "esp_codec_dev_defaults.h"
+
+static const char *TAG = "M5Stack";
+
+/* This configuration is used by default in bsp_audio_init() */
+#define BSP_I2S_DUPLEX_MONO_CFG(_sample_rate) \
+ { \
+ .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX, \
+ .sample_rate = _sample_rate, \
+ .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, \
+ .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, \
+ .communication_format = I2S_COMM_FORMAT_STAND_I2S, \
+ .dma_buf_count = 3, \
+ .dma_buf_len = 1024, \
+ .use_apll = true, \
+ .tx_desc_auto_clear = true, \
+ .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM \
+ }
+
+static const audio_codec_data_if_t *i2s_data_if = NULL; /* Codec data interface */
+
+esp_err_t bsp_audio_init(const i2s_config_t *i2s_config)
+{
+ esp_err_t ret = ESP_FAIL;
+
+ if (i2s_data_if != NULL) {
+ /* Audio was initialized before */
+ return ESP_OK;
+ }
+
+ /* Setup I2S peripheral */
+ const i2s_pin_config_t i2s_pin_config = {
+ .mck_io_num = BSP_I2S_MCLK,
+ .bck_io_num = BSP_I2S_SCLK,
+ .ws_io_num = BSP_I2S_LCLK,
+ .data_out_num = BSP_I2S_DOUT,
+ .data_in_num = BSP_I2S_DSIN
+ };
+
+ /* Setup I2S channels */
+ const i2s_config_t std_cfg_default = BSP_I2S_DUPLEX_MONO_CFG(22050);
+ const i2s_config_t *p_i2s_cfg = &std_cfg_default;
+ if (i2s_config != NULL) {
+ p_i2s_cfg = i2s_config;
+ }
+
+ ESP_ERROR_CHECK(i2s_driver_install(CONFIG_BSP_I2S_NUM, p_i2s_cfg, 0, NULL));
+ ESP_GOTO_ON_ERROR(i2s_set_pin(CONFIG_BSP_I2S_NUM, &i2s_pin_config), err, TAG, "I2S set pin failed");
+
+ audio_codec_i2s_cfg_t i2s_cfg = {
+ .port = CONFIG_BSP_I2S_NUM,
+ };
+ i2s_data_if = audio_codec_new_i2s_data(&i2s_cfg);
+ BSP_NULL_CHECK_GOTO(i2s_data_if, err);
+
+ return ESP_OK;
+
+err:
+ i2s_driver_uninstall(CONFIG_BSP_I2S_NUM);
+ return ret;
+}
+
+const audio_codec_data_if_t *bsp_audio_get_codec_itf(void)
+{
+ return i2s_data_if;
+}
diff --git a/bsp/m5stack_core_s3/m5stack_core_s3_idf5.c b/bsp/m5stack_core_s3/m5stack_core_s3_idf5.c
new file mode 100644
index 000000000..6805a8adc
--- /dev/null
+++ b/bsp/m5stack_core_s3/m5stack_core_s3_idf5.c
@@ -0,0 +1,95 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_err.h"
+#include "bsp/m5stack_core_s3.h"
+#include "bsp_err_check.h"
+#include "esp_codec_dev_defaults.h"
+
+static const char *TAG = "M5Stack";
+
+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/m5stack_core_s3/pic.webp b/bsp/m5stack_core_s3/pic.webp
new file mode 100644
index 000000000..fe0c71af2
Binary files /dev/null and b/bsp/m5stack_core_s3/pic.webp differ
diff --git a/bsp/m5stack_core_s3/priv_include/bsp_err_check.h b/bsp/m5stack_core_s3/priv_include/bsp_err_check.h
new file mode 100644
index 000000000..e00199943
--- /dev/null
+++ b/bsp/m5stack_core_s3/priv_include/bsp_err_check.h
@@ -0,0 +1,58 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 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/docu/pics/m5stack_cores3.webp b/docu/pics/m5stack_cores3.webp
new file mode 100644
index 000000000..aa1dd99bc
Binary files /dev/null and b/docu/pics/m5stack_cores3.webp differ
diff --git a/examples/bsp_ext.py b/examples/bsp_ext.py
index 360b0f9ba..e97e5ebab 100644
--- a/examples/bsp_ext.py
+++ b/examples/bsp_ext.py
@@ -57,6 +57,7 @@ def set_bsp_callback(action: str, ctx: Context, args: PropertyDict, **kwargs: st
'esp32_c3_lcdkit',
'esp_bsp_generic',
'esp32_s3_korvo_1',
+ 'm5stack_core_s3'
}
if bsp == '':
diff --git a/examples/display_audio_photo/main/app_disp_fs.c b/examples/display_audio_photo/main/app_disp_fs.c
index ad88631e5..f4930338c 100644
--- a/examples/display_audio_photo/main/app_disp_fs.c
+++ b/examples/display_audio_photo/main/app_disp_fs.c
@@ -345,6 +345,7 @@ static void play_file(void *arg)
.sample_rate = wav_header.sample_rate,
.channel = wav_header.num_channels,
.bits_per_sample = wav_header.bits_per_sample,
+ .mclk_multiple = I2S_MCLK_MULTIPLE_384,
};
esp_codec_dev_open(spk_codec_dev, &fs);
@@ -793,6 +794,7 @@ static void rec_file(void *arg)
.sample_rate = SAMPLE_RATE,
.channel = 1,
.bits_per_sample = 16,
+ .mclk_multiple = I2S_MCLK_MULTIPLE_384,
};
esp_codec_dev_open(mic_codec_dev, &fs);
diff --git a/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_s3 b/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_s3
new file mode 100644
index 000000000..4e8064c11
--- /dev/null
+++ b/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_s3
@@ -0,0 +1,17 @@
+# 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="esp32s3"
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_SPIRAM=y
+CONFIG_SPIRAM_SPEED_80M=y
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
+CONFIG_SPIFFS_PAGE_SIZE=1024
+CONFIG_LV_COLOR_16_SWAP=y
+CONFIG_LV_MEM_CUSTOM=y
+CONFIG_LV_MEMCPY_MEMSET_STD=y
+CONFIG_LV_USE_PERF_MONITOR=y
+CONFIG_LV_SPRINTF_CUSTOM=y
+# CONFIG_LV_BUILD_EXAMPLES is not set
diff --git a/examples/display_camera/sdkconfig.bsp.m5stack_core_s3 b/examples/display_camera/sdkconfig.bsp.m5stack_core_s3
new file mode 100644
index 000000000..9f9ca2ac4
--- /dev/null
+++ b/examples/display_camera/sdkconfig.bsp.m5stack_core_s3
@@ -0,0 +1,20 @@
+# 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="esp32s3"
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP_DEFAULT_CPU_FREQ_240=y
+CONFIG_SPIRAM=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y
+CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
+CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192
+CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
+CONFIG_LV_COLOR_16_SWAP=y
+CONFIG_LV_MEM_CUSTOM=y
+CONFIG_LV_MEMCPY_MEMSET_STD=y
+CONFIG_LV_USE_PERF_MONITOR=y
+CONFIG_LV_SPRINTF_CUSTOM=y
+# CONFIG_LV_BUILD_EXAMPLES is not set
diff --git a/examples/display_rotation/sdkconfig.bsp.m5stack_core_s3 b/examples/display_rotation/sdkconfig.bsp.m5stack_core_s3
new file mode 100644
index 000000000..80a2848c3
--- /dev/null
+++ b/examples/display_rotation/sdkconfig.bsp.m5stack_core_s3
@@ -0,0 +1,8 @@
+# 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="esp32s3"
+CONFIG_LV_COLOR_16_SWAP=y
+CONFIG_LV_MEM_CUSTOM=y
+CONFIG_LV_MEMCPY_MEMSET_STD=y
+CONFIG_LV_USE_PERF_MONITOR=y