diff --git a/.build-test-rules.yml b/.build-test-rules.yml index a879f1e14..f241485a5 100644 --- a/.build-test-rules.yml +++ b/.build-test-rules.yml @@ -3,7 +3,7 @@ examples: disable: - if: CONFIG_NAME in ["esp-box", "esp-box-lite"] reason: Do not build examples for deprecated BSPs - - if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 2) and CONFIG_NAME in ["esp_bsp_generic", "esp_bsp_devkit"] + - if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 2) and CONFIG_NAME in ["esp_bsp_generic", "esp_bsp_devkit", "m5stack_core"] reason: Example depends on BSP, which is supported only for IDF >= 5.2 - if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 3) and CONFIG_NAME in ["esp32_p4_function_ev_board", "esp-box-3", "esp32_s3_lcd_ev_board"] reason: Example depends on BSP, which is supported only for IDF >= 5.3 diff --git a/bsp/m5stack_core/CMakeLists.txt b/bsp/m5stack_core/CMakeLists.txt new file mode 100644 index 000000000..8053566f2 --- /dev/null +++ b/bsp/m5stack_core/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + SRCS "m5stack_core.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "priv_include" + REQUIRES driver spiffs + PRIV_REQUIRES fatfs esp_lcd +) diff --git a/bsp/m5stack_core/Kconfig b/bsp/m5stack_core/Kconfig new file mode 100644 index 000000000..047ad0252 --- /dev/null +++ b/bsp/m5stack_core/Kconfig @@ -0,0 +1,93 @@ +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 + ESP32 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_M5STACK_CORE_LCD_INVERT_COLOR + bool "Invert LCD colors (for Core v2.2 and above)" + default y + help + Enable this option if you have M5Stack Core v2.2 or above with IPS display. + Disable for older versions with TN 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 0 + range 0 1 + help + ESP32 has two I2S peripherals, pick the one you want to use. + +endmenu diff --git a/bsp/m5stack_core/LICENSE b/bsp/m5stack_core/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/bsp/m5stack_core/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/README.md b/bsp/m5stack_core/README.md new file mode 100644 index 000000000..7383ae40e --- /dev/null +++ b/bsp/m5stack_core/README.md @@ -0,0 +1,44 @@ +# BSP: M5Stack Core + +> [!WARNING] +> The SD card is not working simultaneously with the LCD screen. We are working on a fix. + +[![Component Registry](https://components.espressif.com/components/espressif/m5stack_core/badge.svg)](https://components.espressif.com/components/espressif/m5stack_core) + +* [Hardware Reference](https://docs.m5stack.com/en/core/basic_v2.7) + +basic +fire + +This BSP supports the following M5Stack Core v2.7 series devices: +- M5Stack Basic v2.7 +- M5Stack Fire v2.7 +- Other M5Stack Core based devices + +M5Stack Core is a development board based on ESP32 microcontroller. It features: + +- **MCU**: ESP32 dual-core Xtensa® 32-bit LX6 microprocessor, up to 240MHz +- **Memory**: 4MB Flash + 520KB SRAM +- **Interface**: USB Type-C for programming and debugging +- **Display**: 2.0" TFT LCD screen (320x240 resolution) with ILI9341 controller + - If you have a v2.2 or above, you can enable the IPS display by setting `CONFIG_BSP_M5STACK_CORE_LCD_INVERT_COLOR=y` in the SDK configuration. Vice versa. +- **Power Management**: IP5306 power management chip for battery charging and power control +- **Audio**: Single GPIO controlled speaker +- **Storage**: microSD card slot (SPI interface) +- **Input**: Three physical buttons (ButtonA, ButtonB, ButtonC) +- **Expansion**: Bottom expansion headers for additional modules + + +### Capabilities and dependencies +| Capability | Available | Component |Version| +|-------------|------------------|--------------------------------------------------------------------------------------------------|-------| +| DISPLAY |:heavy_check_mark:|[espressif/esp_lcd_ili9341](https://components.espressif.com/components/espressif/esp_lcd_ili9341)| ^1 | +| LVGL_PORT |:heavy_check_mark:| [espressif/esp_lvgl_port](https://components.espressif.com/components/espressif/esp_lvgl_port) | ^2 | +| TOUCH | :x: | | | +| BUTTONS |:heavy_check_mark:| [espressif/button](https://components.espressif.com/components/espressif/button) | ^2.4 | +| AUDIO | :x: | | | +|AUDIO_SPEAKER|:heavy_check_mark:| | | +| AUDIO_MIC | :x: | | | +| SDCARD |:heavy_check_mark:| idf | >=5.2 | +| IMU | :x: | | | + diff --git a/bsp/m5stack_core/idf_component.yml b/bsp/m5stack_core/idf_component.yml new file mode 100644 index 000000000..d76f68411 --- /dev/null +++ b/bsp/m5stack_core/idf_component.yml @@ -0,0 +1,21 @@ +version: "1.0.0" +description: Board Support Package (BSP) for M5Stack Core +url: https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core + +targets: + - esp32 + +tags: + - bsp + +dependencies: + idf: ">=5.2" + esp_lcd_ili9341: "^1" + + button: + version: "^2.4" + public: true + + espressif/esp_lvgl_port: + version: "^2" + public: true diff --git a/bsp/m5stack_core/include/bsp/config.h b/bsp/m5stack_core/include/bsp/config.h new file mode 100644 index 000000000..f3cb5ebe7 --- /dev/null +++ b/bsp/m5stack_core/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/include/bsp/display.h b/bsp/m5stack_core/include/bsp/display.h new file mode 100644 index 000000000..1963bbd68 --- /dev/null +++ b/bsp/m5stack_core/include/bsp/display.h @@ -0,0 +1,121 @@ +/* + * 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" + +/* 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 Initialize display's brightness + * + * Brightness is controlled with AXP2101 via I2C. + * + * @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 AXP2101 via I2C. + * Backlight must be already initialized by calling bsp_display_brightness_init() or bsp_display_start() + * + * @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 + * + * Backlight must be already initialized by calling bsp_display_brightness_init() or 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 + * + * Backlight must be already initialized by calling bsp_display_brightness_init() or 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/include/bsp/esp-bsp.h b/bsp/m5stack_core/include/bsp/esp-bsp.h new file mode 100644 index 000000000..78b794cf2 --- /dev/null +++ b/bsp/m5stack_core/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/m5stack_core.h" diff --git a/bsp/m5stack_core/include/bsp/m5stack_core.h b/bsp/m5stack_core/include/bsp/m5stack_core.h new file mode 100644 index 000000000..d77242a43 --- /dev/null +++ b/bsp/m5stack_core/include/bsp/m5stack_core.h @@ -0,0 +1,341 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ESP BSP: M5Stack Core + */ + +#pragma once + +#include "sdkconfig.h" +#include "driver/gpio.h" +#include "driver/sdmmc_host.h" +#include "bsp/config.h" +#include "bsp/display.h" + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +#include "lvgl.h" +#include "esp_lvgl_port.h" +#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0 + +#include "iot_button.h" + +/************************************************************************************************** + * BSP Capabilities + **************************************************************************************************/ + +#define BSP_CAPS_DISPLAY 1 +#define BSP_CAPS_TOUCH 0 +#define BSP_CAPS_BUTTONS 1 +#define BSP_CAPS_AUDIO 0 +#define BSP_CAPS_AUDIO_SPEAKER 1 +#define BSP_CAPS_AUDIO_MIC 0 +#define BSP_CAPS_SDCARD 1 +#define BSP_CAPS_IMU 0 + +/************************************************************************************************** + * M5Stack-Core pinout + **************************************************************************************************/ +/* I2C */ +#define BSP_I2C_SCL (GPIO_NUM_22) +#define BSP_I2C_SDA (GPIO_NUM_21) + +/* Audio */ +#define BSP_SPEAKER_IO (GPIO_NUM_25) + +/* Display */ +#define BSP_LCD_MOSI (GPIO_NUM_23) +#define BSP_LCD_MISO (GPIO_NUM_NC) +#define BSP_LCD_PCLK (GPIO_NUM_18) +#define BSP_LCD_CS (GPIO_NUM_14) +#define BSP_LCD_DC (GPIO_NUM_27) +#define BSP_LCD_RST (GPIO_NUM_33) +#define BSP_LCD_BACKLIGHT (GPIO_NUM_32) + +/* SD card */ +#define BSP_SD_MOSI (GPIO_NUM_23) +#define BSP_SD_MISO (GPIO_NUM_19) +#define BSP_SD_SCK (GPIO_NUM_18) +#define BSP_SD_CS (GPIO_NUM_4) + +/* BUTTON */ +#define BSP_BUTTON_LEFT (GPIO_NUM_39) +#define BSP_BUTTON_MIDDLE (GPIO_NUM_38) +#define BSP_BUTTON_RIGHT (GPIO_NUM_37) + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + * + * Speaker interface + * + * M5Stack-Core has a simple speaker that can be controlled via GPIO. + * The speaker must be initialized before use by calling bsp_speaker_init() + **************************************************************************************************/ +/** + * @brief Initialize speaker GPIO + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG GPIO parameter error + */ +esp_err_t bsp_speaker_init(void); + +/************************************************************************************************** + * + * I2C interface + * + * There are multiple devices connected to I2C peripheral: + * - IP5306 + **************************************************************************************************/ +#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); + +/************************************************************************************************** + * + * 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 + * + * M5Stack-Core is shipped with 2.0inch ILI9341C display controller. + * It features 16-bit colors, 320x240 resolution. + * + * 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 (SPI2_HOST) + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * 50) +#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_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_display_rotation_t rotation); +#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0 + +/************************************************************************************************** + * + * BSP Features + * + * This module provides an interface to enable and disable various features on the M5Stack-Core-2 board. + * Supported features include the LCD display, touch screen, SD card, and speaker. + * + * The bsp_feature_enable function is used to enable or disable a specified feature. + * It communicates with the Power Management Unit (PMU) via the I2C interface to control the power of each feature. + * + * Supported PMU models include AXP2101 and AXP192. + * Depending on the configuration, the function selects the appropriate PMU registers and values to enable or disable the feature. + * + * Parameters: + * - feature: The feature to enable or disable, of type bsp_feature_t enum. + * - enable: A boolean value, true to enable the feature, false to disable it. + * + * Return value: + * - esp_err_t: Error code indicating the result of the operation. + * + **************************************************************************************************/ +typedef enum { + BSP_FEATURE_LCD, +} bsp_feature_t; + +esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable); + +/************************************************************************************************** + * + * Button interface + * + * M5Stack-Core has three buttons: + * - Left button (GPIO39): Used for navigation (previous) + * - Middle button (GPIO38): Used for selection (enter) + * - Right button (GPIO37): Used for navigation (next) + * + * The buttons can be used with LVGL for UI navigation + **************************************************************************************************/ +/** + * @brief Create button objects + * + * @param btn_array Output array of button handles + * @param btn_cnt Output number of created buttons + * @param btn_array_size Size of output array + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL Create button failed + */ +esp_err_t bsp_iot_button_create(button_handle_t btn_array[], int *btn_cnt, int btn_array_size); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/m5stack_core/m5stack_core.c b/bsp/m5stack_core/m5stack_core.c new file mode 100644 index 000000000..3811e8f1a --- /dev/null +++ b/bsp/m5stack_core/m5stack_core.c @@ -0,0 +1,470 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "bsp/m5stack_core.h" +#include "bsp/display.h" +#include "esp_lcd_ili9341.h" +#include "bsp_err_check.h" + +static const char *TAG = "M5Stack"; + +#define BSP_IP5306_ADDR 0x75 + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static lv_display_t *disp; +static lv_indev_t *disp_indev = NULL; +/* Button definitions */ +typedef enum { + BSP_BUTTON_PREV, // Button left + BSP_BUTTON_ENTER, // Button middle + BSP_BUTTON_NEXT, // Button right + BSP_BUTTON_NUM +} bsp_button_t; +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static i2c_master_bus_handle_t i2c_handle = NULL; +static bool i2c_initialized = false; +static i2c_master_dev_handle_t ip5306_h = NULL; +static bool spi_initialized = false; + +esp_err_t bsp_i2c_init(void) +{ + /* I2C was initialized before */ + if (i2c_initialized) { + return ESP_OK; + } + + const i2c_master_bus_config_t i2c_config = { + .i2c_port = BSP_I2C_NUM, + .scl_io_num = BSP_I2C_SCL, + .sda_io_num = BSP_I2C_SDA, + .clk_source = I2C_CLK_SRC_DEFAULT, + }; + BSP_ERROR_CHECK_RETURN_ERR(i2c_new_master_bus(&i2c_config, &i2c_handle)); + + const i2c_device_config_t ip5306_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = BSP_IP5306_ADDR, + .scl_speed_hz = CONFIG_BSP_I2C_CLK_SPEED_HZ, + }; + BSP_ERROR_CHECK_RETURN_ERR(i2c_master_bus_add_device(i2c_handle, &ip5306_config, &ip5306_h)); + + i2c_initialized = true; + + return ESP_OK; +} + +esp_err_t bsp_i2c_deinit(void) +{ + if (i2c_initialized) { + // Delete I2C device for IP5306 first + if (i2c_handle != NULL) { + i2c_master_bus_rm_device(ip5306_h); + ip5306_h = NULL; + } + // Then delete the I2C master bus + BSP_ERROR_CHECK_RETURN_ERR(i2c_del_master_bus(i2c_handle)); + i2c_handle = NULL; + i2c_initialized = false; + } + return ESP_OK; +} + +esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable) +{ + esp_err_t err = ESP_OK; + + /* Initialize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); + + switch (feature) { + case BSP_FEATURE_LCD: + // backlight is controlled by GPIO + if (enable) { + err = bsp_display_backlight_on(); + } else { + err = bsp_display_backlight_off(); + } + break; + } + 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) +{ + 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_err_t bsp_speaker_init(void) +{ + // Configure speaker GPIO as output mode + gpio_config_t io_conf = { + .pin_bit_mask = (1ULL << BSP_SPEAKER_IO), + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + ESP_ERROR_CHECK(gpio_config(&io_conf)); + + gpio_set_level(BSP_SPEAKER_IO, 0); // Turn off speaker + + return ESP_OK; +} + +#define LCD_CMD_BITS 8 +#define LCD_PARAM_BITS 8 +#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); +} + +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_feature_enable(BSP_FEATURE_LCD, true)); + + /* Initialize SPI */ + ESP_RETURN_ON_ERROR(bsp_spi_init(config->max_transfer_sz), TAG, ""); + + ESP_LOGI(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_LOGI(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); +#if CONFIG_BSP_M5STACK_CORE_LCD_INVERT_COLOR + esp_lcd_panel_invert_color(*ret_panel, true); +#else + esp_lcd_panel_invert_color(*ret_panel, false); +#endif + 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; +} + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static lv_display_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_DRAW_BUFF_SIZE * 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 = false, + .mirror_y = false, + }, + .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 + } + }; + + return lvgl_port_add_disp(&disp_cfg); +} + +static const button_config_t bsp_button_config[BSP_BUTTON_NUM] = { + { + .type = BUTTON_TYPE_GPIO, + .gpio_button_config.active_level = false, + .gpio_button_config.gpio_num = BSP_BUTTON_LEFT, + }, + { + .type = BUTTON_TYPE_GPIO, + .gpio_button_config.active_level = false, + .gpio_button_config.gpio_num = BSP_BUTTON_MIDDLE, + }, + { + .type = BUTTON_TYPE_GPIO, + .gpio_button_config.active_level = false, + .gpio_button_config.gpio_num = BSP_BUTTON_RIGHT, + }, +}; + +static lv_indev_t *bsp_display_indev_init(lv_display_t *disp) +{ + const lvgl_port_nav_btns_cfg_t btns = { + .disp = disp, + .button_prev = &bsp_button_config[BSP_BUTTON_PREV], + .button_next = &bsp_button_config[BSP_BUTTON_NEXT], + .button_enter = &bsp_button_config[BSP_BUTTON_ENTER] + }; + + return lvgl_port_add_navigation_buttons(&btns); +} + +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 = { + .buff_dma = true, + .buff_spiram = false, + } + }; + cfg.lvgl_port_cfg.task_affinity = 1; /* For camera */ + return bsp_display_start_with_config(&cfg); +} + +lv_display_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); + + // Initialize keypad input device + BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL); + + // Turn on backlight + bsp_display_backlight_on(); + + return disp; +} + +lv_indev_t *bsp_display_get_input_dev(void) +{ + return disp_indev; +} + +void bsp_display_rotate(lv_display_t *disp, lv_display_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(); +} + +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; +} +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) diff --git a/bsp/m5stack_core/priv_include/bsp_err_check.h b/bsp/m5stack_core/priv_include/bsp_err_check.h new file mode 100644 index 000000000..cf2f36eb4 --- /dev/null +++ b/bsp/m5stack_core/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/bsp/m5stack_core_2/README.md b/bsp/m5stack_core_2/README.md index 89967d1f2..10bb4ebfd 100644 --- a/bsp/m5stack_core_2/README.md +++ b/bsp/m5stack_core_2/README.md @@ -16,6 +16,8 @@ M5Core2 is the second generation core device in the M5Stack development kit seri - **Interface**: USB TYPE-C interface for charging, program downloading, and serial communication. - **Display**: 2.0-inch integrated capacitive touch screen with three programmable capacitive buttons on the front. - **Power Management:** Managed by an AXP192 power management chip (upgraded to AXP2101 in Core2 V1.1), which effectively controls power consumption. It includes a built-in green LED power indicator for battery level notification. The battery capacity is 390mAh, providing longer power duration than the previous model. + - For Core2 V1.0: Configure `CONFIG_BSP_PMU_AXP192` + - For Core2 V1.1: Configure `CONFIG_BSP_PMU_AXP2101` - **Audio**: I2S digital audio interface power amplifier chip to prevent signal distortion, along with a built-in speaker. - **Expansion**: Retains a TF-card (microSD) slot, and an expansion board on the back with a 6-axis IMU sensor and a microphone. - **RTC Module**: Built-in RTC module for accurate timing, with a dedicated battery for RTC power supply in Core2 V1.1. diff --git a/examples/bsp_ext.py b/examples/bsp_ext.py index 78d2b52fc..6549a9f8c 100644 --- a/examples/bsp_ext.py +++ b/examples/bsp_ext.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os from re import match, compile @@ -61,7 +61,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', + 'm5stack_core', } if bsp == '': diff --git a/examples/display/sdkconfig.bsp.m5stack_core b/examples/display/sdkconfig.bsp.m5stack_core new file mode 100644 index 000000000..636599d69 --- /dev/null +++ b/examples/display/sdkconfig.bsp.m5stack_core @@ -0,0 +1,25 @@ +# 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="esp32" +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESP_DEFAULT_CPU_FREQ_240=y + +## LVGL8 ## +CONFIG_LV_USE_PERF_MONITOR=y +CONFIG_LV_COLOR_16_SWAP=y +CONFIG_LV_MEM_CUSTOM=y +CONFIG_LV_MEMCPY_MEMSET_STD=y + +## LVGL9 ## +CONFIG_LV_CONF_SKIP=y + +#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