diff --git a/esp/cpp/07_lcd-panel/main/display.cpp b/esp/cpp/07_lcd-panel/main/display.cpp index 4c0fea8..7c68426 100644 --- a/esp/cpp/07_lcd-panel/main/display.cpp +++ b/esp/cpp/07_lcd-panel/main/display.cpp @@ -2,21 +2,17 @@ #include "display.h" #include "ssd1306.h" -#include "widgets/label/lv_label.h" -#include -#include -#include -#include #include + #include -#include + #include // LVGL library is not thread-safe, this example calls LVGL APIs from tasks. // We must use a mutex to protect it. -_lock_t Display::ScopedLock::lock_; +_lock_t Display::ScopedLock::lv_lock_; -Display::Display(IPanelDevice *device) : +Display::Display(IPanelDevice &device) : panel_(device) { if (!lv_is_initialized()) { @@ -24,7 +20,7 @@ Display::Display(IPanelDevice *device) : lv_init(); } - // Create a lvgl display. + ESP_LOGI(TAG, "Creating LVGL display"); lv_display_ = panel_.device_->create_display(); // associate the i2c panel handle to the display lv_display_set_user_data(lv_display_, panel_.esp_panel_); @@ -35,27 +31,26 @@ Display::Display(IPanelDevice *device) : MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); assert(lv_buf_); - // LVGL9 suooprt new monochromatic format. + ESP_LOGI(TAG, "Set LVGL draw buffers"); + // Color format must be set first, LVGL9 suooprt new monochromatic format. lv_display_set_color_format(lv_display_, LV_COLOR_FORMAT_I1); - // Initialize LVGL draw buffers. lv_display_set_buffers(lv_display_, lv_buf_, nullptr, panel_.device_->lv_buf_size_, LV_DISPLAY_RENDER_MODE_FULL); lv_display_set_rotation(lv_display_, LV_DISPLAY_ROTATION_0); - // Set callback which can copy the rendered image to an area of the display. + + ESP_LOGI(TAG, "Set LVGL callback for flushing to the display"); lv_display_set_flush_cb(lv_display_, Display::lvgl_flush_cb); ESP_LOGI(TAG, "Register io panel callback for LVGL flush ready notification"); const esp_lcd_panel_io_callbacks_t cbs = { .on_color_trans_done = Display::lvgl_flush_ready, }; - /* Register done callback */ ESP_ERROR_CHECK( - esp_lcd_panel_io_register_event_callbacks(panel_.io_handle_, &cbs, + esp_lcd_panel_io_register_event_callbacks(panel_.esp_io_handle_, &cbs, lv_display_)); - // TODO: What is this - ESP_LOGI(TAG, "Use esp_timer as LVGL tick timer"); + ESP_LOGI(TAG, "Use esp_timer to increase LVGL tick"); const esp_timer_create_args_t lvgl_tick_timer_args = { .callback = &Display::lvgl_increase_tick, .name = "lvgl_tick" @@ -80,10 +75,10 @@ void Display::set_text(const char *text, ESP_LOGI(TAG, "Display LVGL Scroll Text"); lv_obj_t *scr = lv_display_get_screen_active(lv_display_); - objects_[name] = lv_label_create(scr); + lv_objects_[name] = lv_label_create(scr); // Circular scroll. - auto obj = objects_[name]; + auto obj = lv_objects_[name]; lv_label_set_long_mode(obj, long_mode); lv_label_set_text(obj, text); @@ -157,9 +152,9 @@ void Display::lvgl_increase_tick(void *) { ESP_LOGI(TAG, "Starting LVGL task"); for (uint32_t time_till_next_ms = 0; true;) { - _lock_acquire(&ScopedLock::lock_); + _lock_acquire(&ScopedLock::lv_lock_); time_till_next_ms = lv_timer_handler(); - _lock_release(&ScopedLock::lock_); + _lock_release(&ScopedLock::lv_lock_); usleep(1000 * time_till_next_ms); } } diff --git a/esp/cpp/07_lcd-panel/main/display.h b/esp/cpp/07_lcd-panel/main/display.h index f31fdcb..43e65c0 100644 --- a/esp/cpp/07_lcd-panel/main/display.h +++ b/esp/cpp/07_lcd-panel/main/display.h @@ -1,17 +1,9 @@ #ifndef DISPLAY_H #define DISPLAY_H -#include -#include -#include -#include +#include + #include -#include -#include -#include "misc/lv_types.h" -#include "misc/lv_area.h" -#include "display/lv_display.h" -#include "widgets/label/lv_label.h" #include "panel.h" @@ -21,7 +13,7 @@ class Display { public: - explicit Display(IPanelDevice *device); + explicit Display(IPanelDevice &device); ~Display() = default; @@ -61,16 +53,16 @@ private: // Objects stored in the screen associated with this display. // @sa Display::set_text // @sa lv_display_get_screen_active - std::unordered_map objects_; + std::unordered_map lv_objects_; struct ScopedLock { - explicit ScopedLock() { _lock_acquire(&lock_); } + explicit ScopedLock() { _lock_acquire(&lv_lock_); } - ~ScopedLock() { _lock_release(&lock_); } + ~ScopedLock() { _lock_release(&lv_lock_); } // LVGL library is not thread-safe, this example calls LVGL APIs from tasks. // We must use a mutex to protect it. - static _lock_t lock_; + static _lock_t lv_lock_; }; }; diff --git a/esp/cpp/07_lcd-panel/main/i2c.h b/esp/cpp/07_lcd-panel/main/i2c.h index ce7b2d2..ac51b5e 100644 --- a/esp/cpp/07_lcd-panel/main/i2c.h +++ b/esp/cpp/07_lcd-panel/main/i2c.h @@ -4,15 +4,14 @@ #define I2C_BUS_PORT 0 #include -#include "soc/gpio_num.h" static const char *TAG = "lcd-panel"; struct I2C { I2C(gpio_num_t sda, gpio_num_t scl, int rst = -1) : - i2c_bus_(nullptr), + esp_i2c_bus_(nullptr), rst_num_(rst), - bus_config_( + esp_bus_config_( (i2c_master_bus_config_t) { .i2c_port = I2C_BUS_PORT, .sda_io_num = sda, @@ -25,17 +24,18 @@ struct I2C { } ) { - ESP_LOGI(TAG, "Initialize I2C bus"); - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config_, &i2c_bus_)); + ESP_LOGI(TAG, "Initializing new master I2C bus"); + ESP_ERROR_CHECK(i2c_new_master_bus(&esp_bus_config_, &esp_i2c_bus_)); } ~I2C() = default; - i2c_master_bus_handle_t i2c_bus_; + i2c_master_bus_handle_t esp_i2c_bus_; int rst_num_; + private: - i2c_master_bus_config_t bus_config_; + i2c_master_bus_config_t esp_bus_config_; }; #endif //I2C_H diff --git a/esp/cpp/07_lcd-panel/main/main.cpp b/esp/cpp/07_lcd-panel/main/main.cpp index def472f..68a52d2 100644 --- a/esp/cpp/07_lcd-panel/main/main.cpp +++ b/esp/cpp/07_lcd-panel/main/main.cpp @@ -6,14 +6,12 @@ #define PIN_SCL GPIO_NUM_22 #define PIN_RST -1 -// TODO: Can this be static since there can only be one initialization? -// TODO: Store RST in I2C and retrieve within SSD instead of the #define I2C i2c(PIN_SDA, PIN_SCL, PIN_RST); void setup() { SSD1306 ssd1306(i2c); - Display d(&ssd1306); + Display d(ssd1306); d.set_text("Test test 12345678910", "test-text1", diff --git a/esp/cpp/07_lcd-panel/main/panel.cpp b/esp/cpp/07_lcd-panel/main/panel.cpp index e011317..0bc778a 100644 --- a/esp/cpp/07_lcd-panel/main/panel.cpp +++ b/esp/cpp/07_lcd-panel/main/panel.cpp @@ -1,23 +1,21 @@ #include "panel.h" -Panel::Panel(IPanelDevice *device) : - device_(device), - io_handle_(nullptr), +Panel::Panel(IPanelDevice &device) : + device_(&device), + esp_io_handle_(nullptr), esp_panel_(nullptr), - panel_config_( + esp_panel_config_( (esp_lcd_panel_dev_config_t) { .reset_gpio_num = device_->rst_num_, .bits_per_pixel = 1, - // .vendor_config should be set in IPanelDevice::init_panel override + .vendor_config = device_->vendor_config(), } ) { - ESP_LOGI(TAG, "Install panel IO"); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c( - device_->i2c_bus_, &device_->io_config_, &io_handle_)); + esp_io_handle_ = device_->create_io_handle(); - device_->create_panel(panel_config_, io_handle_, esp_panel_); + device_->create_panel(esp_panel_config_, esp_io_handle_, esp_panel_); ESP_LOGI(TAG, "Resetting panel display"); ESP_ERROR_CHECK(esp_lcd_panel_reset(esp_panel_)); diff --git a/esp/cpp/07_lcd-panel/main/panel.h b/esp/cpp/07_lcd-panel/main/panel.h index eebd2b6..4ddeadd 100644 --- a/esp/cpp/07_lcd-panel/main/panel.h +++ b/esp/cpp/07_lcd-panel/main/panel.h @@ -5,18 +5,18 @@ class Panel { public: - explicit Panel(IPanelDevice *device); + explicit Panel(IPanelDevice &device); ~Panel() = default; IPanelDevice *device_; - esp_lcd_panel_io_handle_t io_handle_; + esp_lcd_panel_io_handle_t esp_io_handle_; esp_lcd_panel_handle_t esp_panel_; private: - esp_lcd_panel_dev_config_t panel_config_; + esp_lcd_panel_dev_config_t esp_panel_config_; }; #endif //PANEL_H diff --git a/esp/cpp/07_lcd-panel/main/panel_device.h b/esp/cpp/07_lcd-panel/main/panel_device.h index a2ab745..e3533b2 100644 --- a/esp/cpp/07_lcd-panel/main/panel_device.h +++ b/esp/cpp/07_lcd-panel/main/panel_device.h @@ -3,11 +3,10 @@ #include #include -#include -#include #include #include -#include "display/lv_display.h" + +#include #include "i2c.h" @@ -31,8 +30,8 @@ public: height_(height), rst_num_(i2c.rst_num_), lv_buf_size_(draw_buf_size), - i2c_bus_(i2c.i2c_bus_), - io_config_(io_config) { } + esp_i2c_bus_(i2c.esp_i2c_bus_), + esp_io_config_(io_config) { } virtual ~IPanelDevice() = default; @@ -43,6 +42,15 @@ public: return display; } + [[nodiscard]] esp_lcd_panel_io_handle_t create_io_handle() + { + ESP_LOGI(TAG, "Creating panel IO handle"); + esp_lcd_panel_io_handle_t handle = nullptr; + ESP_ERROR_CHECK( + esp_lcd_new_panel_io_i2c(esp_i2c_bus_, &esp_io_config_, &handle)); + return handle; + } + void create_panel(esp_lcd_panel_dev_config_t &config, esp_lcd_panel_io_handle_t io, esp_lcd_panel_handle_t &panel) @@ -57,16 +65,20 @@ public: init_panel(config, io, panel); } + virtual void *vendor_config() = 0; + int32_t width_; + int32_t height_; + int rst_num_; // LVGL reserves 2x4 bytes in the buffer to be used as a palette. size_t lv_buf_size_; - // TODO: Can we use a static accessor in I2C instead? - i2c_master_bus_handle_t i2c_bus_; - esp_lcd_panel_io_i2c_config_t io_config_; + i2c_master_bus_handle_t esp_i2c_bus_; + + esp_lcd_panel_io_i2c_config_t esp_io_config_; private: virtual void init_panel(esp_lcd_panel_dev_config_t &config, diff --git a/esp/cpp/07_lcd-panel/main/ssd1306.h b/esp/cpp/07_lcd-panel/main/ssd1306.h index 5279391..2537466 100644 --- a/esp/cpp/07_lcd-panel/main/ssd1306.h +++ b/esp/cpp/07_lcd-panel/main/ssd1306.h @@ -31,6 +31,11 @@ public: virtual ~SSD1306() = default; + void *vendor_config() override + { + return &ssd1306_config_; + } + // The configuration structure specific to the SSD1306. esp_lcd_panel_ssd1306_config_t ssd1306_config_; @@ -41,7 +46,6 @@ private: void init_panel(esp_lcd_panel_dev_config_t &config, esp_lcd_panel_io_handle_t io, esp_lcd_panel_handle_t &panel) override; - }; #endif // SSD1306_H