ESPHome 2026.3.0
Loading...
Searching...
No Matches
lvgl_esphome.cpp
Go to the documentation of this file.
2#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5#include "lvgl_hal.h"
6#include "lvgl_esphome.h"
7
8#include <numeric>
9
10namespace esphome {
11namespace lvgl {
12static const char *const TAG = "lvgl";
13
14static const size_t MIN_BUFFER_FRAC = 8;
15
16static const char *const EVENT_NAMES[] = {
17 "NONE",
18 "PRESSED",
19 "PRESSING",
20 "PRESS_LOST",
21 "SHORT_CLICKED",
22 "LONG_PRESSED",
23 "LONG_PRESSED_REPEAT",
24 "CLICKED",
25 "RELEASED",
26 "SCROLL_BEGIN",
27 "SCROLL_END",
28 "SCROLL",
29 "GESTURE",
30 "KEY",
31 "FOCUSED",
32 "DEFOCUSED",
33 "LEAVE",
34 "HIT_TEST",
35 "COVER_CHECK",
36 "REFR_EXT_DRAW_SIZE",
37 "DRAW_MAIN_BEGIN",
38 "DRAW_MAIN",
39 "DRAW_MAIN_END",
40 "DRAW_POST_BEGIN",
41 "DRAW_POST",
42 "DRAW_POST_END",
43 "DRAW_PART_BEGIN",
44 "DRAW_PART_END",
45 "VALUE_CHANGED",
46 "INSERT",
47 "REFRESH",
48 "READY",
49 "CANCEL",
50 "DELETE",
51 "CHILD_CHANGED",
52 "CHILD_CREATED",
53 "CHILD_DELETED",
54 "SCREEN_UNLOAD_START",
55 "SCREEN_LOAD_START",
56 "SCREEN_LOADED",
57 "SCREEN_UNLOADED",
58 "SIZE_CHANGED",
59 "STYLE_CHANGED",
60 "LAYOUT_CHANGED",
61 "GET_SELF_SIZE",
62};
63
64std::string lv_event_code_name_for(uint8_t event_code) {
65 if (event_code < sizeof(EVENT_NAMES) / sizeof(EVENT_NAMES[0])) {
66 return EVENT_NAMES[event_code];
67 }
68 // max 4 bytes: "%u" with uint8_t (max 255, 3 digits) + null
69 char buf[4];
70 snprintf(buf, sizeof(buf), "%u", event_code);
71 return buf;
72}
73
74static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) {
75 // cater for display driver chips with special requirements for bounds of partial
76 // draw areas. Extend the draw area to satisfy:
77 // * Coordinates must be a multiple of draw_rounding
78 auto *comp = static_cast<LvglComponent *>(disp_drv->user_data);
79 auto draw_rounding = comp->draw_rounding;
80 // round down the start coordinates
81 area->x1 = area->x1 / draw_rounding * draw_rounding;
82 area->y1 = area->y1 / draw_rounding * draw_rounding;
83 // round up the end coordinates
84 area->x2 = (area->x2 + draw_rounding) / draw_rounding * draw_rounding - 1;
85 area->y2 = (area->y2 + draw_rounding) / draw_rounding * draw_rounding - 1;
86}
87
88void LvglComponent::monitor_cb(lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px) {
89 ESP_LOGVV(TAG, "Draw end: %" PRIu32 " pixels in %" PRIu32 " ms", px, time);
90 auto *comp = static_cast<LvglComponent *>(disp_drv->user_data);
91 comp->draw_end_();
92}
93
94void LvglComponent::render_start_cb(lv_disp_drv_t *disp_drv) {
95 ESP_LOGVV(TAG, "Draw start");
96 auto *comp = static_cast<LvglComponent *>(disp_drv->user_data);
97 comp->draw_start_();
98}
99
100lv_event_code_t lv_api_event; // NOLINT
101lv_event_code_t lv_update_event; // NOLINT
103 ESP_LOGCONFIG(TAG,
104 "LVGL:\n"
105 " Display width/height: %d x %d\n"
106 " Buffer size: %zu%%\n"
107 " Rotation: %d\n"
108 " Draw rounding: %d",
109 this->disp_drv_.hor_res, this->disp_drv_.ver_res, 100 / this->buffer_frac_, this->rotation,
110 (int) this->draw_rounding);
111}
112
113void LvglComponent::set_paused(bool paused, bool show_snow) {
114 this->paused_ = paused;
115 this->show_snow_ = show_snow;
116 if (!paused && lv_scr_act() != nullptr) {
117 lv_disp_trig_activity(this->disp_); // resets the inactivity time
118 lv_obj_invalidate(lv_scr_act());
119 }
120 if (paused && this->pause_callback_ != nullptr)
121 this->pause_callback_->trigger();
122 if (!paused && this->resume_callback_ != nullptr)
123 this->resume_callback_->trigger();
124}
125
127 lv_init();
128 lv_update_event = static_cast<lv_event_code_t>(lv_event_register_id());
129 lv_api_event = static_cast<lv_event_code_t>(lv_event_register_id());
130}
131
132void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) {
133 lv_obj_add_event_cb(obj, callback, event, nullptr);
134}
135
136void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
137 lv_event_code_t event2) {
138 add_event_cb(obj, callback, event1);
139 add_event_cb(obj, callback, event2);
140}
141
142void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
143 lv_event_code_t event2, lv_event_code_t event3) {
144 add_event_cb(obj, callback, event1);
145 add_event_cb(obj, callback, event2);
146 add_event_cb(obj, callback, event3);
147}
148
150 this->pages_.push_back(page);
151 page->set_parent(this);
152 lv_disp_set_default(this->disp_);
153 page->setup(this->pages_.size() - 1);
154}
155
156void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) {
157 if (index >= this->pages_.size())
158 return;
159 this->current_page_ = index;
160 lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false);
161}
162
163void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) {
164 if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_))
165 return;
166 size_t start = this->current_page_;
167 do {
168 this->current_page_ = (this->current_page_ + 1) % this->pages_.size();
169 if (this->current_page_ == start)
170 return; // all pages have skip=true (guaranteed not to happen by YAML validation)
171 } while (this->pages_[this->current_page_]->skip); // skip empty pages()
172 this->show_page(this->current_page_, anim, time);
173}
174
175void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) {
176 if (this->pages_.empty() || (this->current_page_ == 0 && !this->page_wrap_))
177 return;
178 size_t start = this->current_page_;
179 do {
180 this->current_page_ = (this->current_page_ + this->pages_.size() - 1) % this->pages_.size();
181 if (this->current_page_ == start)
182 return; // all pages have skip=true (guaranteed not to happen by YAML validation)
183 } while (this->pages_[this->current_page_]->skip); // skip empty pages()
184 this->show_page(this->current_page_, anim, time);
185}
186
187size_t LvglComponent::get_current_page() const { return this->current_page_; }
188bool LvPageType::is_showing() const { return this->parent_->get_current_page() == this->index; }
189
190void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) {
191 auto width = lv_area_get_width(area);
192 auto height = lv_area_get_height(area);
193 auto height_rounded = (height + this->draw_rounding - 1) / this->draw_rounding * this->draw_rounding;
194 auto x1 = area->x1;
195 auto y1 = area->y1;
196 lv_color_t *dst = this->rotate_buf_;
197 switch (this->rotation) {
199 for (lv_coord_t x = height; x-- != 0;) {
200 for (lv_coord_t y = 0; y != width; y++) {
201 dst[y * height_rounded + x] = *ptr++;
202 }
203 }
204 y1 = x1;
205 x1 = this->disp_drv_.ver_res - area->y1 - height;
206 height = width;
207 width = height_rounded;
208 break;
209
211 for (lv_coord_t y = height; y-- != 0;) {
212 for (lv_coord_t x = width; x-- != 0;) {
213 dst[y * width + x] = *ptr++;
214 }
215 }
216 x1 = this->disp_drv_.hor_res - x1 - width;
217 y1 = this->disp_drv_.ver_res - y1 - height;
218 break;
219
221 for (lv_coord_t x = 0; x != height; x++) {
222 for (lv_coord_t y = width; y-- != 0;) {
223 dst[y * height_rounded + x] = *ptr++;
224 }
225 }
226 x1 = y1;
227 y1 = this->disp_drv_.hor_res - area->x1 - width;
228 height = width;
229 width = height_rounded;
230 break;
231
232 default:
233 dst = ptr;
234 break;
235 }
236 for (auto *display : this->displays_) {
237 ESP_LOGV(TAG, "draw buffer x1=%d, y1=%d, width=%d, height=%d", x1, y1, width, height);
238 display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) dst, display::COLOR_ORDER_RGB, LV_BITNESS,
239 LV_COLOR_16_SWAP);
240 }
241}
242
243void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
244 if (!this->is_paused()) {
245 auto now = millis();
246 this->draw_buffer_(area, color_p);
247 ESP_LOGVV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area),
248 lv_area_get_height(area), (int) (millis() - now));
249 }
250 lv_disp_flush_ready(disp_drv);
251}
252
253IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeout) : timeout_(std::move(timeout)) {
254 parent->add_on_idle_callback([this](uint32_t idle_time) {
255 if (!this->is_idle_ && idle_time > this->timeout_.value()) {
256 this->is_idle_ = true;
257 this->trigger();
258 } else if (this->is_idle_ && idle_time < this->timeout_.value()) {
259 this->is_idle_ = false;
260 }
261 });
262}
263
264#ifdef USE_LVGL_TOUCHSCREEN
265LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent) {
266 this->set_parent(parent);
267 lv_indev_drv_init(&this->drv_);
268 this->drv_.disp = parent->get_disp();
269 this->drv_.long_press_repeat_time = long_press_repeat_time;
270 this->drv_.long_press_time = long_press_time;
271 this->drv_.type = LV_INDEV_TYPE_POINTER;
272 this->drv_.user_data = this;
273 this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
274 auto *l = static_cast<LVTouchListener *>(d->user_data);
275 if (l->touch_pressed_) {
276 data->point.x = l->touch_point_.x;
277 data->point.y = l->touch_point_.y;
278 data->state = LV_INDEV_STATE_PRESSED;
279 } else {
280 data->state = LV_INDEV_STATE_RELEASED;
281 }
282 };
283}
284
286 this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty();
287 if (this->touch_pressed_)
288 this->touch_point_ = tpoints[0];
289}
290#endif // USE_LVGL_TOUCHSCREEN
291
292#ifdef USE_LVGL_KEY_LISTENER
293LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) {
294 lv_indev_drv_init(&this->drv_);
295 this->drv_.type = type;
296 this->drv_.user_data = this;
297 this->drv_.long_press_time = lpt;
298 this->drv_.long_press_repeat_time = lprt;
299 this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
300 auto *l = static_cast<LVEncoderListener *>(d->user_data);
301 data->state = l->pressed_ ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
302 data->key = l->key_;
303 data->enc_diff = (int16_t) (l->count_ - l->last_count_);
304 l->last_count_ = l->count_;
305 data->continue_reading = false;
306 };
307}
308#endif // USE_LVGL_KEY_LISTENER
309
310#if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER)
312 auto selected = this->get_selected_index();
313 if (selected >= this->options_.size())
314 return "";
315 return this->options_[selected];
316}
317
318static std::string join_string(std::vector<std::string> options) {
319 return std::accumulate(
320 options.begin(), options.end(), std::string(),
321 [](const std::string &a, const std::string &b) -> std::string { return a + (!a.empty() ? "\n" : "") + b; });
322}
323
324void LvSelectable::set_selected_text(const std::string &text, lv_anim_enable_t anim) {
325 auto index = std::find(this->options_.begin(), this->options_.end(), text);
326 if (index != this->options_.end()) {
327 this->set_selected_index(index - this->options_.begin(), anim);
328 lv_event_send(this->obj, lv_api_event, nullptr);
329 }
330}
331
332void LvSelectable::set_options(std::vector<std::string> options) {
333 auto index = this->get_selected_index();
334 if (index >= options.size())
335 index = options.size() - 1;
336 this->options_ = std::move(options);
337 this->set_option_string(join_string(this->options_).c_str());
338 lv_event_send(this->obj, LV_EVENT_REFRESH, nullptr);
339 this->set_selected_index(index, LV_ANIM_OFF);
340}
341#endif // USE_LVGL_DROPDOWN || LV_USE_ROLLER
342
343#ifdef USE_LVGL_BUTTONMATRIX
344void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) {
345 LvCompound::set_obj(lv_obj);
346 lv_obj_add_event_cb(
347 lv_obj,
348 [](lv_event_t *event) {
349 auto *self = static_cast<LvButtonMatrixType *>(event->user_data);
350 if (self->key_callback_.size() == 0)
351 return;
352 auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
353 if (key_idx == LV_BTNMATRIX_BTN_NONE)
354 return;
355 if (self->key_map_.count(key_idx) != 0) {
356 self->send_key_(self->key_map_[key_idx]);
357 return;
358 }
359 const auto *str = lv_btnmatrix_get_btn_text(self->obj, key_idx);
360 auto len = strlen(str);
361 while (len--)
362 self->send_key_(*str++);
363 },
364 LV_EVENT_PRESSED, this);
365}
366#endif // USE_LVGL_BUTTONMATRIX
367
368#ifdef USE_LVGL_KEYBOARD
369static const char *const KB_SPECIAL_KEYS[] = {
370 "abc", "ABC", "1#",
371 // maybe add other special keys here
372};
373
374void LvKeyboardType::set_obj(lv_obj_t *lv_obj) {
375 LvCompound::set_obj(lv_obj);
376 lv_obj_add_event_cb(
377 lv_obj,
378 [](lv_event_t *event) {
379 auto *self = static_cast<LvKeyboardType *>(event->user_data);
380 if (self->key_callback_.size() == 0)
381 return;
382
383 auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
384 if (key_idx == LV_BTNMATRIX_BTN_NONE)
385 return;
386 const char *txt = lv_btnmatrix_get_btn_text(self->obj, key_idx);
387 if (txt == nullptr)
388 return;
389 for (const auto *kb_special_key : KB_SPECIAL_KEYS) {
390 if (strcmp(txt, kb_special_key) == 0)
391 return;
392 }
393 while (*txt != 0)
394 self->send_key_(*txt++);
395 },
396 LV_EVENT_PRESSED, this);
397}
398#endif // USE_LVGL_KEYBOARD
399
401 if (this->draw_end_callback_ != nullptr)
403 if (this->update_when_display_idle_) {
404 for (auto *disp : this->displays_)
405 disp->update();
406 }
407}
408
410 if (this->paused_)
411 return true;
412 if (this->update_when_display_idle_) {
413 for (auto *disp : this->displays_) {
414 if (!disp->is_idle())
415 return true;
416 }
417 }
418 return false;
419}
420
422 int iterations = 6 - lv_disp_get_inactive_time(this->disp_) / 60000;
423 if (iterations <= 0)
424 iterations = 1;
425 while (iterations-- != 0) {
426 auto col = random_uint32() % this->disp_drv_.hor_res;
427 col = col / this->draw_rounding * this->draw_rounding;
428 auto row = random_uint32() % this->disp_drv_.ver_res;
429 row = row / this->draw_rounding * this->draw_rounding;
430 auto size = ((random_uint32() % 32) / this->draw_rounding + 2) * this->draw_rounding - 1;
431 // clamp size so the square fits within the draw buffer
432 if ((size + 1) * (size + 1) > this->draw_buf_.size)
433 size = static_cast<decltype(size)>(sqrtf(this->draw_buf_.size)) - 1;
434 lv_area_t area;
435 area.x1 = col;
436 area.y1 = row;
437 area.x2 = col + size;
438 area.y2 = row + size;
439 if (area.x2 >= this->disp_drv_.hor_res)
440 area.x2 = this->disp_drv_.hor_res - 1;
441 if (area.y2 >= this->disp_drv_.ver_res)
442 area.y2 = this->disp_drv_.ver_res - 1;
443
444 size_t line_len = lv_area_get_width(&area) * lv_area_get_height(&area) / 2;
445 for (size_t i = 0; i != line_len; i++) {
446 ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32();
447 }
448 this->draw_buffer_(&area, (lv_color_t *) this->draw_buf_.buf1);
449 }
450}
451
472LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh,
473 int draw_rounding, bool resume_on_input, bool update_when_display_idle)
474 : draw_rounding(draw_rounding),
475 displays_(std::move(displays)),
476 buffer_frac_(buffer_frac),
477 full_refresh_(full_refresh),
478 resume_on_input_(resume_on_input),
479 update_when_display_idle_(update_when_display_idle) {
480 lv_disp_draw_buf_init(&this->draw_buf_, nullptr, nullptr, 0);
481 lv_disp_drv_init(&this->disp_drv_);
482 this->disp_drv_.draw_buf = &this->draw_buf_;
483 this->disp_drv_.user_data = this;
484 this->disp_drv_.full_refresh = this->full_refresh_;
485 this->disp_drv_.flush_cb = static_flush_cb;
486 this->disp_drv_.rounder_cb = rounder_cb;
487 this->disp_ = lv_disp_drv_register(&this->disp_drv_);
488}
489
491 auto *display = this->displays_[0];
492 auto rounding = this->draw_rounding;
493 // cater for displays with dimensions that don't divide by the required rounding
494 auto width = (display->get_width() + rounding - 1) / rounding * rounding;
495 auto height = (display->get_height() + rounding - 1) / rounding * rounding;
496 auto frac = this->buffer_frac_;
497 if (frac == 0)
498 frac = 1;
499 size_t buffer_pixels = width * height / frac;
500 auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
501 void *buffer = nullptr;
502 if (this->buffer_frac_ >= MIN_BUFFER_FRAC / 2)
503 buffer = malloc(buf_bytes); // NOLINT
504 if (buffer == nullptr)
505 buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT
506 // if specific buffer size not set and can't get 100%, try for a smaller one
507 if (buffer == nullptr && this->buffer_frac_ == 0) {
508 frac = MIN_BUFFER_FRAC;
509 buffer_pixels /= MIN_BUFFER_FRAC;
510 buf_bytes /= MIN_BUFFER_FRAC;
511 buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT
512 }
513 this->buffer_frac_ = frac;
514 if (buffer == nullptr) {
515 this->status_set_error(LOG_STR("Memory allocation failure"));
516 this->mark_failed();
517 return;
518 }
519 lv_disp_draw_buf_init(&this->draw_buf_, buffer, nullptr, buffer_pixels);
520 this->disp_drv_.hor_res = display->get_width();
521 this->disp_drv_.ver_res = display->get_height();
522 lv_disp_drv_update(this->disp_, &this->disp_drv_);
523 this->rotation = display->get_rotation();
525 this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
526 if (this->rotate_buf_ == nullptr) {
527 this->status_set_error(LOG_STR("Memory allocation failure"));
528 this->mark_failed();
529 return;
530 }
531 }
532 if (this->draw_start_callback_ != nullptr) {
533 this->disp_drv_.render_start_cb = render_start_cb;
534 }
535 if (this->draw_end_callback_ != nullptr || this->update_when_display_idle_) {
536 this->disp_drv_.monitor_cb = monitor_cb;
537 }
538#if LV_USE_LOG
539 lv_log_register_print_cb([](const char *buf) {
540 auto next = strchr(buf, ')');
541 if (next != nullptr)
542 buf = next + 1;
543 while (isspace(*buf))
544 buf++;
545 esp_log_printf_(LVGL_LOG_LEVEL, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf);
546 });
547#endif
548 // Rotation will be handled by our drawing function, so reset the display rotation.
549 for (auto *disp : this->displays_)
550 disp->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
551 this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0);
552 lv_disp_trig_activity(this->disp_);
553}
554
556 // update indicators
557 if (this->is_paused()) {
558 return;
559 }
560 this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_));
561}
562
564 if (this->is_paused()) {
565 if (this->paused_ && this->show_snow_)
566 this->write_random_();
567 } else {
568 lv_timer_handler_run_in_period(5);
569 }
570}
571
572#ifdef USE_LVGL_ANIMIMG
573void lv_animimg_stop(lv_obj_t *obj) {
574 auto *animg = (lv_animimg_t *) obj;
575 int32_t duration = animg->anim.time;
576 lv_animimg_set_duration(obj, 0);
577 lv_animimg_start(obj);
578 lv_animimg_set_duration(obj, duration);
579}
580#endif
581void LvglComponent::static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
582 reinterpret_cast<LvglComponent *>(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p);
583}
584} // namespace lvgl
585} // namespace esphome
586
587size_t lv_millis(void) { return esphome::millis(); }
588
589#if defined(USE_HOST) || defined(USE_RP2040) || defined(USE_ESP8266)
590void *lv_custom_mem_alloc(size_t size) {
591 auto *ptr = malloc(size); // NOLINT
592 if (ptr == nullptr) {
593 ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
594 }
595 return ptr;
596}
597void lv_custom_mem_free(void *ptr) { return free(ptr); } // NOLINT
598void *lv_custom_mem_realloc(void *ptr, size_t size) { return realloc(ptr, size); } // NOLINT
599#else
600static unsigned cap_bits = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; // NOLINT
601
602void *lv_custom_mem_alloc(size_t size) {
603 void *ptr;
604 ptr = heap_caps_malloc(size, cap_bits);
605 if (ptr == nullptr) {
606 cap_bits = MALLOC_CAP_8BIT;
607 ptr = heap_caps_malloc(size, cap_bits);
608 }
609 if (ptr == nullptr) {
610 ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
611 return nullptr;
612 }
613 ESP_LOGV(esphome::lvgl::TAG, "allocate %zu - > %p", size, ptr);
614 return ptr;
615}
616
617void lv_custom_mem_free(void *ptr) {
618 ESP_LOGV(esphome::lvgl::TAG, "free %p", ptr);
619 if (ptr == nullptr)
620 return;
621 heap_caps_free(ptr);
622}
623
624void *lv_custom_mem_realloc(void *ptr, size_t size) {
625 ESP_LOGV(esphome::lvgl::TAG, "realloc %p: %zu", ptr, size);
626 return heap_caps_realloc(ptr, size, cap_bits);
627}
628#endif
uint8_t l
Definition bl0906.h:0
void mark_failed()
Mark this component as failed.
void set_parent(T *parent)
Set the parent of this object.
Definition helpers.h:1723
T value(X... x) const
Definition automation.h:160
void trigger(const Ts &...x)
Inform the parent automation that the event has triggered.
Definition automation.h:325
IdleTrigger(LvglComponent *parent, TemplatableValue< uint32_t > timeout)
TemplatableValue< uint32_t > timeout_
LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt)
LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent)
touchscreen::TouchPoint touch_point_
void update(const touchscreen::TouchPoints_t &tpoints) override
void set_obj(lv_obj_t *lv_obj) override
virtual void set_obj(lv_obj_t *lv_obj)
void set_obj(lv_obj_t *lv_obj) override
void setup(size_t index)
void set_selected_text(const std::string &text, lv_anim_enable_t anim)
void set_options(std::vector< std::string > options)
std::vector< std::string > options_
virtual void set_selected_index(size_t index, lv_anim_enable_t anim)=0
virtual size_t get_selected_index()=0
virtual void set_option_string(const char *options)=0
Component for rendering LVGL.
void set_paused(bool paused, bool show_snow)
static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
LvglComponent(std::vector< display::Display * > displays, float buffer_frac, bool full_refresh, int draw_rounding, bool resume_on_input, bool update_when_display_idle)
std::vector< LvPageType * > pages_
static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event)
void show_next_page(lv_scr_load_anim_t anim, uint32_t time)
CallbackManager< void(uint32_t)> idle_callbacks_
void add_on_idle_callback(std::function< void(uint32_t)> &&callback)
lv_disp_draw_buf_t draw_buf_
display::DisplayRotation rotation
void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time)
void show_prev_page(lv_scr_load_anim_t anim, uint32_t time)
static void render_start_cb(lv_disp_drv_t *disp_drv)
std::vector< display::Display * > displays_
static void esphome_lvgl_init()
Initialize the LVGL library and register custom events.
void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
void add_page(LvPageType *page)
void draw_buffer_(const lv_area_t *area, lv_color_t *ptr)
static void monitor_cb(lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px)
uint16_t type
uint8_t options
void * lv_custom_mem_alloc(size_t size)
size_t lv_millis(void)
void lv_custom_mem_free(void *ptr)
void * lv_custom_mem_realloc(void *ptr, size_t size)
uint8_t duration
Definition msa3xx.h:0
@ DISPLAY_ROTATION_0_DEGREES
Definition display.h:135
@ DISPLAY_ROTATION_270_DEGREES
Definition display.h:138
@ DISPLAY_ROTATION_180_DEGREES
Definition display.h:137
@ DISPLAY_ROTATION_90_DEGREES
Definition display.h:136
void lv_animimg_stop(lv_obj_t *obj)
std::string lv_event_code_name_for(uint8_t event_code)
lv_event_code_t lv_update_event
void(_lv_event_t *) event_callback_t
lv_event_code_t lv_api_event
std::vector< TouchPoint > TouchPoints_t
Definition touchscreen.h:30
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void HOT esp_log_printf_(int level, const char *tag, int line, const char *format,...)
Definition log.cpp:21
std::string size_t len
Definition helpers.h:892
size_t size
Definition helpers.h:929
if(written< 0)
Definition helpers.h:938
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
Definition helpers.cpp:17
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:26
static void uint32_t
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6