1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-18 15:55:46 +00:00

[lvgl] Revise code generation to allow early widget creation (#7611)

This commit is contained in:
Clyde Stubbs
2024-10-17 13:20:19 +11:00
committed by GitHub
parent f490585f66
commit 8bbe4efded
10 changed files with 155 additions and 132 deletions

View File

@@ -11,12 +11,6 @@ namespace esphome {
namespace lvgl {
static const char *const TAG = "lvgl";
#if LV_USE_LOG
static void log_cb(const char *buf) {
esp_log_printf_(ESPHOME_LOG_LEVEL_INFO, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf);
}
#endif // LV_USE_LOG
static const char *const EVENT_NAMES[] = {
"NONE",
"PRESSED",
@@ -383,26 +377,48 @@ void LvglComponent::write_random_() {
}
}
void LvglComponent::setup() {
ESP_LOGCONFIG(TAG, "LVGL Setup starts");
#if LV_USE_LOG
lv_log_register_print_cb(log_cb);
#endif
/**
* @class LvglComponent
* @brief Component for rendering LVGL.
*
* This component renders LVGL widgets on a display. Some initialisation must be done in the constructor
* since LVGL needs to be initialised before any widgets can be created.
*
* @param displays a list of displays to render onto. All displays must have the same
* resolution.
* @param buffer_frac the fraction of the display resolution to use for the LVGL
* draw buffer. A higher value will make animations smoother but
* also increase memory usage.
* @param full_refresh if true, the display will be fully refreshed on every frame.
* If false, only changed areas will be updated.
* @param draw_rounding the rounding to use when drawing. A value of 1 will draw
* without any rounding, a value of 2 will round to the nearest
* multiple of 2, and so on.
* @param resume_on_input if true, this component will resume rendering when the user
* presses a key or clicks on the screen.
*/
LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh,
int draw_rounding, bool resume_on_input)
: draw_rounding(draw_rounding),
displays_(std::move(displays)),
buffer_frac_(buffer_frac),
full_refresh_(full_refresh),
resume_on_input_(resume_on_input) {
lv_init();
lv_update_event = static_cast<lv_event_code_t>(lv_event_register_id());
lv_api_event = static_cast<lv_event_code_t>(lv_event_register_id());
auto *display = this->displays_[0];
size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_;
auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
auto *buf = lv_custom_mem_alloc(buf_bytes); // NOLINT
if (buf == nullptr) {
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes);
#endif
this->mark_failed();
this->status_set_error("Memory allocation failure");
return;
this->rotation = display->get_rotation();
if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) {
this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
if (this->rotate_buf_ == nullptr)
return;
}
auto *buf = lv_custom_mem_alloc(buf_bytes); // NOLINT
if (buf == nullptr)
return;
lv_disp_draw_buf_init(&this->draw_buf_, buf, nullptr, buffer_pixels);
lv_disp_drv_init(&this->disp_drv_);
this->disp_drv_.draw_buf = &this->draw_buf_;
@@ -410,18 +426,7 @@ void LvglComponent::setup() {
this->disp_drv_.full_refresh = this->full_refresh_;
this->disp_drv_.flush_cb = static_flush_cb;
this->disp_drv_.rounder_cb = rounder_cb;
this->rotation = display->get_rotation();
if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) {
this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
if (this->rotate_buf_ == nullptr) {
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes);
#endif
this->mark_failed();
this->status_set_error("Memory allocation failure");
return;
}
}
// reset the display rotation since we will handle all rotations
display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
switch (this->rotation) {
default:
@@ -435,12 +440,30 @@ void LvglComponent::setup() {
break;
}
this->disp_ = lv_disp_drv_register(&this->disp_drv_);
for (const auto &v : this->init_lambdas_)
v(this);
}
void LvglComponent::setup() {
if (this->draw_buf_.buf1 == nullptr) {
this->mark_failed();
this->status_set_error("Memory allocation failure");
return;
}
ESP_LOGCONFIG(TAG, "LVGL Setup starts");
#if LV_USE_LOG
lv_log_register_print_cb([](const char *buf) {
auto next = strchr(buf, ')');
if (next != nullptr)
buf = next + 1;
while (isspace(*buf))
buf++;
esp_log_printf_(LVGL_LOG_LEVEL, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf);
});
#endif
this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0);
lv_disp_trig_activity(this->disp_);
ESP_LOGCONFIG(TAG, "LVGL Setup complete");
}
void LvglComponent::update() {
// update indicators
if (this->paused_) {
@@ -455,13 +478,6 @@ void LvglComponent::loop() {
}
lv_timer_handler_run_in_period(5);
}
bool lv_is_pre_initialise() {
if (!lv_is_initialized()) {
ESP_LOGE(TAG, "LVGL call before component is initialised");
return true;
}
return false;
}
#ifdef USE_LVGL_ANIMIMG
void lv_animimg_stop(lv_obj_t *obj) {