From 11a3bb3f35460b1a44764677cb00564eb4fdc467 Mon Sep 17 00:00:00 2001 From: whble <512580942@qq.com> Date: Mon, 30 Dec 2024 02:57:34 +0800 Subject: [PATCH 1/3] The repair screen displays ESP_BOX3 --- main/CMakeLists.txt | 1 + main/boards/esp-box-3/config.h | 13 +- main/boards/esp-box-3/esp_box3_board.cc | 82 +++++- main/display/ili9341_display.cc | 374 ++++++++++++++++++++++++ main/display/ili9341_display.h | 51 ++++ main/idf_component.yml | 2 +- 6 files changed, 515 insertions(+), 8 deletions(-) create mode 100644 main/display/ili9341_display.cc create mode 100644 main/display/ili9341_display.h diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 7fbebf69..3d8f10f1 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES "audio_codecs/audio_codec.cc" "display/display.cc" "display/no_display.cc" "display/st7789_display.cc" + "display/ili9341_display.cc" "display/ssd1306_display.cc" "protocols/protocol.cc" "protocols/mqtt_protocol.cc" 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..dcd80c10 100644 --- a/main/boards/esp-box-3/esp_box3_board.cc +++ b/main/boards/esp-box-3/esp_box3_board.cc @@ -1,6 +1,6 @@ #include "wifi_board.h" #include "audio_codecs/box_audio_codec.h" -#include "display/no_display.h" +#include "display/ili9341_display.h" #include "application.h" #include "button.h" #include "led.h" @@ -8,14 +8,37 @@ #include "iot/thing_manager.h" #include +#include #include +#include #define TAG "EspBox3Board" +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}, +}; + class EspBox3Board : public WifiBoard { private: i2c_master_bus_handle_t i2c_bus_; Button boot_button_; + Ili9341Display* display_; void InitializeI2c() { // Initialize I2C peripheral @@ -34,12 +57,64 @@ 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); + } + // 物联网初始化,添加对 AI 可见设备 void InitializeIot() { auto& thing_manager = iot::ThingManager::GetInstance(); @@ -49,6 +124,8 @@ private: public: EspBox3Board() : boot_button_(BOOT_BUTTON_GPIO) { InitializeI2c(); + InitializeSpi(); + InitializeIli9341Display(); InitializeButtons(); InitializeIot(); } @@ -70,8 +147,7 @@ public: } virtual Display* GetDisplay() override { - static NoDisplay display; - return &display; + return display_; } }; diff --git a/main/display/ili9341_display.cc b/main/display/ili9341_display.cc new file mode 100644 index 00000000..9daa2355 --- /dev/null +++ b/main/display/ili9341_display.cc @@ -0,0 +1,374 @@ +#include "ili9341_display.h" +#include "font_awesome_symbols.h" + +#include +#include +#include +#include + +#define TAG "Ili9341Display" +#define LCD_LEDC_CH LEDC_CHANNEL_0 + +#define ILI9341_LVGL_TICK_PERIOD_MS 2 +#define ILI9341_LVGL_TASK_MAX_DELAY_MS 20 +#define ILI9341_LVGL_TASK_MIN_DELAY_MS 1 +#define ILI9341_LVGL_TASK_STACK_SIZE (4 * 1024) +#define ILI9341_LVGL_TASK_PRIORITY 10 + +LV_FONT_DECLARE(font_puhui_14_1); +LV_FONT_DECLARE(font_awesome_30_1); +LV_FONT_DECLARE(font_awesome_14_1); + +static lv_disp_drv_t disp_drv; + +static void ili9341_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) +{ + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; + int offsetx1 = area->x1; + int offsetx2 = area->x2; + int offsety1 = area->y1; + int offsety2 = area->y2; + // copy a buffer's content to a specific area of the display + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); + lv_disp_flush_ready(&disp_drv); +} + +/* Rotate display and touch, when rotated screen in LVGL. Called when driver parameters are updated. */ +static void ili9341_lvgl_port_update_callback(lv_disp_drv_t *drv) +{ + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; + + switch (drv->rotated) + { + case LV_DISP_ROT_NONE: + // Rotate LCD display + esp_lcd_panel_swap_xy(panel_handle, false); + esp_lcd_panel_mirror(panel_handle, true, false); +#if CONFIG_ILI9341_LCD_TOUCH_ENABLED + // Rotate LCD touch + esp_lcd_touch_set_mirror_y(tp, false); + esp_lcd_touch_set_mirror_x(tp, false); +#endif + break; + case LV_DISP_ROT_90: + // Rotate LCD display + esp_lcd_panel_swap_xy(panel_handle, true); + esp_lcd_panel_mirror(panel_handle, true, true); +#if CONFIG_ILI9341_LCD_TOUCH_ENABLED + // Rotate LCD touch + esp_lcd_touch_set_mirror_y(tp, false); + esp_lcd_touch_set_mirror_x(tp, false); +#endif + break; + case LV_DISP_ROT_180: + // Rotate LCD display + esp_lcd_panel_swap_xy(panel_handle, false); + esp_lcd_panel_mirror(panel_handle, false, true); +#if CONFIG_ILI9341_LCD_TOUCH_ENABLED + // Rotate LCD touch + esp_lcd_touch_set_mirror_y(tp, false); + esp_lcd_touch_set_mirror_x(tp, false); +#endif + break; + case LV_DISP_ROT_270: + // Rotate LCD display + esp_lcd_panel_swap_xy(panel_handle, true); + esp_lcd_panel_mirror(panel_handle, false, false); +#if CONFIG_ILI9341_LCD_TOUCH_ENABLED + // Rotate LCD touch + esp_lcd_touch_set_mirror_y(tp, false); + esp_lcd_touch_set_mirror_x(tp, false); +#endif + break; + } +} + +void Ili9341Display::LvglTask() { + ESP_LOGI(TAG, "Starting LVGL task"); + uint32_t task_delay_ms = ILI9341_LVGL_TASK_MAX_DELAY_MS; + while (1) + { + // Lock the mutex due to the LVGL APIs are not thread-safe + if (Lock()) + { + task_delay_ms = lv_timer_handler(); + Unlock(); + } + if (task_delay_ms > ILI9341_LVGL_TASK_MAX_DELAY_MS) + { + task_delay_ms = ILI9341_LVGL_TASK_MAX_DELAY_MS; + } + else if (task_delay_ms < ILI9341_LVGL_TASK_MIN_DELAY_MS) + { + task_delay_ms = ILI9341_LVGL_TASK_MIN_DELAY_MS; + } + vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + } +} + +Ili9341Display::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) + : panel_io_(panel_io), panel_(panel), backlight_pin_(backlight_pin), backlight_output_invert_(backlight_output_invert), + mirror_x_(mirror_x), mirror_y_(mirror_y), swap_xy_(swap_xy){ + width_ = width; + height_ = height; + offset_x_ = offset_x; + offset_y_ = offset_y; + + + InitializeBacklight(backlight_pin); + + // draw white + std::vector buffer(width_, 0xFFFF); + for (int y = 0; y < height_; y++) { + esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data()); + } + + // Set the display to on + ESP_LOGI(TAG, "Turning display on"); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); + + ESP_LOGI(TAG, "Initialize LVGL library"); + lv_init(); + // alloc draw buffers used by LVGL + static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) + // it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized + lv_color_t *buf1 = (lv_color_t *)heap_caps_malloc(width_ * 10 * sizeof(lv_color_t), MALLOC_CAP_DMA); + assert(buf1); + lv_color_t *buf2 = (lv_color_t *)heap_caps_malloc(width_ * 10 * sizeof(lv_color_t), MALLOC_CAP_DMA); + assert(buf2); + // initialize LVGL draw buffers + lv_disp_draw_buf_init(&disp_buf, buf1, buf2, width_ * 10); + + ESP_LOGI(TAG, "Register display driver to LVGL"); + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = width_; + disp_drv.ver_res = height_; + disp_drv.offset_x = offset_x_; + disp_drv.offset_y = offset_y_; + disp_drv.flush_cb = ili9341_lvgl_flush_cb; + disp_drv.drv_update_cb = ili9341_lvgl_port_update_callback; + disp_drv.draw_buf = &disp_buf; + disp_drv.user_data = panel_; + + lv_disp_drv_register(&disp_drv); + + ESP_LOGI(TAG, "Install LVGL tick timer"); + // Tick interface for LVGL (using esp_timer to generate 2ms periodic event) + const esp_timer_create_args_t lvgl_tick_timer_args = { + .callback = [](void* arg) { + lv_tick_inc(ILI9341_LVGL_TICK_PERIOD_MS); + }, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "LVGL Tick Timer", + .skip_unhandled_events = false + }; + ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer_)); + ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer_, ILI9341_LVGL_TICK_PERIOD_MS * 1000)); + + lvgl_mutex_ = xSemaphoreCreateRecursiveMutex(); + assert(lvgl_mutex_ != nullptr); + ESP_LOGI(TAG, "Create LVGL task"); + xTaskCreate([](void *arg) { + static_cast(arg)->LvglTask(); + vTaskDelete(NULL); + }, "LVGL", ILI9341_LVGL_TASK_STACK_SIZE, this, ILI9341_LVGL_TASK_PRIORITY, NULL); + + SetBacklight(100); + + SetupUI(); +} + +Ili9341Display::~Ili9341Display() { + ESP_ERROR_CHECK(esp_timer_stop(lvgl_tick_timer_)); + ESP_ERROR_CHECK(esp_timer_delete(lvgl_tick_timer_)); + + if (network_label_ != nullptr) { + lv_obj_del(ai_messge_label_); + lv_obj_del(user_messge_label_); + } + + if (content_ != nullptr) { + lv_obj_del(content_); + } + if (status_bar_ != nullptr) { + lv_obj_del(status_bar_); + } + if (side_bar_ != nullptr) { + lv_obj_del(side_bar_); + } + if (container_ != nullptr) { + lv_obj_del(container_); + } + + if (panel_ != nullptr) { + esp_lcd_panel_del(panel_); + } + if (panel_io_ != nullptr) { + esp_lcd_panel_io_del(panel_io_); + } + vSemaphoreDelete(lvgl_mutex_); +} + +void Ili9341Display::InitializeBacklight(gpio_num_t backlight_pin) { + if (backlight_pin == GPIO_NUM_NC) { + return; + } + + // Setup LEDC peripheral for PWM backlight control + const ledc_channel_config_t backlight_channel = { + .gpio_num = backlight_pin, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LCD_LEDC_CH, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_0, + .duty = 0, + .hpoint = 0, + .flags = { + .output_invert = backlight_output_invert_, + } + }; + const ledc_timer_config_t backlight_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .duty_resolution = LEDC_TIMER_10_BIT, + .timer_num = LEDC_TIMER_0, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK, + .deconfigure = false + }; + + ESP_ERROR_CHECK(ledc_timer_config(&backlight_timer)); + ESP_ERROR_CHECK(ledc_channel_config(&backlight_channel)); +} + +void Ili9341Display::SetBacklight(uint8_t brightness) { + if (backlight_pin_ == GPIO_NUM_NC) { + return; + } + + if (brightness > 100) { + brightness = 100; + } + + ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness); + // LEDC resolution set to 10bits, thus: 100% = 1023 + uint32_t duty_cycle = (1023 * brightness) / 100; + ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle)); + ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH)); +} + +bool Ili9341Display::Lock(int timeout_ms) { + // Convert timeout in milliseconds to FreeRTOS ticks + // If `timeout_ms` is set to 0, the program will block until the condition is met + const TickType_t timeout_ticks = (timeout_ms == 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + return xSemaphoreTakeRecursive(lvgl_mutex_, timeout_ticks) == pdTRUE; +} + +void Ili9341Display::Unlock() { + xSemaphoreGiveRecursive(lvgl_mutex_); +} + +void Ili9341Display::SetChatMessage(const std::string &role, const std::string &content) { + 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 Ili9341Display::SetupUI() { + DisplayLockGuard lock(this); + + auto screen = lv_disp_get_scr_act(lv_disp_get_default()); + lv_obj_set_style_text_font(screen, &font_puhui_14_1, 0); + lv_obj_set_style_text_color(screen, lv_color_black(), 0); + + /* Container */ + container_ = lv_obj_create(screen); + lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); + lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_all(container_, 0, 0); + lv_obj_set_style_border_width(container_, 0, 0); + lv_obj_set_style_pad_row(container_, 0, 0); + + /* Status bar */ + status_bar_ = lv_obj_create(container_); + lv_obj_set_size(status_bar_, LV_HOR_RES, 18); + lv_obj_set_style_radius(status_bar_, 0, 0); + + /* Content */ + content_ = lv_obj_create(container_); + lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_radius(content_, 0, 0); + lv_obj_set_width(content_, LV_HOR_RES); + lv_obj_set_flex_grow(content_, 1); + + emotion_label_ = lv_label_create(content_); + 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_center(emotion_label_); + 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); + + /* Status bar */ + lv_obj_set_flex_flow(status_bar_, LV_FLEX_FLOW_ROW); + lv_obj_set_style_pad_all(status_bar_, 0, 0); + lv_obj_set_style_border_width(status_bar_, 0, 0); + lv_obj_set_style_pad_column(status_bar_, 0, 0); + + network_label_ = lv_label_create(status_bar_); + lv_label_set_text(network_label_, ""); + lv_obj_set_style_text_font(network_label_, &font_awesome_14_1, 0); + + notification_label_ = lv_label_create(status_bar_); + lv_obj_set_flex_grow(notification_label_, 1); + lv_obj_set_style_text_align(notification_label_, LV_TEXT_ALIGN_CENTER, 0); + lv_label_set_text(notification_label_, "通知"); + lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); + + status_label_ = lv_label_create(status_bar_); + lv_obj_set_flex_grow(status_label_, 1); + lv_label_set_text(status_label_, "正在初始化"); + lv_obj_set_style_text_align(status_label_, LV_TEXT_ALIGN_CENTER, 0); + + mute_label_ = lv_label_create(status_bar_); + lv_label_set_text(mute_label_, ""); + lv_obj_set_style_text_font(mute_label_, &font_awesome_14_1, 0); + + battery_label_ = lv_label_create(status_bar_); + lv_label_set_text(battery_label_, ""); + lv_obj_set_style_text_font(battery_label_, &font_awesome_14_1, 0); +} \ No newline at end of file diff --git a/main/display/ili9341_display.h b/main/display/ili9341_display.h new file mode 100644 index 00000000..9beb08b8 --- /dev/null +++ b/main/display/ili9341_display.h @@ -0,0 +1,51 @@ +#ifndef ILI9341_DISPLAY_H +#define ILI9341_DISPLAY_H + +#include "display.h" +#include "esp_lcd_ili9341.h" +#include +#include +#include +#include +#include +#include + +class Ili9341Display : public Display { +private: + esp_lcd_panel_io_handle_t panel_io_ = nullptr; + esp_lcd_panel_handle_t panel_ = nullptr; + gpio_num_t backlight_pin_ = GPIO_NUM_NC; + bool backlight_output_invert_ = false; + bool mirror_x_ = false; + bool mirror_y_ = false; + bool swap_xy_ = false; + int offset_x_ = 0; + int offset_y_ = 0; + SemaphoreHandle_t lvgl_mutex_ = nullptr; + esp_timer_handle_t lvgl_tick_timer_ = nullptr; + + lv_obj_t* status_bar_ = nullptr; + lv_obj_t* content_ = nullptr; + lv_obj_t* container_ = nullptr; + lv_obj_t* side_bar_ = nullptr; + + lv_obj_t *user_messge_label_ = nullptr; + lv_obj_t *ai_messge_label_ = nullptr; + + void InitializeBacklight(gpio_num_t backlight_pin); + void SetBacklight(uint8_t brightness); + void SetupUI(); + void LvglTask(); + + virtual bool Lock(int timeout_ms = 0) override; + virtual void Unlock() override; + virtual void SetChatMessage(const std::string &role, const std::string &content) override; + +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); + ~Ili9341Display(); +}; + +#endif // Ili9341_DISPLAY_H 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" From f98be270002fa545e18250118ce9174d4427673f Mon Sep 17 00:00:00 2001 From: whble <512580942@qq.com> Date: Wed, 1 Jan 2025 22:43:20 +0800 Subject: [PATCH 2/3] fix display for esp32 box3 --- main/CMakeLists.txt | 1 - main/boards/esp-box-3/esp_box3_board.cc | 94 +++++- main/display/ili9341_display.cc | 374 ------------------------ main/display/ili9341_display.h | 51 ---- main/display/st7789_display.h | 4 +- 5 files changed, 95 insertions(+), 429 deletions(-) delete mode 100644 main/display/ili9341_display.cc delete mode 100644 main/display/ili9341_display.h diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 3d8f10f1..7fbebf69 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -6,7 +6,6 @@ set(SOURCES "audio_codecs/audio_codec.cc" "display/display.cc" "display/no_display.cc" "display/st7789_display.cc" - "display/ili9341_display.cc" "display/ssd1306_display.cc" "protocols/protocol.cc" "protocols/mqtt_protocol.cc" diff --git a/main/boards/esp-box-3/esp_box3_board.cc b/main/boards/esp-box-3/esp_box3_board.cc index dcd80c10..f1fa0fb4 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/ili9341_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" @@ -14,6 +16,12 @@ #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}, @@ -34,6 +42,82 @@ static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { {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_; @@ -113,6 +197,7 @@ private: 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 可见设备 @@ -149,6 +234,13 @@ public: virtual Display* GetDisplay() override { return display_; } + + virtual bool GetBatteryLevel(int &level, bool& charging) override + { + charging = false; + level =60; + return true; + }; }; DECLARE_BOARD(EspBox3Board); diff --git a/main/display/ili9341_display.cc b/main/display/ili9341_display.cc deleted file mode 100644 index 9daa2355..00000000 --- a/main/display/ili9341_display.cc +++ /dev/null @@ -1,374 +0,0 @@ -#include "ili9341_display.h" -#include "font_awesome_symbols.h" - -#include -#include -#include -#include - -#define TAG "Ili9341Display" -#define LCD_LEDC_CH LEDC_CHANNEL_0 - -#define ILI9341_LVGL_TICK_PERIOD_MS 2 -#define ILI9341_LVGL_TASK_MAX_DELAY_MS 20 -#define ILI9341_LVGL_TASK_MIN_DELAY_MS 1 -#define ILI9341_LVGL_TASK_STACK_SIZE (4 * 1024) -#define ILI9341_LVGL_TASK_PRIORITY 10 - -LV_FONT_DECLARE(font_puhui_14_1); -LV_FONT_DECLARE(font_awesome_30_1); -LV_FONT_DECLARE(font_awesome_14_1); - -static lv_disp_drv_t disp_drv; - -static void ili9341_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) -{ - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; - int offsetx1 = area->x1; - int offsetx2 = area->x2; - int offsety1 = area->y1; - int offsety2 = area->y2; - // copy a buffer's content to a specific area of the display - esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); - lv_disp_flush_ready(&disp_drv); -} - -/* Rotate display and touch, when rotated screen in LVGL. Called when driver parameters are updated. */ -static void ili9341_lvgl_port_update_callback(lv_disp_drv_t *drv) -{ - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; - - switch (drv->rotated) - { - case LV_DISP_ROT_NONE: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, false); - esp_lcd_panel_mirror(panel_handle, true, false); -#if CONFIG_ILI9341_LCD_TOUCH_ENABLED - // Rotate LCD touch - esp_lcd_touch_set_mirror_y(tp, false); - esp_lcd_touch_set_mirror_x(tp, false); -#endif - break; - case LV_DISP_ROT_90: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, true); - esp_lcd_panel_mirror(panel_handle, true, true); -#if CONFIG_ILI9341_LCD_TOUCH_ENABLED - // Rotate LCD touch - esp_lcd_touch_set_mirror_y(tp, false); - esp_lcd_touch_set_mirror_x(tp, false); -#endif - break; - case LV_DISP_ROT_180: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, false); - esp_lcd_panel_mirror(panel_handle, false, true); -#if CONFIG_ILI9341_LCD_TOUCH_ENABLED - // Rotate LCD touch - esp_lcd_touch_set_mirror_y(tp, false); - esp_lcd_touch_set_mirror_x(tp, false); -#endif - break; - case LV_DISP_ROT_270: - // Rotate LCD display - esp_lcd_panel_swap_xy(panel_handle, true); - esp_lcd_panel_mirror(panel_handle, false, false); -#if CONFIG_ILI9341_LCD_TOUCH_ENABLED - // Rotate LCD touch - esp_lcd_touch_set_mirror_y(tp, false); - esp_lcd_touch_set_mirror_x(tp, false); -#endif - break; - } -} - -void Ili9341Display::LvglTask() { - ESP_LOGI(TAG, "Starting LVGL task"); - uint32_t task_delay_ms = ILI9341_LVGL_TASK_MAX_DELAY_MS; - while (1) - { - // Lock the mutex due to the LVGL APIs are not thread-safe - if (Lock()) - { - task_delay_ms = lv_timer_handler(); - Unlock(); - } - if (task_delay_ms > ILI9341_LVGL_TASK_MAX_DELAY_MS) - { - task_delay_ms = ILI9341_LVGL_TASK_MAX_DELAY_MS; - } - else if (task_delay_ms < ILI9341_LVGL_TASK_MIN_DELAY_MS) - { - task_delay_ms = ILI9341_LVGL_TASK_MIN_DELAY_MS; - } - vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); - } -} - -Ili9341Display::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) - : panel_io_(panel_io), panel_(panel), backlight_pin_(backlight_pin), backlight_output_invert_(backlight_output_invert), - mirror_x_(mirror_x), mirror_y_(mirror_y), swap_xy_(swap_xy){ - width_ = width; - height_ = height; - offset_x_ = offset_x; - offset_y_ = offset_y; - - - InitializeBacklight(backlight_pin); - - // draw white - std::vector buffer(width_, 0xFFFF); - for (int y = 0; y < height_; y++) { - esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data()); - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - // alloc draw buffers used by LVGL - static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s) - // it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized - lv_color_t *buf1 = (lv_color_t *)heap_caps_malloc(width_ * 10 * sizeof(lv_color_t), MALLOC_CAP_DMA); - assert(buf1); - lv_color_t *buf2 = (lv_color_t *)heap_caps_malloc(width_ * 10 * sizeof(lv_color_t), MALLOC_CAP_DMA); - assert(buf2); - // initialize LVGL draw buffers - lv_disp_draw_buf_init(&disp_buf, buf1, buf2, width_ * 10); - - ESP_LOGI(TAG, "Register display driver to LVGL"); - lv_disp_drv_init(&disp_drv); - disp_drv.hor_res = width_; - disp_drv.ver_res = height_; - disp_drv.offset_x = offset_x_; - disp_drv.offset_y = offset_y_; - disp_drv.flush_cb = ili9341_lvgl_flush_cb; - disp_drv.drv_update_cb = ili9341_lvgl_port_update_callback; - disp_drv.draw_buf = &disp_buf; - disp_drv.user_data = panel_; - - lv_disp_drv_register(&disp_drv); - - ESP_LOGI(TAG, "Install LVGL tick timer"); - // Tick interface for LVGL (using esp_timer to generate 2ms periodic event) - const esp_timer_create_args_t lvgl_tick_timer_args = { - .callback = [](void* arg) { - lv_tick_inc(ILI9341_LVGL_TICK_PERIOD_MS); - }, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "LVGL Tick Timer", - .skip_unhandled_events = false - }; - ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer_, ILI9341_LVGL_TICK_PERIOD_MS * 1000)); - - lvgl_mutex_ = xSemaphoreCreateRecursiveMutex(); - assert(lvgl_mutex_ != nullptr); - ESP_LOGI(TAG, "Create LVGL task"); - xTaskCreate([](void *arg) { - static_cast(arg)->LvglTask(); - vTaskDelete(NULL); - }, "LVGL", ILI9341_LVGL_TASK_STACK_SIZE, this, ILI9341_LVGL_TASK_PRIORITY, NULL); - - SetBacklight(100); - - SetupUI(); -} - -Ili9341Display::~Ili9341Display() { - ESP_ERROR_CHECK(esp_timer_stop(lvgl_tick_timer_)); - ESP_ERROR_CHECK(esp_timer_delete(lvgl_tick_timer_)); - - if (network_label_ != nullptr) { - lv_obj_del(ai_messge_label_); - lv_obj_del(user_messge_label_); - } - - if (content_ != nullptr) { - lv_obj_del(content_); - } - if (status_bar_ != nullptr) { - lv_obj_del(status_bar_); - } - if (side_bar_ != nullptr) { - lv_obj_del(side_bar_); - } - if (container_ != nullptr) { - lv_obj_del(container_); - } - - if (panel_ != nullptr) { - esp_lcd_panel_del(panel_); - } - if (panel_io_ != nullptr) { - esp_lcd_panel_io_del(panel_io_); - } - vSemaphoreDelete(lvgl_mutex_); -} - -void Ili9341Display::InitializeBacklight(gpio_num_t backlight_pin) { - if (backlight_pin == GPIO_NUM_NC) { - return; - } - - // Setup LEDC peripheral for PWM backlight control - const ledc_channel_config_t backlight_channel = { - .gpio_num = backlight_pin, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = LCD_LEDC_CH, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_0, - .duty = 0, - .hpoint = 0, - .flags = { - .output_invert = backlight_output_invert_, - } - }; - const ledc_timer_config_t backlight_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_10_BIT, - .timer_num = LEDC_TIMER_0, - .freq_hz = 5000, - .clk_cfg = LEDC_AUTO_CLK, - .deconfigure = false - }; - - ESP_ERROR_CHECK(ledc_timer_config(&backlight_timer)); - ESP_ERROR_CHECK(ledc_channel_config(&backlight_channel)); -} - -void Ili9341Display::SetBacklight(uint8_t brightness) { - if (backlight_pin_ == GPIO_NUM_NC) { - return; - } - - if (brightness > 100) { - brightness = 100; - } - - ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness); - // LEDC resolution set to 10bits, thus: 100% = 1023 - uint32_t duty_cycle = (1023 * brightness) / 100; - ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle)); - ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH)); -} - -bool Ili9341Display::Lock(int timeout_ms) { - // Convert timeout in milliseconds to FreeRTOS ticks - // If `timeout_ms` is set to 0, the program will block until the condition is met - const TickType_t timeout_ticks = (timeout_ms == 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); - return xSemaphoreTakeRecursive(lvgl_mutex_, timeout_ticks) == pdTRUE; -} - -void Ili9341Display::Unlock() { - xSemaphoreGiveRecursive(lvgl_mutex_); -} - -void Ili9341Display::SetChatMessage(const std::string &role, const std::string &content) { - 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 Ili9341Display::SetupUI() { - DisplayLockGuard lock(this); - - auto screen = lv_disp_get_scr_act(lv_disp_get_default()); - lv_obj_set_style_text_font(screen, &font_puhui_14_1, 0); - lv_obj_set_style_text_color(screen, lv_color_black(), 0); - - /* Container */ - container_ = lv_obj_create(screen); - lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); - lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(container_, 0, 0); - lv_obj_set_style_border_width(container_, 0, 0); - lv_obj_set_style_pad_row(container_, 0, 0); - - /* Status bar */ - status_bar_ = lv_obj_create(container_); - lv_obj_set_size(status_bar_, LV_HOR_RES, 18); - lv_obj_set_style_radius(status_bar_, 0, 0); - - /* Content */ - content_ = lv_obj_create(container_); - lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_radius(content_, 0, 0); - lv_obj_set_width(content_, LV_HOR_RES); - lv_obj_set_flex_grow(content_, 1); - - emotion_label_ = lv_label_create(content_); - 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_center(emotion_label_); - 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); - - /* Status bar */ - lv_obj_set_flex_flow(status_bar_, LV_FLEX_FLOW_ROW); - lv_obj_set_style_pad_all(status_bar_, 0, 0); - lv_obj_set_style_border_width(status_bar_, 0, 0); - lv_obj_set_style_pad_column(status_bar_, 0, 0); - - network_label_ = lv_label_create(status_bar_); - lv_label_set_text(network_label_, ""); - lv_obj_set_style_text_font(network_label_, &font_awesome_14_1, 0); - - notification_label_ = lv_label_create(status_bar_); - lv_obj_set_flex_grow(notification_label_, 1); - lv_obj_set_style_text_align(notification_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_label_set_text(notification_label_, "通知"); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - status_label_ = lv_label_create(status_bar_); - lv_obj_set_flex_grow(status_label_, 1); - lv_label_set_text(status_label_, "正在初始化"); - lv_obj_set_style_text_align(status_label_, LV_TEXT_ALIGN_CENTER, 0); - - mute_label_ = lv_label_create(status_bar_); - lv_label_set_text(mute_label_, ""); - lv_obj_set_style_text_font(mute_label_, &font_awesome_14_1, 0); - - battery_label_ = lv_label_create(status_bar_); - lv_label_set_text(battery_label_, ""); - lv_obj_set_style_text_font(battery_label_, &font_awesome_14_1, 0); -} \ No newline at end of file diff --git a/main/display/ili9341_display.h b/main/display/ili9341_display.h deleted file mode 100644 index 9beb08b8..00000000 --- a/main/display/ili9341_display.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef ILI9341_DISPLAY_H -#define ILI9341_DISPLAY_H - -#include "display.h" -#include "esp_lcd_ili9341.h" -#include -#include -#include -#include -#include -#include - -class Ili9341Display : public Display { -private: - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - gpio_num_t backlight_pin_ = GPIO_NUM_NC; - bool backlight_output_invert_ = false; - bool mirror_x_ = false; - bool mirror_y_ = false; - bool swap_xy_ = false; - int offset_x_ = 0; - int offset_y_ = 0; - SemaphoreHandle_t lvgl_mutex_ = nullptr; - esp_timer_handle_t lvgl_tick_timer_ = nullptr; - - lv_obj_t* status_bar_ = nullptr; - lv_obj_t* content_ = nullptr; - lv_obj_t* container_ = nullptr; - lv_obj_t* side_bar_ = nullptr; - - lv_obj_t *user_messge_label_ = nullptr; - lv_obj_t *ai_messge_label_ = nullptr; - - void InitializeBacklight(gpio_num_t backlight_pin); - void SetBacklight(uint8_t brightness); - void SetupUI(); - void LvglTask(); - - virtual bool Lock(int timeout_ms = 0) override; - virtual void Unlock() override; - virtual void SetChatMessage(const std::string &role, const std::string &content) override; - -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); - ~Ili9341Display(); -}; - -#endif // Ili9341_DISPLAY_H 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; From ded4f40e3423aeff6eee69dcd80d2f8f45256e43 Mon Sep 17 00:00:00 2001 From: Xiaoxia Date: Fri, 3 Jan 2025 00:50:58 +0800 Subject: [PATCH 3/3] Update esp_box3_board.cc fix spacing --- main/boards/esp-box-3/esp_box3_board.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/boards/esp-box-3/esp_box3_board.cc b/main/boards/esp-box-3/esp_box3_board.cc index f1fa0fb4..7df36c19 100644 --- a/main/boards/esp-box-3/esp_box3_board.cc +++ b/main/boards/esp-box-3/esp_box3_board.cc @@ -238,7 +238,7 @@ public: virtual bool GetBatteryLevel(int &level, bool& charging) override { charging = false; - level =60; + level = 60; return true; }; };