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
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:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.x(P4X)使用 ESP-IDF 6.0 或更高版本:
|
||||
|
||||
```bash
|
||||
python3 scripts/build.py m5stack/corep4 --name m5stack-corep4x --zip
|
||||
```
|
||||
|
||||
构建脚本会生成合并固件和 release ZIP。烧录前请确认设备使用的 ESP32-P4 芯片版本与构建变体一致。
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user