diff --git a/main/boards/esp-box-3/config.h b/main/boards/esp-box-3/config.h index a1255732..14bddbd3 100644 --- a/main/boards/esp-box-3/config.h +++ b/main/boards/esp-box-3/config.h @@ -26,12 +26,17 @@ #define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC #define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 +#define DISPLAY_WIDTH 320 +#define DISPLAY_HEIGHT 240 #define DISPLAY_MIRROR_X true #define DISPLAY_MIRROR_Y true +#define DISPLAY_SWAP_XY false + +#define DISPLAY_OFFSET_X 0 +#define DISPLAY_OFFSET_Y 0 + +#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_47 +#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false #endif // _BOARD_CONFIG_H_ diff --git a/main/boards/esp-box-3/esp_box3_board.cc b/main/boards/esp-box-3/esp_box3_board.cc index c74106f0..7df36c19 100644 --- a/main/boards/esp-box-3/esp_box3_board.cc +++ b/main/boards/esp-box-3/esp_box3_board.cc @@ -1,6 +1,8 @@ #include "wifi_board.h" #include "audio_codecs/box_audio_codec.h" -#include "display/no_display.h" +#include "display/st7789_display.h" +#include "esp_lcd_ili9341.h" +#include "font_awesome_symbols.h" #include "application.h" #include "button.h" #include "led.h" @@ -8,14 +10,119 @@ #include "iot/thing_manager.h" #include +#include #include +#include #define TAG "EspBox3Board" +// Can move to display/st7789_display.h +LV_FONT_DECLARE(font_puhui_14_1); +LV_FONT_DECLARE(font_awesome_30_1); +LV_FONT_DECLARE(font_awesome_14_1); + +// Init ili9341 by custom cmd +static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { + {0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0}, + {0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0}, + {0xC5, (uint8_t []){0xD0}, 1, 0}, + {0xC1, (uint8_t []){0x02}, 1, 0}, + {0xB4, (uint8_t []){0x02}, 1, 0}, + {0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0}, + {0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0}, + + {0xB1, (uint8_t []){00, 0x1B}, 2, 0}, + {0x36, (uint8_t []){0x08}, 1, 0}, + {0x3A, (uint8_t []){0x55}, 1, 0}, + {0xB7, (uint8_t []){0x06}, 1, 0}, + + {0x11, (uint8_t []){0}, 0x80, 0}, + {0x29, (uint8_t []){0}, 0x80, 0}, + + {0, (uint8_t []){0}, 0xff, 0}, +}; + +// Example Display and UI overwrite in different board +class Ili9341Display : public St7789Display { +private: + lv_obj_t *user_messge_label_ = nullptr; + lv_obj_t *ai_messge_label_ = nullptr; +public: + Ili9341Display(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, + gpio_num_t backlight_pin, bool backlight_output_invert, + int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) + : St7789Display(panel_io, panel, backlight_pin, backlight_output_invert, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) {} + + void SetStatus(const std::string &status) override + { + if (status_label_ == nullptr) { + return; + } + if(status=="待命") + { + SetChatMessage(" "," "); + } + DisplayLockGuard lock(this); + lv_label_set_text(status_label_, status.c_str()); + } + + void SetChatMessage(const std::string &role, const std::string &content) override { + if (ai_messge_label_== nullptr || user_messge_label_== nullptr) { + return; + } + DisplayLockGuard lock(this); + ESP_LOGI(TAG,"role:%s",role.c_str()); + if(role=="assistant") + { + std::string new_content = "AI:" + content; + lv_label_set_text(ai_messge_label_, new_content.c_str()); + } + else if(role=="user") + { + std::string new_content = "User:" + content; + lv_label_set_text(user_messge_label_, new_content.c_str()); + } + else{ + std::string new_content = "AI:"; + lv_label_set_text(ai_messge_label_, new_content.c_str()); + new_content="User:"; + lv_label_set_text(user_messge_label_, new_content.c_str()); + } + } + void SetupUI() override { + DisplayLockGuard lock(this); + + lv_obj_del(chat_message_label_); + + lv_obj_set_flex_align(content_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY); // 子对象居中对齐,等距分布 + + lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_1, 0); + lv_label_set_text(emotion_label_, FONT_AWESOME_AI_CHIP); + lv_obj_align(emotion_label_,LV_ALIGN_TOP_MID, 0, -10); // 左侧居中,向右偏移10个单位 + + static lv_style_t style_msg; + lv_style_init(&style_msg); + lv_style_set_width(&style_msg, LV_HOR_RES-25); + + user_messge_label_ = lv_label_create(content_); + lv_obj_set_style_text_font(user_messge_label_, &font_puhui_14_1, 0); + lv_label_set_text(user_messge_label_, "User:"); + lv_obj_add_style(user_messge_label_, &style_msg, 0); + lv_obj_align(user_messge_label_,LV_ALIGN_TOP_LEFT, 2, 25); + + ai_messge_label_ = lv_label_create(content_); + lv_obj_set_style_text_font(ai_messge_label_, &font_puhui_14_1, 0); + lv_label_set_text(ai_messge_label_, "AI:"); + lv_obj_add_style(ai_messge_label_, &style_msg, 0); + lv_obj_align(ai_messge_label_,LV_ALIGN_TOP_LEFT, 2, 77); + } +}; + class EspBox3Board : public WifiBoard { private: i2c_master_bus_handle_t i2c_bus_; Button boot_button_; + Ili9341Display* display_; void InitializeI2c() { // Initialize I2C peripheral @@ -34,12 +141,65 @@ private: ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); } + void InitializeSpi() { + spi_bus_config_t buscfg = {}; + buscfg.mosi_io_num = GPIO_NUM_6; + buscfg.miso_io_num = GPIO_NUM_NC; + buscfg.sclk_io_num = GPIO_NUM_7; + 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(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); + } + void InitializeButtons() { boot_button_.OnClick([this]() { Application::GetInstance().ToggleChatState(); }); } + void InitializeIli9341Display() { + esp_lcd_panel_io_handle_t panel_io = nullptr; + esp_lcd_panel_handle_t panel = nullptr; + + // 液晶屏控制IO初始化 + ESP_LOGD(TAG, "Install panel IO"); + esp_lcd_panel_io_spi_config_t io_config = {}; + io_config.cs_gpio_num = GPIO_NUM_5; + io_config.dc_gpio_num = GPIO_NUM_4; + io_config.spi_mode = 0; + io_config.pclk_hz = 40 * 1000 * 1000; + io_config.trans_queue_depth = 10; + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); + + // 初始化液晶屏驱动芯片 + ESP_LOGD(TAG, "Install LCD driver"); + const ili9341_vendor_config_t vendor_config = { + .init_cmds = &vendor_specific_init[0], + .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), + }; + + esp_lcd_panel_dev_config_t panel_config = {}; + panel_config.reset_gpio_num = GPIO_NUM_48; + panel_config.flags.reset_active_high = 1, + panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; + panel_config.bits_per_pixel = 16; + panel_config.vendor_config = (void *)&vendor_config; + ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); + + esp_lcd_panel_reset(panel); + esp_lcd_panel_init(panel); + esp_lcd_panel_invert_color(panel, true); + esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); + esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); + esp_lcd_panel_disp_on_off(panel, true); + display_ = new Ili9341Display(panel_io, panel, DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT, + DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); + display_->SetupUI(); + } + // 物联网初始化,添加对 AI 可见设备 void InitializeIot() { auto& thing_manager = iot::ThingManager::GetInstance(); @@ -49,6 +209,8 @@ private: public: EspBox3Board() : boot_button_(BOOT_BUTTON_GPIO) { InitializeI2c(); + InitializeSpi(); + InitializeIli9341Display(); InitializeButtons(); InitializeIot(); } @@ -70,9 +232,15 @@ public: } virtual Display* GetDisplay() override { - static NoDisplay display; - return &display; + return display_; } + + virtual bool GetBatteryLevel(int &level, bool& charging) override + { + charging = false; + level = 60; + return true; + }; }; DECLARE_BOARD(EspBox3Board); diff --git a/main/display/st7789_display.h b/main/display/st7789_display.h index 724bc2c0..e053e344 100644 --- a/main/display/st7789_display.h +++ b/main/display/st7789_display.h @@ -11,7 +11,7 @@ #include class St7789Display : public Display { -private: +protected: esp_lcd_panel_io_handle_t panel_io_ = nullptr; esp_lcd_panel_handle_t panel_ = nullptr; gpio_num_t backlight_pin_ = GPIO_NUM_NC; @@ -32,9 +32,9 @@ private: void InitializeBacklight(gpio_num_t backlight_pin); void SetBacklight(uint8_t brightness); - void SetupUI(); void LvglTask(); + virtual void SetupUI(); virtual bool Lock(int timeout_ms = 0) override; virtual void Unlock() override; diff --git a/main/idf_component.yml b/main/idf_component.yml index 6cbd79a0..45049fdd 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,6 +1,6 @@ ## IDF Component Manager Manifest File dependencies: - espressif/esp_lcd_ili9341: "==1.0.0" + espressif/esp_lcd_ili9341: "==1.2.0" 78/esp-wifi-connect: "~1.4.1" 78/esp-opus-encoder: "~2.0.0" 78/esp-ml307: "~1.7.0"