diff --git a/.build-test-rules.yml b/.build-test-rules.yml index 0be46653..d58f6056 100644 --- a/.build-test-rules.yml +++ b/.build-test-rules.yml @@ -2,7 +2,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 CONFIG_NAME in ["esp32_c3_lcdkit", "esp32_s3_lcd_ev_board", "esp32_s3_usb_otg", "m5stack_core_s3", "m5dial"] + - if: IDF_VERSION_MAJOR < 5 and CONFIG_NAME in ["esp32_c3_lcdkit", "esp32_s3_lcd_ev_board", "esp32_s3_usb_otg", "m5stack_core_s3", "m5stack_core_2", "m5dial"] reason: Example depends on BSP, which is supported only for IDF >= 5.0 - if: IDF_VERSION_MAJOR < 5 and IDF_TARGET in ["esp32c2", "esp32p4", "esp32c5", "esp32c6"] reason: Example depends on target, which is supported only for IDF >= 5.0 diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml index f52ddd01..b8985005 100644 --- a/.github/workflows/upload_component.yml +++ b/.github/workflows/upload_component.yml @@ -17,7 +17,7 @@ jobs: uses: espressif/upload-components-ci-action@v1 with: directories: > - bsp/esp32_azure_iot_kit;bsp/esp32_s2_kaluga_kit;bsp/esp_wrover_kit;bsp/esp-box;bsp/esp32_s3_usb_otg;bsp/esp32_s3_eye;bsp/esp32_s3_lcd_ev_board;bsp/esp32_s3_korvo_2;bsp/esp-box-lite;bsp/esp32_lyrat;bsp/esp32_c3_lcdkit;bsp/esp-box-3;bsp/esp_bsp_generic;bsp/esp32_s3_korvo_1;bsp/esp32_p4_function_ev_board;bsp/m5stack_core_s3;bsp/m5dial; + bsp/esp32_azure_iot_kit;bsp/esp32_s2_kaluga_kit;bsp/esp_wrover_kit;bsp/esp-box;bsp/esp32_s3_usb_otg;bsp/esp32_s3_eye;bsp/esp32_s3_lcd_ev_board;bsp/esp32_s3_korvo_2;bsp/esp-box-lite;bsp/esp32_lyrat;bsp/esp32_c3_lcdkit;bsp/esp-box-3;bsp/esp_bsp_generic;bsp/esp32_s3_korvo_1;bsp/esp32_p4_function_ev_board;bsp/m5stack_core_s3;bsp/m5dial;bsp/m5stack_core_2; 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 c0beb8b9..9c09bcc9 100644 --- a/.github/workflows/upload_component_noglib.yml +++ b/.github/workflows/upload_component_noglib.yml @@ -16,7 +16,7 @@ jobs: - name: Upload noglib version of BSPs # TODO: Extend this part to all BSPs env: - BSPs: "bsp/esp_wrover_kit bsp/esp32_s3_eye bsp/esp32_p4_function_ev_board bsp/m5stack_core_s3 bsp/m5dial" + BSPs: "bsp/esp_wrover_kit bsp/esp32_s3_eye bsp/esp32_p4_function_ev_board bsp/m5stack_core_s3 bsp/m5stack_core_2 bsp/m5dial" run: | pip install idf-component-manager==1.* py-markdown-table --upgrade python .github/ci/bsp_noglib.py ${BSPs} diff --git a/README.md b/README.md index 744c91a3..b2bcb3a5 100644 --- a/README.md +++ b/README.md @@ -4,28 +4,29 @@ Board support packages for development boards using Espressif's SoCs, written in C. ## Supported boards -| Board name | SoC | Features | Photo | -|---|---|---|---| -| [ESP-WROVER-KIT](bsp/esp_wrover_kit) | ESP32 | LCD display, uSD card slot | | -| [ESP-BOX](bsp/esp-box) | ESP32-S3 | LCD display with touch, audio codec + power amplifier,
accelerometer and gyroscope | | -| [ESP-BOX-Lite](bsp/esp-box-lite) | ESP32-S3 | LCD display, audio codec + power amplifier | | -| [ESP32-Azure IoT Kit](bsp/esp32_azure_iot_kit) | ESP32 | OLED display, uSD card slot, accelerometer,
magnetometer, humidity, pressure, light
and temperature sensors | | -| [ESP32-S2-Kaluga Kit](bsp/esp32_s2_kaluga_kit) | ESP32-S2 | LCD display, audio codec + power amplifier,
smart LED and camera | | -| [ESP32-S3-USB-OTG](bsp/esp32_s3_usb_otg) | ESP32-S3 | LCD display, uSD card slot, USB-OTG | | -| [ESP32-S3-EYE](bsp/esp32_s3_eye) | ESP32-S3 | LCD display, camera, uSD card slot, microphone and accelerometer | | -| [ESP32-S3-LCD-EV-Board](bsp/esp32_s3_lcd_ev_board) | ESP32-S3 | LCD display with touch, audio codec + power amplifier | | -| [ESP32-S3-LCD-EV-Board-2](bsp/esp32_s3_lcd_ev_board) | ESP32-S3 | LCD display with touch, audio codec + power amplifier | | -| [ESP32-S3-Korvo-2](bsp/esp32_s3_korvo_2) | ESP32-S3 | LCD display, camera, uSD card slot, microphone, audio codec + power amplifier | | -| [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 | 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 | | -| [M5Dial](bsp/m5dial) | ESP32-S3 | LCD display with touch and encoder | | +| Board name | SoC | Features | Photo | +| ---------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| [ESP-WROVER-KIT](bsp/esp_wrover_kit) | ESP32 | LCD display, uSD card slot | | +| [ESP-BOX](bsp/esp-box) | ESP32-S3 | LCD display with touch, audio codec + power amplifier,
accelerometer and gyroscope | | +| [ESP-BOX-Lite](bsp/esp-box-lite) | ESP32-S3 | LCD display, audio codec + power amplifier | | +| [ESP32-Azure IoT Kit](bsp/esp32_azure_iot_kit) | ESP32 | OLED display, uSD card slot, accelerometer,
magnetometer, humidity, pressure, light
and temperature sensors | | +| [ESP32-S2-Kaluga Kit](bsp/esp32_s2_kaluga_kit) | ESP32-S2 | LCD display, audio codec + power amplifier,
smart LED and camera | | +| [ESP32-S3-USB-OTG](bsp/esp32_s3_usb_otg) | ESP32-S3 | LCD display, uSD card slot, USB-OTG | | +| [ESP32-S3-EYE](bsp/esp32_s3_eye) | ESP32-S3 | LCD display, camera, uSD card slot, microphone and accelerometer | | +| [ESP32-S3-LCD-EV-Board](bsp/esp32_s3_lcd_ev_board) | ESP32-S3 | LCD display with touch, audio codec + power amplifier | | +| [ESP32-S3-LCD-EV-Board-2](bsp/esp32_s3_lcd_ev_board) | ESP32-S3 | LCD display with touch, audio codec + power amplifier | | +| [ESP32-S3-Korvo-2](bsp/esp32_s3_korvo_2) | ESP32-S3 | LCD display, camera, uSD card slot, microphone, audio codec + power amplifier | | +| [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 | 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 | | +| [M5Stack Core2](bsp/m5stack_core_2) | ESP32 | LCD display with touch, uSD card slot | | +| [M5Dial](bsp/m5dial) | ESP32-S3 | LCD display with touch and encoder | | ## LCD displays and TOUCH | [LVGL port](components/esp_lvgl_port) | [LCD drivers](LCD.md) | -| :---: | :---: | +| :-----------------------------------: | :-------------------: | The BSP repository includes a lot of LCD and Touch driver components. The list of available and planned LCDs is [here](LCD.md). @@ -39,16 +40,16 @@ Moreover, LVGL port includes recommendations and tips for [increasing graphical Best way to start with ESP-BSP is trying one of the [examples](examples) on your board. Every example contains `README.md` with a list of supported boards. Here is the summary of the available examples: -| Example | Supported boards | Try with ESP Launchpad | -|---|---|---| -| [audio](examples/audio) | ESP32-S3-Korvo-2 | [Flash audio](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=audio) | -| [display](examples/display) | WROVER-KIT | [Flash display](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display) | -| [display_camera](examples/display_camera) | Kaluga-kit | [Flash display_camera](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_camera) | -| [display_audio_photo](examples/display_audio_photo) | ESP-BOX | [Flash display_audio_photo](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_audio_photo) | -| [display_rotation](examples/display_rotation) | ESP-BOX | [Flash display_rotation](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_rotation) | -| [display_lvgl_demos](examples/display_lvgl_demos) | ESP32-S3-LCD-EV-Board | [Flash display_lvgl_demos](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_lvgl_demos) | -| [display_sensors](examples/display_sensors) | Azure-IoT-kit | [Flash display_sensors](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_sensors) | -| [mqtt_example](examples/mqtt_example) | Azure-IoT-kit | - | +| Example | Supported boards | Try with ESP Launchpad | +| --------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [audio](examples/audio) | ESP32-S3-Korvo-2 | [Flash audio](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=audio) | +| [display](examples/display) | WROVER-KIT | [Flash display](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display) | +| [display_camera](examples/display_camera) | Kaluga-kit | [Flash display_camera](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_camera) | +| [display_audio_photo](examples/display_audio_photo) | ESP-BOX | [Flash display_audio_photo](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_audio_photo) | +| [display_rotation](examples/display_rotation) | ESP-BOX | [Flash display_rotation](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_rotation) | +| [display_lvgl_demos](examples/display_lvgl_demos) | ESP32-S3-LCD-EV-Board | [Flash display_lvgl_demos](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_lvgl_demos) | +| [display_sensors](examples/display_sensors) | Azure-IoT-kit | [Flash display_sensors](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-bsp/config.toml&app=display_sensors) | +| [mqtt_example](examples/mqtt_example) | Azure-IoT-kit | - | ### BSP headers and options * `bsp/name-of-the-bsp.h`: Main include file of the BSP with public API diff --git a/SquareLine/boards/v9/m5stack_core_2/image.png b/SquareLine/boards/v9/m5stack_core_2/image.png new file mode 100644 index 00000000..735b3471 Binary files /dev/null and b/SquareLine/boards/v9/m5stack_core_2/image.png differ diff --git a/SquareLine/boards/v9/m5stack_core_2/main/idf_component.yml b/SquareLine/boards/v9/m5stack_core_2/main/idf_component.yml new file mode 100644 index 00000000..9373a608 --- /dev/null +++ b/SquareLine/boards/v9/m5stack_core_2/main/idf_component.yml @@ -0,0 +1,6 @@ +description: ESP-BSP SquareLine LVGL Example +targets: + - esp32 +dependencies: + idf: ">=5.0" + m5stack_core_2: ">=1.0.0" diff --git a/SquareLine/boards/v9/m5stack_core_2/manifest.json b/SquareLine/boards/v9/m5stack_core_2/manifest.json new file mode 100644 index 00000000..d382db56 --- /dev/null +++ b/SquareLine/boards/v9/m5stack_core_2/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "M5Stack Core2", + "version": "1.0.0", + "mcu": "ESP32", + "screen_width": "320", + "screen_height": "240", + "screen_color_swap": true, + "supported_lvgl_version": "9.1.*", + "short_description": "M5Core2 is the second generation core device in the M5Stack development kit series, which further enhances the functions of the original generation of cores.The MCU is an ESP32 model D0WDQ6-V3 and has dual core Xtensa® 32-bit 240Mhz LX6 processors that can be controlled separately. Wi-Fi are supported as standard and it includes an on board 16MB Flash and 8MB PSRAM, USB TYPE-C interface for charging, downloading of programs and serial communication, a 2.0-inch integrated capacitive touch screen, and a built-in vibration motor.", + "long_description": "M5Core2 also features a built-in RTC module which can provide accurate timing. The power supply is managed by an AXP192 power management chip, which can effectively control the power consumption of the base and a built-in green LED power indicator helps to notify the user of battery level. The battery capacity has been upgraded to 390mAh, which can power the core for much longer than the previous model.The M5Core2 retains the TF-card(microSD) slot and speakers. However, in order to ensure higher quality sound output, the I2S digital audio interface power amplifier chip is used to effectively prevent signal distortion. There are independent power and reset buttons on the left side and bottom of the base.", + "placeholders": { + "__ESP_BOARD_INCLUDE__": "bsp/esp-bsp.h", + "__ESP_BOARD_I2C_INIT__": "/* Initialize I2C (for touch) */\n bsp_i2c_init();" + } +} \ No newline at end of file diff --git a/bsp/m5stack_core_2/CMakeLists.txt b/bsp/m5stack_core_2/CMakeLists.txt new file mode 100644 index 00000000..674756f5 --- /dev/null +++ b/bsp/m5stack_core_2/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + SRCS "m5stack_core_2.c" "m5stack_core_2_idf5.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "priv_include" + REQUIRES driver spiffs + PRIV_REQUIRES fatfs esp_lcd +) diff --git a/bsp/m5stack_core_2/Kconfig b/bsp/m5stack_core_2/Kconfig new file mode 100644 index 00000000..e539bcfd --- /dev/null +++ b/bsp/m5stack_core_2/Kconfig @@ -0,0 +1,102 @@ +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 "PMU" + choice PMU_VERSION + prompt "PMU Version" + default BSP_PMU_AXP192 + help + Core2 v1.0 PMU version is AXP192, Core2 v1.1 PMU version is AXP2101, you can determine the version of Core2 by the backplane sticker or PCB. + + config BSP_PMU_AXP192 + bool "AXP192" + + config BSP_PMU_AXP2101 + bool "AXP2101" + + endchoice + endmenu + + 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_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_2/LICENSE b/bsp/m5stack_core_2/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/bsp/m5stack_core_2/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_2/README.md b/bsp/m5stack_core_2/README.md new file mode 100644 index 00000000..89967d1f --- /dev/null +++ b/bsp/m5stack_core_2/README.md @@ -0,0 +1,47 @@ +# BSP: M5Stack Core2 + +> [!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_2/badge.svg)](https://components.espressif.com/components/espressif/m5stack_core_2) + +* [Hardware Reference](https://docs.m5stack.com/en/core/Core2) + +basicgray + +M5Core2 is the second generation core device in the M5Stack development kit series, which further enhances the functions of the original generation of cores. It is a powerful and user-friendly development board with the following features: + +- **MCU**: Equipped with an ESP32-D0WDQ6-V3, featuring dual core Xtensa® 32-bit 240Mhz LX6 processors that can be controlled separately. +- **Memory**: Onboard 16MB Flash and 8MB PSRAM. +- **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. +- **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. +Additional Features: Built-in vibration motor for haptic feedback, independent power, and reset buttons on the left side and bottom of the base. + +#### Core2 V1.1 Enhancements +Core2 V1.1 is an iterative version of Core2 with the following upgrades and additional features: + +- **Power Management**: Uses the AXP2101 power management chip for enhanced power control. +- **Indicators**: Built-in blue power indicator light for specific functions or status indications. +- RTC Battery: Dedicated battery for RTC power supply for accurate timing. +- **User Interaction**: Enhanced touch screen experience with programmable virtual buttons for diverse human-machine interaction. + + + + +### 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 |:heavy_check_mark:|[espressif/esp_lcd_touch_ft5x06](https://components.espressif.com/components/espressif/esp_lcd_touch_ft5x06)| ^1 | +| BUTTONS | :x: | | | +| AUDIO |:heavy_check_mark:| [espressif/esp_codec_dev](https://components.espressif.com/components/espressif/esp_codec_dev) | ~1.1 | +|AUDIO_SPEAKER|:heavy_check_mark:| | | +| AUDIO_MIC | :x: | | | +| SDCARD |:heavy_check_mark:| idf | >=5.0 | +| IMU | :x: | | | + diff --git a/bsp/m5stack_core_2/idf_component.yml b/bsp/m5stack_core_2/idf_component.yml new file mode 100644 index 00000000..353132c8 --- /dev/null +++ b/bsp/m5stack_core_2/idf_component.yml @@ -0,0 +1,23 @@ +version: "1.0.0" +description: Board Support Package (BSP) for M5Stack Core2 +url: https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_2 + +targets: + - esp32 + +tags: + - bsp + +dependencies: + idf: ">=5.0" + esp_lcd_ili9341: "^1" + esp_lcd_touch_ft5x06: "^1" + + espressif/esp_lvgl_port: + version: "^2" + public: true + override_path: "../../components/esp_lvgl_port" + + esp_codec_dev: + version: "~1.1" + public: true diff --git a/bsp/m5stack_core_2/include/bsp/config.h b/bsp/m5stack_core_2/include/bsp/config.h new file mode 100644 index 00000000..f3cb5ebe --- /dev/null +++ b/bsp/m5stack_core_2/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_2/include/bsp/display.h b/bsp/m5stack_core_2/include/bsp/display.h new file mode 100644 index 00000000..1963bbd6 --- /dev/null +++ b/bsp/m5stack_core_2/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_2/include/bsp/esp-bsp.h b/bsp/m5stack_core_2/include/bsp/esp-bsp.h new file mode 100644 index 00000000..642f9e17 --- /dev/null +++ b/bsp/m5stack_core_2/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_2.h" diff --git a/bsp/m5stack_core_2/include/bsp/m5stack_core_2.h b/bsp/m5stack_core_2/include/bsp/m5stack_core_2.h new file mode 100644 index 00000000..ac827867 --- /dev/null +++ b/bsp/m5stack_core_2/include/bsp/m5stack_core_2.h @@ -0,0 +1,361 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ESP BSP: M5Stack Core2 + */ + +#pragma once + +#include "sdkconfig.h" +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "driver/sdmmc_host.h" +#include "esp_codec_dev.h" +#include "bsp/config.h" +#include "bsp/display.h" + +#include "driver/i2s_std.h" + +#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 0 +#define BSP_CAPS_SDCARD 1 +#define BSP_CAPS_IMU 0 + +/************************************************************************************************** + * M5Stack-Core-2 pinout + **************************************************************************************************/ +/* I2C */ +#define BSP_I2C_SCL (GPIO_NUM_22) +#define BSP_I2C_SDA (GPIO_NUM_21) +/* Audio */ +#define BSP_I2S_SCLK (GPIO_NUM_12) //I2S_BCK +#define BSP_I2S_MCLK (GPIO_NUM_NC) +#define BSP_I2S_LCLK (GPIO_NUM_0) //I2S_WCK +#define BSP_I2S_DOUT (GPIO_NUM_2) +#define BSP_I2S_DSIN (GPIO_NUM_34) +#define BSP_POWER_AMP_IO (GPIO_NUM_NC) +#define BSP_MUTE_STATUS (GPIO_NUM_NC) +/* Display */ +#define BSP_LCD_MOSI (GPIO_NUM_23) +#define BSP_LCD_MISO (GPIO_NUM_38) +#define BSP_LCD_PCLK (GPIO_NUM_18) +#define BSP_LCD_CS (GPIO_NUM_5) +#define BSP_LCD_DC (GPIO_NUM_15) +#define BSP_LCD_RST (GPIO_NUM_NC) +#define BSP_LCD_BACKLIGHT (GPIO_NUM_NC) +#define BSP_LCD_TOUCH_INT (GPIO_NUM_39) + +/* SD card */ +#define BSP_SD_MOSI (GPIO_NUM_23) +#define BSP_SD_MISO (GPIO_NUM_38) +#define BSP_SD_SCK (GPIO_NUM_18) +#define BSP_SD_CS (GPIO_NUM_4) + + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + * + * I2S audio interface + * + * For speaker initialization use bsp_audio_codec_speaker_init() which is inside initialize I2S with bsp_audio_init(). + * After speaker 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); + +/************************************************************************************************** + * + * I2C interface + * + * There are multiple devices connected to I2C peripheral: + * - AXP192 / AXP2101 PMU + * - LCD Touch controller + **************************************************************************************************/ +#define BSP_I2C_NUM CONFIG_BSP_I2C_NUM + +/** + * @brief Init I2C driver + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG I2C parameter error + * - ESP_FAIL I2C driver installation error + * + */ +esp_err_t bsp_i2c_init(void); + +/** + * @brief Deinit I2C driver and free its resources + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG I2C parameter error + * + */ +esp_err_t bsp_i2c_deinit(void); + +/************************************************************************************************** + * + * SPIFFS + * + * After mounting the SPIFFS, it can be accessed with stdio functions ie.: + * \code{.c} + * FILE* f = fopen(BSP_SPIFFS_MOUNT_POINT"/hello.txt", "w"); + * fprintf(f, "Hello World!\n"); + * fclose(f); + * \endcode + **************************************************************************************************/ +#define BSP_SPIFFS_MOUNT_POINT CONFIG_BSP_SPIFFS_MOUNT_POINT + +/** + * @brief Mount SPIFFS to virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_register was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes + */ +esp_err_t bsp_spiffs_mount(void); + +/** + * @brief Unmount SPIFFS from virtual file system + * + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain SPIFFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_unregister was already called + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes + */ +esp_err_t bsp_spiffs_unmount(void); + +/************************************************************************************************** + * + * 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-2 is shipped with 2.0inch ILI9341C 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 (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_TOUCH, + BSP_FEATURE_SD, + BSP_FEATURE_SPEAKER, + BSP_FEATURE_BATTERY, + BSP_FEATURE_VIBRATION +} bsp_feature_t; + +esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/m5stack_core_2/include/bsp/touch.h b/bsp/m5stack_core_2/include/bsp/touch.h new file mode 100644 index 00000000..095e8ce1 --- /dev/null +++ b/bsp/m5stack_core_2/include/bsp/touch.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief BSP Touchscreen + * + * This file offers API for basic touchscreen initialization. + * It is useful for users who want to use the touchscreen without the default Graphical Library LVGL. + * + * For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_touch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief BSP touch configuration structure + * + */ +typedef struct { + void *dummy; /*!< Prepared for future use. */ +} bsp_touch_config_t; + +/** + * @brief Create new touchscreen + * + * If you want to free resources allocated by this function, you can use esp_lcd_touch API, ie.: + * + * \code{.c} + * esp_lcd_touch_del(tp); + * \endcode + * + * @param[in] config touch configuration + * @param[out] ret_touch esp_lcd_touch touchscreen handle + * @return + * - ESP_OK On success + * - Else esp_lcd_touch failure + */ +esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch); + +#ifdef __cplusplus +} +#endif diff --git a/bsp/m5stack_core_2/m5stack_core_2.c b/bsp/m5stack_core_2/m5stack_core_2.c new file mode 100644 index 00000000..fd7f8c6b --- /dev/null +++ b/bsp/m5stack_core_2/m5stack_core_2.c @@ -0,0 +1,603 @@ +/* + * SPDX-FileCopyrightText: 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_2.h" +#include "bsp/display.h" +#include "bsp/touch.h" +#include "esp_lcd_ili9341.h" +#include "esp_lcd_touch_ft5x06.h" +#include "bsp_err_check.h" +#include "esp_codec_dev_defaults.h" + +static const char *TAG = "M5Stack"; + +#define BSP_AXP192_ADDR 0x34 +#define BSP_AXP2101_ADDR 0x34 + +#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static lv_display_t *disp; +static lv_indev_t *disp_indev = NULL; +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) +static esp_lcd_touch_handle_t tp; // LCD touch handle +sdmmc_card_t *bsp_sdcard = NULL; // Global 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; +} + +uint8_t read8bit(uint8_t sub_addr) +{ + // Read register data + uint8_t reg_data[1] = {0}; + esp_err_t err = i2c_master_write_read_device(BSP_I2C_NUM, BSP_AXP192_ADDR, &sub_addr, 1, reg_data, sizeof(reg_data), + 1000 / portTICK_PERIOD_MS); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write & read register address: %s", esp_err_to_name(err)); + } + ESP_LOGD(TAG, "AXP192 register %x: 0x%x", sub_addr, reg_data[0]); + + return reg_data[0]; +} + +esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable) +{ + esp_err_t err = ESP_OK; + + /* Initilize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); + + switch (feature) { + case BSP_FEATURE_LCD: // ldo2 + case BSP_FEATURE_TOUCH: + case BSP_FEATURE_SD: +#if defined(CONFIG_BSP_PMU_AXP2101) + /* AXP ALDO4 voltage / SD Card / Touch Pad / 3V3 */ + const uint8_t aldo4_value = enable ? 0x1C : 0x00; + const uint8_t feature_ctr[] = {0x95, aldo4_value}; // axp: lcd logic and sdcard voltage preset to 3.3v + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, feature_ctr, sizeof(feature_ctr), + 1000 / portTICK_PERIOD_MS); + +#elif defined(CONFIG_BSP_PMU_AXP192) + const uint8_t pmu_value = enable ? (read8bit(0x28) & 0x0f) | 0xf0 : (read8bit(0x28) & 0x0f); + const uint8_t pmu_ldo2[] = { + 0x28, pmu_value + }; + + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_ldo2, sizeof(pmu_ldo2), + 1000 / portTICK_PERIOD_MS); +#endif + break; + case BSP_FEATURE_SPEAKER: +#if defined(CONFIG_BSP_PMU_AXP2101) + /* AXP ALDO3 voltage / Codec+Mic / 3V3 */ + const uint8_t aldo3_value = enable ? 0x1C : 0x00; + const uint8_t spk_ctr[] = {0x94, aldo3_value}; // axp: lcd logic and sdcard voltage preset to 3.3v + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, spk_ctr, sizeof(spk_ctr), + 1000 / portTICK_PERIOD_MS); +#elif defined(CONFIG_BSP_PMU_AXP192) + const uint8_t led_gpio_value = enable ? (read8bit(0x94) | 0x04) | 0xf0 : (read8bit(0x94) & ~0x04); + const uint8_t led_gpio_set[] = {0x94, led_gpio_value}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, led_gpio_set, + sizeof(led_gpio_set), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); +#endif + break; + case BSP_FEATURE_BATTERY: +#if defined(CONFIG_BSP_PMU_AXP2101) + // Battery detection enabled. + const uint8_t axp_bat_val = enable ? 0x01 : 0x00; + const uint8_t axp_bat_ctr[] = {0x68, axp_bat_val}; + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, axp_bat_ctr, sizeof(axp_bat_ctr), + 1000 / portTICK_PERIOD_MS); +#endif + break; + case BSP_FEATURE_VIBRATION: +#if defined(CONFIG_BSP_PMU_AXP2101) + const uint8_t dldo1_vol[] = {0x99, 0x1C}; // AXP DLDO1 Voltage set + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, dldo1_vol, sizeof(dldo1_vol), + 1000 / portTICK_PERIOD_MS); + const uint8_t dldo1_en_val = enable ? (read8bit(0x90) | 0x80) : (read8bit(0x90) & ~0x80); + const uint8_t dldo1_en[] = {0x90, dldo1_en_val}; // AXP DLDO1 Enable + err |= i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, dldo1_en, sizeof(dldo1_en), + 1000 / portTICK_PERIOD_MS); +#elif defined(CONFIG_BSP_PMU_AXP192) + const uint8_t pmu_ldo3[] = {0x28, (read8bit(0x28) & 0xf0) | 0x0f}; // Vibrator power voltage preset + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_ldo3, sizeof(pmu_ldo3), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_ldo3_en_val = enable ? read8bit(0x12) | 0x08 : read8bit(0x12) & ~0x08; + const uint8_t pmu_ldo3_en[] = {0x12, pmu_ldo3_en_val}; // ldo3 enable + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_ldo3_en, sizeof(pmu_ldo3_en), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); +#endif + 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) +{ + BSP_ERROR_CHECK_RETURN_ERR(bsp_feature_enable(BSP_FEATURE_SD, true)); + + 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_feature_enable(BSP_FEATURE_SPEAKER, true)); + + esp_codec_dev_cfg_t codec_dev_cfg = { + .dev_type = ESP_CODEC_DEV_TYPE_OUT, + .codec_if = NULL, + .data_if = i2s_data_if, + }; + return esp_codec_dev_new(&codec_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 + +esp_err_t bsp_display_brightness_init(void) +{ + /* Initilize I2C */ + BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init()); +#if defined(CONFIG_BSP_PMU_AXP2101) + const uint8_t lcd_bl_en[] = {0x90, 0x3F}; // AXP ALDO1~4 BLDO1~2 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[] = {0x96, 0b000011000}; // AXP BLDO1 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"); + + // AXP2101 + // PowerKey Hold=1sec / PowerOff=4sec IRQLEVEL/OFFLEVEL/ONLEVEL setting + const uint8_t axp_pwr_val[] = {0x27, 0b00000000}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, axp_pwr_val, sizeof(axp_pwr_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + // Internal off-discharge enable for DCDC & LDO & SWITCH + const uint8_t axp_en_val[] = {0x10, 0b00110000}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, axp_en_val, sizeof(axp_en_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + // BATFET disable + const uint8_t axp_bat_val[] = {0x12, 0b00000000}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, axp_bat_val, sizeof(axp_bat_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + // CHGLED setting + const uint8_t axp_hgled_val[] = {0x69, 0b00010011}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP2101_ADDR, axp_hgled_val, sizeof(axp_hgled_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); +#elif defined(CONFIG_BSP_PMU_AXP192) + read8bit(0x12); + + const uint8_t vbus_limit[] = {0x30, (read8bit(0x30) & 0x04) | 0x02}; // axp: vbus limit off + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, vbus_limit, sizeof(vbus_limit), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_gpio1[] = {0x92, read8bit(0x92) & 0xf8}; // AXP192 GPIO1:OD OUTPUT + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_gpio1, sizeof(pmu_gpio1), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_gpio2[] = {0x93, read8bit(0x93) & 0xf8}; // AXP192 GPIO2:OD OUTPUT + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_gpio2, sizeof(pmu_gpio2), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_gpio3[] = {0x35, (read8bit(0x35) & 0x1c) | 0xa2}; // AXP192 RTC CHG + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_gpio3, sizeof(pmu_gpio3), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t esp_vol[] = {0x26, 0x6a}; // AXP192 RTC CHG + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, esp_vol, sizeof(esp_vol), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t lcd_bl_val[] = {0x27, 0x68}; // Lcd backlight voltage + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, lcd_bl_val, sizeof(lcd_bl_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_ldo2[] = {0x28, + (read8bit(0x28) & 0x0f) | 0xf0 + }; // axp: lcd logic and sdcard voltage preset to 3.3v + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_ldo2, sizeof(pmu_ldo2), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t pmu_ldo2_en[] = {0x12, (read8bit(0x12) & 0xfb) | 0x04}; // ldo2 enable + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pmu_ldo2_en, sizeof(pmu_ldo2_en), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t lcd_bl_en[] = {0x12, (read8bit(0x12) & 0xfd) | 0x02}; // Lcd backlight enable + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, lcd_bl_en, sizeof(lcd_bl_en), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + + const uint8_t chg_current[] = {0x33, ((read8bit(0x33) & 0xf0)) | 0x0}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, chg_current, sizeof(chg_current), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + + const uint8_t apx_gpio4[] = {0x95, (read8bit(0x95) & 0x72) | 0x84}; + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, apx_gpio4, sizeof(apx_gpio4), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + read8bit(0x95); + const uint8_t pek_key[] = {0x36, 0x4c}; // Lcd backlight enable + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, pek_key, sizeof(pek_key), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t adc_en[] = {0x82, 0xff}; // Lcd backlight enable + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, adc_en, sizeof(adc_en), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + const uint8_t lcd_rset2[] = {0x96, read8bit(0x96) &(~0x02)}; // Lcd backlight enable + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, lcd_rset2, sizeof(lcd_rset2), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); + vTaskDelay(pdMS_TO_TICKS(100)); // 延迟100ms + const uint8_t lcd_rset[] = {0x96, read8bit(0x96) | 0x02}; // Lcd backlight enable + ESP_RETURN_ON_ERROR( + i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, lcd_rset, sizeof(lcd_rset), 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); +#endif + 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); +#if defined(CONFIG_BSP_PMU_AXP2101) + const uint8_t reg_val = 20 + ((8 * brightness_percent) / 100); // 0b00000 ~ 0b11100; under 20, it is too dark + const uint8_t lcd_bl_val[] = {0x96, reg_val}; // AXP BLDO1 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"); +#elif defined(CONFIG_BSP_PMU_AXP192) + const uint8_t reg_val = 90 + ((8 * brightness_percent) / 100); // 0b00000 ~ 0b11100; under 20, it is too dark + const uint8_t lcd_bl_val[] = {0x27, reg_val}; // AXP DCDC3 voltage + ESP_RETURN_ON_ERROR(i2c_master_write_to_device(BSP_I2C_NUM, BSP_AXP192_ADDR, lcd_bl_val, sizeof(lcd_bl_val), + 1000 / portTICK_PERIOD_MS), + TAG, "I2C write failed"); +#endif + + 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); + 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_feature_enable(BSP_FEATURE_TOUCH, true)); + + /* 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 = 0, + .mirror_y = 0, + }, + }; + esp_lcd_panel_io_handle_t tp_io_handle = NULL; + const esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_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_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 lv_indev_t *bsp_display_indev_init(lv_display_t *disp) +{ + BSP_ERROR_CHECK_RETURN_NULL(bsp_touch_new(NULL, &tp)); + assert(tp); + + /* Add touch input (for selected screen) */ + const lvgl_port_touch_cfg_t touch_cfg = { + .disp = disp, + .handle = tp, + }; + + return lvgl_port_add_touch(&touch_cfg); +} + +lv_display_t *bsp_display_start(void) +{ + bsp_display_cfg_t cfg = {.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(), + .buffer_size = BSP_LCD_DRAW_BUFF_SIZE, + .double_buffer = BSP_LCD_DRAW_BUFF_DOUBLE, + .flags = { + .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); + + BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL); + + return disp; +} + +lv_indev_t *bsp_display_get_input_dev(void) +{ + return disp_indev; +} + +void bsp_display_rotate(lv_display_t *disp, lv_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(); +} + +#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0) diff --git a/bsp/m5stack_core_2/m5stack_core_2_idf5.c b/bsp/m5stack_core_2/m5stack_core_2_idf5.c new file mode 100644 index 00000000..a79d1ad7 --- /dev/null +++ b/bsp/m5stack_core_2/m5stack_core_2_idf5.c @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_err.h" +#include "bsp/m5stack_core_2.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 \ + { \ + .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 = true, \ + }, \ + .mclk = BSP_I2S_MCLK, \ + } +/* 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) { + ESP_LOGW(TAG, "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 */ + i2s_std_config_t std_cfg_default = BSP_I2S_DUPLEX_MONO_CFG(44100); + + 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 TX channel initialization failed"); + ESP_GOTO_ON_ERROR(i2s_channel_enable(i2s_tx_chan), err, TAG, "I2S TX 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 RX channel initialization failed"); + ESP_GOTO_ON_ERROR(i2s_channel_enable(i2s_rx_chan), err, TAG, "I2S RX 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); + + ESP_LOGI(TAG, "I2S initialized successfully"); + + ESP_LOGI(TAG, "I2S config: sample_rate=%lu, data_bit_width=%d, slot_mode=%ld", + (unsigned long)p_i2s_cfg->clk_cfg.sample_rate_hz, p_i2s_cfg->slot_cfg.data_bit_width, + (long)p_i2s_cfg->slot_cfg.slot_mode); + + return ESP_OK; + +err: + if (i2s_tx_chan) { + i2s_del_channel(i2s_tx_chan); + } + if (i2s_rx_chan) { + i2s_del_channel(i2s_rx_chan); + } + + ESP_LOGE(TAG, "Initialization failed, ret: %d", ret); + return ret; +} + +const audio_codec_data_if_t *bsp_audio_get_codec_itf(void) +{ + return i2s_data_if; +} diff --git a/bsp/m5stack_core_2/priv_include/bsp_err_check.h b/bsp/m5stack_core_2/priv_include/bsp_err_check.h new file mode 100644 index 00000000..cf2f36eb --- /dev/null +++ b/bsp/m5stack_core_2/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/docu/pics/m5stack_core2.webp b/docu/pics/m5stack_core2.webp new file mode 100644 index 00000000..b91f44f2 Binary files /dev/null and b/docu/pics/m5stack_core2.webp differ diff --git a/examples/bsp_ext.py b/examples/bsp_ext.py index 1ed1b2c9..c135cea2 100644 --- a/examples/bsp_ext.py +++ b/examples/bsp_ext.py @@ -59,7 +59,8 @@ def set_bsp_callback(action: str, ctx: Context, args: PropertyDict, **kwargs: st 'esp32_s3_korvo_1', 'esp32_p4_function_ev_board', 'm5stack_core_s3', - 'm5dial' + 'm5dial', + 'm5stack_core_2' } if bsp == '': diff --git a/examples/display/sdkconfig.bsp.m5stack_core_2 b/examples/display/sdkconfig.bsp.m5stack_core_2 new file mode 100644 index 00000000..2394a8df --- /dev/null +++ b/examples/display/sdkconfig.bsp.m5stack_core_2 @@ -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_16MB=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 diff --git a/examples/display_audio_photo/main/app_disp_fs.c b/examples/display_audio_photo/main/app_disp_fs.c index 51287975..79c93085 100644 --- a/examples/display_audio_photo/main/app_disp_fs.c +++ b/examples/display_audio_photo/main/app_disp_fs.c @@ -164,10 +164,12 @@ void app_audio_init(void) esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME); /* Initialize microphone */ +#if BSP_CAPS_AUDIO_MIC mic_codec_dev = bsp_audio_codec_microphone_init(); assert(mic_codec_dev); /* Microphone input gain */ esp_codec_dev_set_in_gain(mic_codec_dev, 50.0); +#endif } void app_disp_fs_init(void) @@ -766,6 +768,7 @@ static void rec_stop_event_cb(lv_event_t *e) static void rec_file(void *arg) { +#if BSP_CAPS_AUDIO_MIC char *path = arg; FILE *record_file = NULL; int16_t *recording_buffer = heap_caps_malloc(BUFFER_SIZE, MALLOC_CAP_DEFAULT); @@ -834,6 +837,9 @@ static void rec_file(void *arg) } vTaskDelete(NULL); +#else + ESP_LOGI(TAG, "Recording not supported!"); +#endif } /* Stop playing recorded audio file */ diff --git a/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_2 b/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_2 new file mode 100644 index 00000000..e885cc57 --- /dev/null +++ b/examples/display_audio_photo/sdkconfig.bsp.m5stack_core_2 @@ -0,0 +1,26 @@ +# 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_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_LV_USE_CLIB_MALLOC=y +CONFIG_LV_USE_CLIB_STRING=y +CONFIG_LV_USE_CLIB_SPRINTF=y +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +CONFIG_LV_FONT_MONTSERRAT_12=y +CONFIG_LV_FONT_MONTSERRAT_16=y +CONFIG_LV_USE_OBSERVER=y +CONFIG_LV_USE_SYSMON=y +CONFIG_LV_USE_PERF_MONITOR=y +CONFIG_LV_BUILD_EXAMPLES=n +CONFIG_LV_USE_DEMO_WIDGETS=y +CONFIG_LV_USE_DEMO_STRESS=y +CONFIG_LV_USE_DEMO_MUSIC=y +CONFIG_LV_DEMO_MUSIC_ROUND=y +CONFIG_LV_DEMO_MUSIC_AUTO_PLAY=y +