Add M5Stack CoreP4 board support. (#2061)
Build Boards / Build ESP32-S31 with IDF 6.1 (push) Has been cancelled
Build Boards / IDF 6 BluFi option (push) Has been cancelled
Build Boards / Determine variants to build (push) Has been cancelled
Build Boards / Build ${{ matrix.full_name }} (push) Has been cancelled

Co-authored-by: luoweiyuan <luoweiyuan@m5stack.com>
This commit is contained in:
Create123
2026-07-29 17:51:47 +08:00
committed by GitHub
parent e0074e90ce
commit dd99da00dc
7 changed files with 571 additions and 0 deletions
+5
View File
@@ -206,6 +206,11 @@ elseif(CONFIG_BOARD_TYPE_M5STACK_STOPWATCH)
set(BUILTIN_TEXT_FONT font_noto_sans_basic_30_4)
set(BUILTIN_ICON_FONT font_material_symbols_30_4)
set(DEFAULT_EMOJI_COLLECTION noto-color-emoji_64)
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_P4)
set(BOARD_DIR "m5stack/corep4")
set(BUILTIN_TEXT_FONT font_noto_sans_basic_30_4)
set(BUILTIN_ICON_FONT font_material_symbols_30_4)
set(DEFAULT_EMOJI_COLLECTION noto-color-emoji_64)
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_S3)
set(BOARD_DIR "m5stack/core-s3")
set(BUILTIN_TEXT_FONT font_noto_sans_basic_20_4)
+3
View File
@@ -325,6 +325,9 @@ choice BOARD_TYPE
config BOARD_TYPE_M5STACK_CARDPUTER_ADV
bool "M5Stack Cardputer Adv"
depends on IDF_TARGET_ESP32S3
config BOARD_TYPE_M5STACK_CORE_P4
bool "M5Stack CoreP4"
depends on IDF_TARGET_ESP32P4
config BOARD_TYPE_M5STACK_CORE_S3
bool "M5Stack CoreS3"
depends on IDF_TARGET_ESP32S3
+79
View File
@@ -0,0 +1,79 @@
# M5Stack CoreP4
- **MCU**: ESP32-P4
- **PSRAM**: 8MB
- **Flash**: 16MB
- **Wi-Fi**: ESP32-C6, ESP-Hosted SDIO
- **Display**: 480x480 MIPI LCD, Capacitive Touch Panel
-----------
## Hardware
* **I2C1**
* SCL -- G9
* SDA -- G11
* **M5STP2 / PM1 (Power)**
* Interface: I2C1 @**0x6E**
* **IO Expander: M5IOE1**
* Interface: I2C1 @**0x4F**
* **Wi-Fi**
* RST -- G42
* SDIO
* CMD -- G44
* CLK -- G43
* D0 -- G45
* D1 -- G46
* D2 -- G47
* D3 -- G48
* **Display**
* Driver: ST7102
* Interface: MIPI
* PWR_EN -- M5IOE1_G10 (Active High)
* RST -- M5IOE1_G11
* BL -- M5IOE1_G9/PWM1
* **Touch Panel**
* Driver: CST3xx
* Interface: I2C1
* RST -- M5IOE1_G8
* INT -- G1
* **Audio**
* PWR_EN -- M5IOE1_G1 (Active High)
* ADC: ES7210
* Control Interface: I2C1
* Data Interface: I2S0
* DAC: ES8311
* Control Interface: I2C1
* Data Interface: I2S0
* MCLK -- G2
* BCLK -- G6
* WS -- G4
* DOUT -- G3
* DIN -- G5
* PA: AW8737A
* EN -- M5IOE1_G3 (Active High)
* **IMU: BMI270**
* Interface: I2C1 @0x68
* INT -- G0
* **RTC: RX8130CE**
* Interface: I2C1 @0x51
* INT -- G4
-----------
## 构建
CoreP4 使用 ESP32-C6 作为 Wi-Fi 协处理器,通过 ESP-Hosted SDIO 连接。板级配置已包含实际使用的 SDIO 引脚和复位引脚。
早期 ESP32-P4 芯片使用 ESP-IDF 5.5
```bash
python3 scripts/build.py m5stack/corep4 --name m5stack-corep4 --zip
```
ESP32-P4 v3.xP4X)使用 ESP-IDF 6.0 或更高版本:
```bash
python3 scripts/build.py m5stack/corep4 --name m5stack-corep4x --zip
```
构建脚本会生成合并固件和 release ZIP。烧录前请确认设备使用的 ESP32-P4 芯片版本与构建变体一致。
+65
View File
@@ -0,0 +1,65 @@
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_
#include <driver/gpio.h>
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
// I2S Audio Configuration (I2S0)
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_2
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_6
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_3
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_5
// Audio Codec I2C (SYS_I2C/I2C1)
#define AUDIO_INPUT_REFERENCE true
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_11
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_9
#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR
#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR
#define AUDIO_CODEC_GPIO_PA GPIO_NUM_NC
// Buttons
#define BOOT_BUTTON_GPIO GPIO_NUM_0
// I2C Configuration
#define SYS_I2C_PORT I2C_NUM_1
// IO expander pins (see M5 CoreP4 reference components/m5stack_corep4/include/m5stack_corep4.h).
// I2C: use M5PM1_DEFAULT_ADDR (0x6E) and M5IOE1_DEFAULT_ADDR (0x6F) in board .cc.
#define IOE1_PIN_LCD_BL M5IOE1_PIN_9 // G9 / PWM1 (M5IOE1_PWM_CH1)
#define IOE1_PIN_LCD_PWR M5IOE1_PIN_10 // G10 — LCD_PWR_EN (see reference display.cpp)
#define IOE1_PIN_LCD_RST M5IOE1_PIN_11 // G11 — LCD_RST
#define IOE1_PIN_TOUCH_RST M5IOE1_PIN_8 // G8 — TP_RST
#define IOE1_PIN_AUDIO_PWR M5IOE1_PIN_1 // G1
#define IOE1_PIN_PA_EN M5IOE1_PIN_3 // G3
// Touch
#define TOUCH_INT_PIN GPIO_NUM_1
// Display configuration (MIPI DSI)
#define DISPLAY_WIDTH 480
#define DISPLAY_HEIGHT 480
#define DISPLAY_OFFSET_X 0
#define DISPLAY_OFFSET_Y 0
#define DISPLAY_MIRROR_X false
#define DISPLAY_MIRROR_Y false
#define DISPLAY_SWAP_XY false
#define DISPLAY_MIPI_LANE_NUM 2
#define DISPLAY_MIPI_LANE_BITRATE_MBPS 600
#define DISPLAY_PIXEL_CLOCK_MHZ 24
#define DISPLAY_HSYNC_PW 2
#define DISPLAY_HSYNC_BP 40
#define DISPLAY_HSYNC_FP 40
#define DISPLAY_VSYNC_PW 4
#define DISPLAY_VSYNC_BP 8
#define DISPLAY_VSYNC_FP 200
// MIPI DSI PHY power
#define MIPI_DSI_PHY_PWR_LDO_CHAN 3
#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
#endif // _BOARD_CONFIG_H_
+47
View File
@@ -0,0 +1,47 @@
{
"manufacturer": "m5stack",
"type": "m5stack-corep4",
"target": "esp32p4",
"builds": [
{
"name": "m5stack-corep4",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_BOARD_TYPE_M5STACK_CORE_P4=y",
"CONFIG_SLAVE_IDF_TARGET_ESP32C6=y",
"CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y",
"CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y",
"CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH=y",
"CONFIG_ESP_HOSTED_SDIO_SLOT_1=y",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CMD_SLOT_1=44",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CLK_SLOT_1=43",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D0_SLOT_1=45",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D1_4BIT_BUS_SLOT_1=46",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D2_4BIT_BUS_SLOT_1=47",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D3_4BIT_BUS_SLOT_1=48",
"CONFIG_ESP_HOSTED_SDIO_GPIO_RESET_SLAVE=42",
"CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y",
"CONFIG_ESP32P4_REV_MIN_100=y"
]
},
{
"name": "m5stack-corep4x",
"idf_version": ">=6.0",
"sdkconfig_append": [
"CONFIG_BOARD_TYPE_M5STACK_CORE_P4=y",
"CONFIG_SLAVE_IDF_TARGET_ESP32C6=y",
"CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y",
"CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y",
"CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH=y",
"CONFIG_ESP_HOSTED_SDIO_SLOT_1=y",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CMD_SLOT_1=44",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CLK_SLOT_1=43",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D0_SLOT_1=45",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D1_4BIT_BUS_SLOT_1=46",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D2_4BIT_BUS_SLOT_1=47",
"CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D3_4BIT_BUS_SLOT_1=48",
"CONFIG_ESP_HOSTED_SDIO_GPIO_RESET_SLAVE=42"
]
}
]
}
@@ -0,0 +1,368 @@
#include "wifi_board.h"
#include "codecs/box_audio_codec.h"
#include "display/lcd_display.h"
#include "application.h"
#include "button.h"
#include "config.h"
#include "backlight.h"
#include "M5IOE1.h"
#include "M5PM1.h"
#include <driver/i2c_master.h>
#include <esp_idf_version.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_mipi_dsi.h"
#include "esp_ldo_regulator.h"
#include "esp_lcd_st7102.h"
#include <esp_lvgl_port.h>
#define TAG "M5StackCoreP4"
static const st7102_lcd_init_cmd_t st7102_init_cmds[] = {
{.cmd = 0x99, .data = (uint8_t[]){0x71, 0x02, 0xA2}, .data_bytes = 3, .delay_ms = 0},
{.cmd = 0x99, .data = (uint8_t[]){0x71, 0x02, 0xA3}, .data_bytes = 3, .delay_ms = 0},
{.cmd = 0x99, .data = (uint8_t[]){0x71, 0x02, 0xA4}, .data_bytes = 3, .delay_ms = 0},
{.cmd = 0x78, .data = (uint8_t[]){0x21}, .data_bytes = 1, .delay_ms = 0},
{.cmd = 0x79, .data = (uint8_t[]){0xCF}, .data_bytes = 1, .delay_ms = 0},
{.cmd = 0xB0, .data = (uint8_t[]){0x22, 0x43, 0x1E, 0x43, 0x2F, 0x57, 0x57}, .data_bytes = 7, .delay_ms = 0},
{.cmd = 0xB7, .data = (uint8_t[]){0x7D, 0x7D}, .data_bytes = 2, .delay_ms = 0},
{.cmd = 0xBF, .data = (uint8_t[]){0x7A, 0x7A}, .data_bytes = 2, .delay_ms = 0},
{.cmd = 0xC8,
.data = (uint8_t[]){0x00, 0x00, 0x13, 0x23, 0x3E, 0x00, 0x6A, 0x03, 0xB0, 0x06, 0x11, 0x0F, 0x07,
0x85, 0x03, 0x21, 0xD5, 0x01, 0x18, 0x00, 0x22, 0x56, 0x0F, 0x98, 0x0A, 0x32,
0xF8, 0x0D, 0x48, 0x0F, 0xF3, 0x80, 0x0F, 0xAC, 0xC1, 0x03, 0xC4},
.data_bytes = 37,
.delay_ms = 0},
{.cmd = 0xC9,
.data = (uint8_t[]){0x00, 0x00, 0x13, 0x23, 0x3E, 0x00, 0x6A, 0x03, 0xB0, 0x06, 0x11, 0x0F, 0x07,
0x85, 0x03, 0x21, 0xD5, 0x01, 0x18, 0x00, 0x22, 0x56, 0x0F, 0x98, 0x0A, 0x32,
0xF8, 0x0D, 0x48, 0x0F, 0xF3, 0x80, 0x0F, 0xAC, 0xC1, 0x03, 0xC4},
.data_bytes = 37,
.delay_ms = 0},
{.cmd = 0xD7, .data = (uint8_t[]){0x10, 0x0C, 0x02, 0x19, 0x40, 0x40}, .data_bytes = 6, .delay_ms = 0},
{.cmd = 0xA3,
.data = (uint8_t[]){0x40, 0x03, 0x80, 0xCF, 0x44, 0x00, 0x00, 0x00, 0x02, 0x05, 0x6F,
0x6F, 0x00, 0x1A, 0x00, 0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x46,
0x00, 0x00, 0x02, 0x20, 0x52, 0x00, 0x05, 0x00, 0x00, 0xFF},
.data_bytes = 32,
.delay_ms = 0},
{.cmd = 0xA6,
.data =
(uint8_t[]){0x02, 0x00, 0x24, 0x55, 0x35, 0x00, 0x38, 0x00, 0x97, 0x97, 0x00, 0x24, 0x55, 0x36, 0x00,
0x37, 0x00, 0x97, 0x97, 0x02, 0xAC, 0x51, 0x3A, 0x00, 0x00, 0x00, 0x97, 0x97, 0x00, 0xAC,
0x21, 0x00, 0x0B, 0x00, 0x00, 0x97, 0x97, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00},
.data_bytes = 44,
.delay_ms = 0},
{.cmd = 0xA7,
.data = (uint8_t[]){0x19, 0x19, 0x00, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x04, 0x03, 0x97,
0x97, 0x00, 0x64, 0x40, 0x25, 0x34, 0x00, 0x00, 0x02, 0x01, 0x97, 0x97,
0x00, 0x64, 0x40, 0x4B, 0x5A, 0x00, 0x00, 0x02, 0x01, 0x97, 0x97, 0x00,
0x24, 0x40, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x97, 0x97, 0x00, 0x44},
.data_bytes = 48,
.delay_ms = 0},
{.cmd = 0xAC,
.data = (uint8_t[]){0x11, 0x08, 0x13, 0x0A, 0x18, 0x1A, 0x1B, 0x00, 0x06, 0x03, 0x19, 0x1B, 0x1B,
0x1B, 0x18, 0x1B, 0x10, 0x09, 0x12, 0x0B, 0x18, 0x1A, 0x1B, 0x02, 0x06, 0x01,
0x19, 0x1B, 0x1B, 0x1B, 0x18, 0x1B, 0xFF, 0x67, 0xFF, 0x67, 0x00},
.data_bytes = 37,
.delay_ms = 0},
{.cmd = 0xAD, .data = (uint8_t[]){0xCC, 0x40, 0x46, 0x11, 0x04, 0x6F, 0x6F}, .data_bytes = 7, .delay_ms = 0},
{.cmd = 0xE8,
.data = (uint8_t[]){0x30, 0x07, 0x00, 0xB3, 0xB3, 0x9C, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEF},
.data_bytes = 14,
.delay_ms = 0},
{.cmd = 0x75, .data = (uint8_t[]){0x03, 0x04}, .data_bytes = 2, .delay_ms = 0},
{.cmd = 0xE7,
.data = (uint8_t[]){0x8B, 0x3C, 0x00, 0x0C, 0xF0, 0x5D, 0x00, 0x5D, 0x00, 0x5D, 0x00,
0x5D, 0x00, 0xFF, 0x00, 0x08, 0x7B, 0x00, 0x00, 0xC8, 0x6A, 0x5A,
0x08, 0x1A, 0x3C, 0x00, 0x71, 0x01, 0x8C, 0x01, 0x7F, 0xF0, 0x22},
.data_bytes = 33,
.delay_ms = 0},
{.cmd = 0xE9,
.data = (uint8_t[]){0x3C, 0x7F, 0x08, 0x07, 0x1A, 0x7A, 0x22, 0x1A, 0x33},
.data_bytes = 9,
.delay_ms = 0},
{.cmd = 0x11, .data = NULL, .data_bytes = 0, .delay_ms = 20},
{.cmd = 0x36, .data = (uint8_t[]){0b11}, .data_bytes = 1, .delay_ms = 0},
{.cmd = 0x29, .data = NULL, .data_bytes = 0, .delay_ms = 20},
{.cmd = 0x35, .data = (uint8_t[]){0x00}, .data_bytes = 1, .delay_ms = 0},
{.cmd = 0x29, .data = NULL, .data_bytes = 0, .delay_ms = 0}
};
class M5IoE1Backlight : public Backlight {
public:
explicit M5IoE1Backlight(M5IOE1* ioe) : ioe_(ioe) {}
void SetBrightnessImpl(uint8_t brightness) override {
if (!ioe_) {
return;
}
ioe_->setPwmDuty(M5IOE1_PWM_CH1, brightness, false, true);
brightness_ = brightness;
}
private:
M5IOE1* ioe_;
};
class M5StackCoreP4Board : public WifiBoard {
private:
Button boot_button_;
LcdDisplay* display_;
i2c_master_bus_handle_t i2c_bus_;
M5IOE1 ioe_;
M5PM1* pmic_;
M5IoE1Backlight* backlight_;
void InitializeI2c() {
i2c_master_bus_config_t i2c_bus_cfg = {
.i2c_port = SYS_I2C_PORT,
.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN,
.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.intr_priority = 0,
.trans_queue_depth = 0,
.flags = {
.enable_internal_pullup = 0,
},
};
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_));
}
void I2cDetect() {
uint8_t address;
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200));
if (ret == ESP_OK) {
printf("%02x ", address);
} else if (ret == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
}
void InitializePm1() {
// Match ~/m5stack_dev/.../m5stack_corep4: PM1 @ M5PM1_DEFAULT_ADDR (0x6E), 100 kHz I2C.
ESP_LOGI(TAG, "M5Stack PMIC Init.");
pmic_ = new M5PM1();
if (pmic_->begin(i2c_bus_, M5PM1_DEFAULT_ADDR, M5PM1_I2C_FREQ_100K) != M5PM1_OK) {
ESP_LOGE(TAG, "M5PM1 begin failed");
return;
}
uint8_t device_id = 0, model = 0, hw_rev = 0, sw_rev = 0;
if (pmic_->getDeviceId(&device_id) == M5PM1_OK && pmic_->getDeviceModel(&model) == M5PM1_OK &&
pmic_->getHwVersion(&hw_rev) == M5PM1_OK && pmic_->getSwVersion(&sw_rev) == M5PM1_OK) {
ESP_LOGI(TAG, "PMIC: ID=0x%02X Model=0x%02X HW=0x%02X SW=0x%02X", device_id, model, hw_rev, sw_rev);
}
}
void InitializeIoExpander() {
// CoreP4 uses the configurable M5IOE1 address 0x4F.
if (ioe_.begin(i2c_bus_, 0x4F, M5IOE1_I2C_FREQ_DEFAULT, M5IOE1_INT_MODE_POLLING) !=
M5IOE1_OK) {
ESP_LOGE(TAG, "M5IOE1 begin failed");
return;
}
// Order matches reference bsp_display_brightness_init + bsp_display_start_with_config (display.cpp).
// 1) Backlight on G9 / PWM1
ioe_.pinMode(IOE1_PIN_LCD_BL, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_LCD_BL, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_LCD_BL, HIGH);
ioe_.setPwmFrequency(1000);
ioe_.setPwmDuty(M5IOE1_PWM_CH1, 0, false, true);
// 2) TP_RST G8
ioe_.pinMode(IOE1_PIN_TOUCH_RST, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_TOUCH_RST, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_TOUCH_RST, HIGH);
// 3) LCD_PWR G10, LCD_RST G11
ioe_.pinMode(IOE1_PIN_LCD_PWR, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_LCD_PWR, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_LCD_PWR, HIGH);
ioe_.pinMode(IOE1_PIN_LCD_RST, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_LCD_RST, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_LCD_RST, HIGH);
vTaskDelay(pdMS_TO_TICKS(20));
// 4) Audio power / PA
ioe_.pinMode(IOE1_PIN_AUDIO_PWR, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_AUDIO_PWR, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_AUDIO_PWR, HIGH);
ioe_.pinMode(IOE1_PIN_PA_EN, OUTPUT);
ioe_.setDriveMode(IOE1_PIN_PA_EN, M5IOE1_DRIVE_PUSHPULL);
ioe_.digitalWrite(IOE1_PIN_PA_EN, HIGH);
}
static esp_err_t bsp_enable_dsi_phy_power() {
static esp_ldo_channel_handle_t phy_pwr_chan = nullptr;
esp_ldo_channel_config_t ldo_cfg = {
.chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN,
.voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
};
esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan);
ESP_LOGI(TAG, "MIPI DSI PHY powered on");
return ESP_OK;
}
void InitializeDisplay() {
esp_lcd_panel_io_handle_t io = nullptr;
esp_lcd_panel_handle_t panel = nullptr;
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = nullptr;
ESP_ERROR_CHECK(bsp_enable_dsi_phy_power());
/* create MIPI DSI bus first, it will initialize the DSI PHY as well */
esp_lcd_dsi_bus_config_t bus_config = {
.bus_id = 0,
.num_data_lanes = DISPLAY_MIPI_LANE_NUM,
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
.lane_bit_rate_mbps = DISPLAY_MIPI_LANE_BITRATE_MBPS,
};
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
ESP_LOGI(TAG, "Install MIPI DSI LCD control panel");
// we use DBI interface to send LCD commands and parameters
esp_lcd_dbi_io_config_t dbi_config = {
.virtual_channel = 0,
.lcd_cmd_bits = 8, // according to the LCD spec
.lcd_param_bits = 8, // according to the LCD spec
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io));
// Wait for MIPI DSI PHY to be ready
vTaskDelay(pdMS_TO_TICKS(50));
ESP_LOGI(TAG, "Install LCD driver of st7102");
esp_lcd_dpi_panel_config_t dpi_config = {
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = DISPLAY_PIXEL_CLOCK_MHZ, // 480x480 60Hz RGB565
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
#else
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, // RGB565 for 16 bits_per_pixel
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
#endif
.num_fbs = 2, // Double buffering for better performance
.video_timing = {
.h_size = DISPLAY_WIDTH,
.v_size = DISPLAY_HEIGHT,
.hsync_pulse_width = DISPLAY_HSYNC_PW,
.hsync_back_porch = DISPLAY_HSYNC_BP,
.hsync_front_porch = DISPLAY_HSYNC_FP,
.vsync_pulse_width = DISPLAY_VSYNC_PW,
.vsync_back_porch = DISPLAY_VSYNC_BP,
.vsync_front_porch = DISPLAY_VSYNC_FP,
},
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
.flags = {.use_dma2d = true},
#endif
};
st7102_vendor_config_t vendor_config = {
.init_cmds = st7102_init_cmds,
.init_cmds_size = sizeof(st7102_init_cmds) / sizeof(st7102_init_cmds[0]),
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
.flags = {
.use_mipi_interface = 1,
},
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7102(io, &panel_config, &panel));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true));
ESP_LOGI(TAG, "Display initialized with resolution %dx%d", DISPLAY_WIDTH, DISPLAY_HEIGHT);
display_ = new MipiLcdDisplay(io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y,
DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
}
void InitializeButtons() {
boot_button_.OnClick([this]() {
auto& app = Application::GetInstance();
if (app.GetDeviceState() == kDeviceStateStarting) {
EnterWifiConfigMode();
return;
}
app.ToggleChatState();
});
}
public:
M5StackCoreP4Board() :
boot_button_(BOOT_BUTTON_GPIO),
display_(nullptr),
i2c_bus_(nullptr),
pmic_(nullptr),
backlight_(nullptr) {
InitializeI2c();
I2cDetect();
InitializePm1();
InitializeIoExpander();
InitializeDisplay();
InitializeButtons();
backlight_ = new M5IoE1Backlight(&ioe_);
backlight_->SetBrightness(90);
}
AudioCodec* GetAudioCodec() override {
static BoxAudioCodec audio_codec(
i2c_bus_,
AUDIO_INPUT_SAMPLE_RATE,
AUDIO_OUTPUT_SAMPLE_RATE,
AUDIO_I2S_GPIO_MCLK,
AUDIO_I2S_GPIO_BCLK,
AUDIO_I2S_GPIO_WS,
AUDIO_I2S_GPIO_DOUT,
AUDIO_I2S_GPIO_DIN,
AUDIO_CODEC_GPIO_PA,
AUDIO_CODEC_ES8311_ADDR,
AUDIO_CODEC_ES7210_ADDR,
AUDIO_INPUT_REFERENCE);
return &audio_codec;
}
Display* GetDisplay() override {
return display_;
}
Backlight* GetBacklight() override {
return backlight_;
}
};
DECLARE_BOARD(M5StackCoreP4Board);
+4
View File
@@ -143,5 +143,9 @@ dependencies:
## Required IDF version
idf:
version: '>=5.5.2'
kevincoooool/esp_lcd_st7102:
version: ^1.0.3
rules:
- if: target in [esp32p4]
m5stack/m5ioe1: ^1.0.8
m5stack/m5pm1: ^1.0.5