diff --git a/.clangd b/.clangd new file mode 100644 index 00000000..437f2554 --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Remove: [-f*, -m*] diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 71e744c0..ec6781e1 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -203,6 +203,10 @@ elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM) set(BOARD_TYPE "bread-compact-wifi-s3cam") elseif(CONFIG_BOARD_TYPE_JIUCHUAN ) set(BOARD_TYPE "jiuchuan-s3") +elseif(CONFIG_BOARD_TYPE_LABPLUS_MPYTHON_V3) + set(BOARD_TYPE "labplus-mpython-v3") +elseif(CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2) + set(BOARD_TYPE "labplus-ledong-v2") elseif(CONFIG_BOARD_TYPE_SURFER_C3_1_14TFT) set(BOARD_TYPE "surfer-c3-1.14tft") endif() diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 32258690..906c3bdd 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -280,6 +280,13 @@ choice BOARD_TYPE select LV_GIF_CACHE_DECODE_DATA config BOARD_TYPE_JIUCHUAN bool "九川智能" + config BOARD_TYPE_LABPLUS_MPYTHON_V3 + bool "labplus mpython_v3 board" + depends on IDF_TARGET_ESP32S3 + config BOARD_TYPE_LABPLUS_LEDONG_V2 + bool "labplus ledong_v2 board" + depends on IDF_TARGET_ESP32S3 + depends on IDF_TARGET_ESP32S3 config BOARD_TYPE_SURFER_C3_1_14TFT bool "Surfer-C3-1-14TFT" depends on IDF_TARGET_ESP32C3 diff --git a/main/boards/labplus-ledong-v2/README.md b/main/boards/labplus-ledong-v2/README.md new file mode 100644 index 00000000..3be2b948 --- /dev/null +++ b/main/boards/labplus-ledong-v2/README.md @@ -0,0 +1,62 @@ +# labplus 乐动掌控V2 + +## 板载资源 + 主控:ESP32-S3 外挂8MB psram 16MB flash + 传感器: + 按钮(A B按键) IO0 IO46 + 光照传感器 IIC + 6轴 IIC + 磁力计 IIC + 声音触发 IO6 + 触摸按键 IIC P Y T H O N + 摄像头 IIC + 执行器: + 蜂鸣器 IO21 + RGB灯 IO16 + 录音播放 es8388 IIC + TFT LCD jd9853 SPI + 电机驱动 IIC + + +## 编译配置 + +### 配置编译目标为 ESP32S3,USB JTAG下载 + +```bash +idf.py set-target esp32s3 +``` + +### menuconfig配置 + +```bash +idf.py menuconfig +``` + +***选择板子:*** + +``` +Xiaozhi Assistant -> Board Type -> labplus Ledong_v2 board +``` + +***修改 psram 配置:*** + +``` +Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> quad Mode PSRAM +``` + +**编译:** + +```bash +idf.py build +``` + +**固件打包:** + +```bash +esptool.py -p /dev/ttyACM0 -b 1500000 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x100000 xiaozhi.bin 0x8000 partition_table/partition-table.bin 0xd000 ota_data_initial.bin 0x10000 srmodels/srmodels.bin +``` + +## 使用 + +### 按键配置 +* A:短按-打断/唤醒 diff --git a/main/boards/labplus-ledong-v2/config.h b/main/boards/labplus-ledong-v2/config.h new file mode 100644 index 00000000..79f9d4f6 --- /dev/null +++ b/main/boards/labplus-ledong-v2/config.h @@ -0,0 +1,44 @@ + +#ifndef _BOARD_CONFIG_H_ +#define _BOARD_CONFIG_H_ + + +#include + +#define AUDIO_INPUT_SAMPLE_RATE 24000 +#define AUDIO_OUTPUT_SAMPLE_RATE 24000 + +#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_39 +#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 +#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 +#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 +#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_38 + +#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_44 +#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_43 +#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR + +#define BOOT_BUTTON_GPIO GPIO_NUM_0 + +#define BUILTIN_LED_GPIO GPIO_NUM_1 + +#define LCD_SCLK_PIN GPIO_NUM_36 +#define LCD_MOSI_PIN GPIO_NUM_37 +#define LCD_MISO_PIN GPIO_NUM_NC +#define LCD_DC_PIN GPIO_NUM_35 +#define LCD_CS_PIN GPIO_NUM_NC + +#define DISPLAY_WIDTH 320 +#define DISPLAY_HEIGHT 172 +#define DISPLAY_MIRROR_X true +#define DISPLAY_MIRROR_Y true +#define DISPLAY_SWAP_XY true + +#define DISPLAY_OFFSET_X 0 +#define DISPLAY_OFFSET_Y 34 + +#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_34 +#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false + +#endif // _BOARD_CONFIG_H_ + diff --git a/main/boards/labplus-ledong-v2/config.json b/main/boards/labplus-ledong-v2/config.json new file mode 100644 index 00000000..8df7030f --- /dev/null +++ b/main/boards/labplus-ledong-v2/config.json @@ -0,0 +1,9 @@ +{ + "target": "esp32s3", + "builds": [ + { + "name": "labplus-ledong-v2", + "sdkconfig_append": [] + } + ] +} \ No newline at end of file diff --git a/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc b/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc new file mode 100644 index 00000000..c5b34422 --- /dev/null +++ b/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc @@ -0,0 +1,183 @@ +#include "wifi_board.h" +#include "es8388_audio_codec.h" +#include "display/lcd_display.h" +#include "application.h" +#include "button.h" +#include "config.h" +#include "i2c_device.h" +#include "iot/thing_manager.h" +#include "led/single_led.h" + +#include +#include +#include +#include +#include + +#define TAG "labplus_ledong_v2" + +#define BOARD_STM8_ADDR 17 +#define BOARD_STM8_CMD 4 + +LV_FONT_DECLARE(font_puhui_20_4); +LV_FONT_DECLARE(font_awesome_20_4); +class labplus_ledong_v2 : public WifiBoard { +private: + i2c_master_bus_handle_t i2c_bus_; + Button boot_button_; + LcdDisplay* display_; + + void InitializeI2c() { + // Initialize I2C peripheral + i2c_master_bus_config_t i2c_bus_cfg = { + .i2c_port = (i2c_port_t)I2C_NUM_0, + .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 = 1, + }, + }; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); + } + + // Initialize spi peripheral + void InitializeSpi() { + spi_bus_config_t buscfg = {}; + buscfg.mosi_io_num = LCD_MOSI_PIN; + buscfg.miso_io_num = GPIO_NUM_NC; + buscfg.sclk_io_num = LCD_SCLK_PIN; + buscfg.quadwp_io_num = GPIO_NUM_NC; + buscfg.quadhd_io_num = GPIO_NUM_NC; + buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); + } + + void InitializeButtons() { + boot_button_.OnClick([this]() { + auto& app = Application::GetInstance(); + if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { + ResetWifiConfiguration(); + } + }); + boot_button_.OnPressDown([this]() { + Application::GetInstance().StartListening(); + }); + boot_button_.OnPressUp([this]() { + Application::GetInstance().StopListening(); + }); + } + + void InitializeJd9853Display() { + esp_lcd_panel_io_handle_t panel_io = nullptr; + esp_lcd_panel_handle_t panel = nullptr; + ESP_LOGD(TAG, "Install panel IO"); + // 液晶屏控制IO初始化 + esp_lcd_panel_io_spi_config_t io_config = {}; + io_config.cs_gpio_num = LCD_CS_PIN; + io_config.dc_gpio_num = LCD_DC_PIN; + io_config.spi_mode = 0; + io_config.pclk_hz = 20 * 1000 * 1000; + io_config.trans_queue_depth = 7; + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); + + // 初始化液晶屏驱动芯片JD9853,使用ST7789驱动,时序和复位有调整。 + ESP_LOGD(TAG, "Install LCD driver"); + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = GPIO_NUM_NC; + panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; + panel_config.bits_per_pixel = 16; + panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, + esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); + + #if CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2 + ESP_LOGI(TAG, "Reset LCD."); + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = BOARD_STM8_ADDR, + .scl_speed_hz = 400000, + }; + + i2c_master_dev_handle_t dev_handle; + i2c_master_bus_add_device(i2c_bus_, &dev_cfg, &dev_handle); + + uint8_t reg = BOARD_STM8_CMD; + i2c_master_transmit(dev_handle, ®, 1, -1); + + i2c_master_bus_rm_device(dev_handle); + #endif + + esp_lcd_panel_reset(panel); + vTaskDelay(pdMS_TO_TICKS(100)); + esp_lcd_panel_init(panel); + esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); + esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); + esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); + display_ = new SpiLcdDisplay(panel_io, panel, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, + { + .text_font = &font_puhui_20_4, + .icon_font = &font_awesome_20_4, + #if CONFIG_USE_WECHAT_MESSAGE_STYLE + .emoji_font = font_emoji_32_init(), + #else + .emoji_font = DISPLAY_HEIGHT >= 240 ? font_emoji_64_init() : font_emoji_32_init(), + #endif + }); + } + + // 物联网初始化,添加对 AI 可见设备 + void InitializeIot() { + auto& thing_manager = iot::ThingManager::GetInstance(); + thing_manager.AddThing(iot::CreateThing("Speaker")); + thing_manager.AddThing(iot::CreateThing("Screen")); + } + +public: + labplus_ledong_v2() : boot_button_(BOOT_BUTTON_GPIO) { + InitializeI2c(); + InitializeSpi(); + InitializeJd9853Display(); + InitializeButtons(); + InitializeIot(); + GetBacklight()->SetBrightness(100); + } + + virtual Led* GetLed() override { + static SingleLed led(BUILTIN_LED_GPIO); + return &led; + } + + virtual AudioCodec* GetAudioCodec() override { + static Es8388AudioCodec audio_codec( + i2c_bus_, + I2C_NUM_0, + 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, + GPIO_NUM_NC, + AUDIO_CODEC_ES8388_ADDR + ); + return &audio_codec; + } + + virtual Display* GetDisplay() override { + return display_; + } + + virtual Backlight* GetBacklight() override { + static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); + return &backlight; + } +}; + +DECLARE_BOARD(labplus_ledong_v2); diff --git a/main/boards/labplus-mpython-v3/README.md b/main/boards/labplus-mpython-v3/README.md new file mode 100644 index 00000000..c5a48456 --- /dev/null +++ b/main/boards/labplus-mpython-v3/README.md @@ -0,0 +1,61 @@ +# labplus 掌控板V3 + +## 板载资源 + 主控:ESP32-S3 外挂8MB psram 16MB flash + 传感器: + 按钮(A B按键) IO0 IO46 + 光照传感器 IIC + 6轴 IIC + 磁力计 IIC + 声音触发 IO6 + 触摸按键 P Y T H O N + 摄像头 IIC + 执行器: + 蜂鸣器 IO21 + RGB灯 IO16 + 录音播放 es8388 IIC + TFT LCD jd9853 SPI + + +## 编译配置 + +### 配置编译目标为 ESP32S3,USB JTAG下载 + +```bash +idf.py set-target esp32s3 +``` + +### menuconfig配置 + +```bash +idf.py menuconfig +``` + +***选择板子:*** + +``` +Xiaozhi Assistant -> Board Type -> labplus mpython_v3 board +``` + +***修改 psram 配置:*** + +``` +Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> quad Mode PSRAM +``` + +**编译:** + +```bash +idf.py build +``` + +**固件打包:** + +```bash +esptool.py -p /dev/ttyACM0 -b 1500000 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x100000 xiaozhi.bin 0x8000 partition_table/partition-table.bin 0xd000 ota_data_initial.bin 0x10000 srmodels/srmodels.bin +``` + +## 使用 + +### 按键配置 +* A:短按-打断/唤醒 diff --git a/main/boards/labplus-mpython-v3/config.h b/main/boards/labplus-mpython-v3/config.h new file mode 100644 index 00000000..e6a84846 --- /dev/null +++ b/main/boards/labplus-mpython-v3/config.h @@ -0,0 +1,44 @@ + +#ifndef _BOARD_CONFIG_H_ +#define _BOARD_CONFIG_H_ + + +#include + +#define AUDIO_INPUT_SAMPLE_RATE 24000 +#define AUDIO_OUTPUT_SAMPLE_RATE 24000 + +#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_39 +#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 +#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 +#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 +#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_38 + +#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_44 +#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_43 +#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR + +#define BOOT_BUTTON_GPIO GPIO_NUM_0 + +#define BUILTIN_LED_GPIO GPIO_NUM_1 + +#define LCD_SCLK_PIN GPIO_NUM_36 +#define LCD_MOSI_PIN GPIO_NUM_37 +#define LCD_MISO_PIN GPIO_NUM_NC +#define LCD_DC_PIN GPIO_NUM_35 +#define LCD_CS_PIN GPIO_NUM_34 + +#define DISPLAY_WIDTH 320 +#define DISPLAY_HEIGHT 172 +#define DISPLAY_MIRROR_X true +#define DISPLAY_MIRROR_Y true +#define DISPLAY_SWAP_XY true + +#define DISPLAY_OFFSET_X 0 +#define DISPLAY_OFFSET_Y 34 + +#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_33 +#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false + +#endif // _BOARD_CONFIG_H_ + diff --git a/main/boards/labplus-mpython-v3/config.json b/main/boards/labplus-mpython-v3/config.json new file mode 100644 index 00000000..b5bd0ee4 --- /dev/null +++ b/main/boards/labplus-mpython-v3/config.json @@ -0,0 +1,9 @@ +{ + "target": "esp32s3", + "builds": [ + { + "name": "labplus-mpython-v3", + "sdkconfig_append": [] + } + ] +} \ No newline at end of file diff --git a/main/boards/labplus-mpython-v3/mpython_pro.cc b/main/boards/labplus-mpython-v3/mpython_pro.cc new file mode 100644 index 00000000..fffcb0ca --- /dev/null +++ b/main/boards/labplus-mpython-v3/mpython_pro.cc @@ -0,0 +1,163 @@ +#include "wifi_board.h" +#include "es8388_audio_codec.h" +#include "display/lcd_display.h" +#include "application.h" +#include "button.h" +#include "config.h" +#include "i2c_device.h" +#include "iot/thing_manager.h" +#include "led/single_led.h" + +#include +#include +#include +#include +#include + +#define TAG "mpython_v3" + +LV_FONT_DECLARE(font_puhui_20_4); +LV_FONT_DECLARE(font_awesome_20_4); +class mpython_v3 : public WifiBoard { +private: + i2c_master_bus_handle_t i2c_bus_; + Button boot_button_; + LcdDisplay* display_; + + void InitializeI2c() { + // Initialize I2C peripheral + i2c_master_bus_config_t i2c_bus_cfg = { + .i2c_port = (i2c_port_t)I2C_NUM_0, + .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 = 1, + }, + }; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); + } + + // Initialize spi peripheral + void InitializeSpi() { + spi_bus_config_t buscfg = {}; + buscfg.mosi_io_num = LCD_MOSI_PIN; + buscfg.miso_io_num = GPIO_NUM_NC; + buscfg.sclk_io_num = LCD_SCLK_PIN; + buscfg.quadwp_io_num = GPIO_NUM_NC; + buscfg.quadhd_io_num = GPIO_NUM_NC; + buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); + } + + void InitializeButtons() { + boot_button_.OnClick([this]() { + auto& app = Application::GetInstance(); + if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) { + ResetWifiConfiguration(); + } + }); + boot_button_.OnPressDown([this]() { + Application::GetInstance().StartListening(); + }); + boot_button_.OnPressUp([this]() { + Application::GetInstance().StopListening(); + }); + } + + void InitializeSt7789Display() { + esp_lcd_panel_io_handle_t panel_io = nullptr; + esp_lcd_panel_handle_t panel = nullptr; + ESP_LOGD(TAG, "Install panel IO"); + // 液晶屏控制IO初始化 + esp_lcd_panel_io_spi_config_t io_config = {}; + io_config.cs_gpio_num = LCD_CS_PIN; + io_config.dc_gpio_num = LCD_DC_PIN; + io_config.spi_mode = 0; + io_config.pclk_hz = 20 * 1000 * 1000; + io_config.trans_queue_depth = 7; + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); + + // 初始化液晶屏驱动芯片JD9853,使用ST7789驱动,时序有调整。 + ESP_LOGD(TAG, "Install LCD driver"); + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = GPIO_NUM_NC; + panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; + panel_config.bits_per_pixel = 16; + panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, + esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); + + esp_lcd_panel_reset(panel); + vTaskDelay(pdMS_TO_TICKS(100)); + esp_lcd_panel_init(panel); + esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); + esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); + esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); + display_ = new SpiLcdDisplay(panel_io, panel, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, + { + .text_font = &font_puhui_20_4, + .icon_font = &font_awesome_20_4, + #if CONFIG_USE_WECHAT_MESSAGE_STYLE + .emoji_font = font_emoji_32_init(), + #else + .emoji_font = DISPLAY_HEIGHT >= 240 ? font_emoji_64_init() : font_emoji_32_init(), + #endif + }); + } + + // 物联网初始化,添加对 AI 可见设备 + void InitializeIot() { + auto& thing_manager = iot::ThingManager::GetInstance(); + thing_manager.AddThing(iot::CreateThing("Speaker")); + thing_manager.AddThing(iot::CreateThing("Screen")); + } + +public: + mpython_v3() : boot_button_(BOOT_BUTTON_GPIO) { + InitializeI2c(); + InitializeSpi(); + InitializeSt7789Display(); + InitializeButtons(); + InitializeIot(); + GetBacklight()->SetBrightness(100); + } + + virtual Led* GetLed() override { + static SingleLed led(BUILTIN_LED_GPIO); + return &led; + } + + virtual AudioCodec* GetAudioCodec() override { + static Es8388AudioCodec audio_codec( + i2c_bus_, + I2C_NUM_0, + 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, + GPIO_NUM_NC, + AUDIO_CODEC_ES8388_ADDR + ); + return &audio_codec; + } + + virtual Display* GetDisplay() override { + return display_; + } + + virtual Backlight* GetBacklight() override { + static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); + return &backlight; + } +}; + +DECLARE_BOARD(mpython_v3);