Skip to content

Commit 44ff49b

Browse files
authored
feat(display): Remove display task to instead have lvgl handle it directly (#400)
* feat: Have LVGL use freertos timing functions * refactor: Applied change to user components * fix: Set correct LVGL delay callback * fix: Fixed component examples
1 parent 5c69d77 commit 44ff49b

File tree

15 files changed

+35
-167
lines changed

15 files changed

+35
-167
lines changed

components/display/include/display.hpp

Lines changed: 15 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,6 @@ template <typename Pixel> class Display : public BaseComponent {
8080
nullptr}; /**< Optional function used to configure display with new rotation setting. */
8181
DisplayRotation rotation{
8282
DisplayRotation::LANDSCAPE}; /**< Default / Initial rotation of the display. */
83-
Task::BaseConfig task_config{.name = "Display",
84-
.stack_size_bytes = 4096,
85-
.priority = 20,
86-
.core_id = 0}; /**< Task configuration. */
87-
std::chrono::duration<float> update_period{
88-
0.01}; /**< How frequently to run the update function. */
8983
};
9084

9185
/**
@@ -148,11 +142,9 @@ template <typename Pixel> class Display : public BaseComponent {
148142
, height_(lvgl_conf.height)
149143
, display_buffer_px_size_(mem_conf.pixel_buffer_size)
150144
, vram_0_(mem_conf.vram0)
151-
, vram_1_(mem_conf.vram1)
152-
, update_period_(lvgl_conf.update_period) {
145+
, vram_1_(mem_conf.vram1) {
153146
init_backlight(lcd_config.backlight_pin, lcd_config.backlight_on_value);
154-
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation,
155-
lvgl_conf.task_config);
147+
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation);
156148
set_brightness(1.0);
157149
}
158150

@@ -170,12 +162,10 @@ template <typename Pixel> class Display : public BaseComponent {
170162
: BaseComponent("Display", log_level)
171163
, width_(lvgl_conf.width)
172164
, height_(lvgl_conf.height)
173-
, display_buffer_px_size_(mem_conf.pixel_buffer_size)
174-
, update_period_(lvgl_conf.update_period) {
165+
, display_buffer_px_size_(mem_conf.pixel_buffer_size) {
175166
init_memory(mem_conf.double_buffered, mem_conf.allocation_flags);
176167
init_backlight(lcd_config.backlight_pin, lcd_config.backlight_on_value);
177-
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation,
178-
lvgl_conf.task_config);
168+
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation);
179169
set_brightness(1.0);
180170
}
181171

@@ -196,11 +186,9 @@ template <typename Pixel> class Display : public BaseComponent {
196186
, display_buffer_px_size_(mem_conf.pixel_buffer_size)
197187
, vram_0_(mem_conf.vram0)
198188
, vram_1_(mem_conf.vram1)
199-
, update_period_(lvgl_conf.update_period)
200189
, set_brightness_(oled_config.set_brightness_callback)
201190
, get_brightness_(oled_config.get_brightness_callback) {
202-
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation,
203-
lvgl_conf.task_config);
191+
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation);
204192
set_brightness(1.0);
205193
}
206194

@@ -219,20 +207,17 @@ template <typename Pixel> class Display : public BaseComponent {
219207
, width_(lvgl_conf.width)
220208
, height_(lvgl_conf.height)
221209
, display_buffer_px_size_(mem_conf.pixel_buffer_size)
222-
, update_period_(lvgl_conf.update_period)
223210
, set_brightness_(oled_config.set_brightness_callback)
224211
, get_brightness_(oled_config.get_brightness_callback) {
225212
init_memory(mem_conf.double_buffered, mem_conf.allocation_flags);
226-
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation,
227-
lvgl_conf.task_config);
213+
init_gfx(lvgl_conf.flush_callback, lvgl_conf.rotation_callback, lvgl_conf.rotation);
228214
set_brightness(1.0);
229215
}
230216

231217
/**
232218
* @brief Stops the upate task and frees the display buffer memory.
233219
*/
234220
~Display() {
235-
task_->stop();
236221
if (created_vram_) {
237222
free(vram_0_);
238223
free(vram_1_);
@@ -282,18 +267,6 @@ template <typename Pixel> class Display : public BaseComponent {
282267
return 0.0f;
283268
}
284269

285-
/**
286-
* @brief Pause the display update task, to prevent LVGL from writing to the
287-
* display.
288-
*/
289-
void pause() { paused_ = true; }
290-
291-
/**
292-
* @brief Resume the display update task, to allow LVGL to write to the
293-
* display.
294-
*/
295-
void resume() { paused_ = false; }
296-
297270
/**
298271
* @brief Force a redraw / refresh of the display.
299272
*
@@ -395,10 +368,9 @@ template <typename Pixel> class Display : public BaseComponent {
395368
* @param flush_callback Callback used to flush color data to the display.
396369
* @param rotation_callback function to call in the event handler on rotation change.
397370
* @param rotation Default / initial rotation of the display.
398-
* @param task_config Configuration for the task that runs the lvgl tick
399371
*/
400372
void init_gfx(const flush_fn flush_callback, const rotation_fn rotation_callback,
401-
DisplayRotation rotation, const Task::BaseConfig &task_config) {
373+
DisplayRotation rotation) {
402374
// save the callbacks
403375
if (flush_callback == nullptr) {
404376
logger_.error("No flush callback provided, cannot initialize display!");
@@ -413,6 +385,10 @@ template <typename Pixel> class Display : public BaseComponent {
413385

414386
lv_init();
415387

388+
lv_tick_set_cb(xTaskGetTickCount);
389+
390+
lv_delay_set_cb(vTaskDelay_wrapper);
391+
416392
display_ = lv_display_create(width_, height_);
417393
// store a pointer to this object in the display user data, so that we can
418394
// access it in the flush callback
@@ -429,14 +405,6 @@ template <typename Pixel> class Display : public BaseComponent {
429405

430406
// Setting as default display, allows the use of lv_disp_get_default()
431407
lv_display_set_default(display_);
432-
433-
// Now start the task for the ui management
434-
using namespace std::placeholders;
435-
task_ = Task::make_unique({
436-
.callback = std::bind(&Display::update, this, _1, _2, _3),
437-
.task_config = task_config,
438-
});
439-
task_->start();
440408
}
441409

442410
/**
@@ -479,35 +447,12 @@ template <typename Pixel> class Display : public BaseComponent {
479447
}
480448

481449
/**
482-
* @brief Flush the data to the display, called within the task_.
483-
*
484-
* This task should always be high priority, so that it is higher than
485-
* than the task running lv_task_handler(). For more info, see
486-
* https://docs.lvgl.io/latest/en/html/porting/tick.html
450+
* @brief Wrapper around vTaskDelay, to pass to LVGL.
451+
* If not, LVGL will do random math as to delay the task instead.
452+
* @param ms The number of milliseconds to delay.
487453
*/
488-
bool update(std::mutex &m, std::condition_variable &cv, bool &task_notified) {
489-
auto now = std::chrono::high_resolution_clock::now();
490-
static auto prev = now;
491-
if (!paused_) {
492-
int elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - prev).count();
493-
// we shouldn't stop, update the display
494-
lv_tick_inc(elapsed_ms);
495-
}
496-
// update previous timestamp
497-
prev = now;
498-
// delay
499-
{
500-
using namespace std::chrono_literals;
501-
std::unique_lock<std::mutex> lk(m);
502-
cv.wait_for(lk, update_period_, [&task_notified] { return task_notified; });
503-
task_notified = false;
504-
}
505-
// don't want to stop the task
506-
return false;
507-
}
454+
static void vTaskDelay_wrapper(const uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); }
508455

509-
std::atomic<bool> paused_{false};
510-
std::unique_ptr<Task> task_;
511456
size_t width_;
512457
size_t height_;
513458
flush_fn flush_callback_{nullptr};
@@ -518,7 +463,6 @@ template <typename Pixel> class Display : public BaseComponent {
518463
bool created_vram_{false};
519464
std::vector<Led::ChannelConfig> led_channel_configs_;
520465
std::unique_ptr<Led> backlight_{nullptr};
521-
std::chrono::duration<float> update_period_;
522466
lv_display_t *display_;
523467
set_brightness_fn set_brightness_{nullptr};
524468
get_brightness_fn get_brightness_{nullptr};

components/esp-box/example/main/esp_box_example.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,8 @@ extern "C" void app_main(void) {
6666
}
6767
// set the pixel buffer to be 50 lines high
6868
static constexpr size_t pixel_buffer_size = box.lcd_width() * 50;
69-
espp::Task::BaseConfig display_task_config = {
70-
.name = "Display",
71-
.stack_size_bytes = 6 * 1024,
72-
.priority = 10,
73-
.core_id = 0,
74-
};
7569
// initialize the LVGL display for the esp-box
76-
if (!box.initialize_display(pixel_buffer_size, display_task_config)) {
70+
if (!box.initialize_display(pixel_buffer_size)) {
7771
logger.error("Failed to initialize display!");
7872
return;
7973
}

components/esp-box/include/esp-box.hpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,9 @@ class EspBox : public BaseComponent {
145145

146146
/// Initialize the display (lvgl display driver)
147147
/// \param pixel_buffer_size The size of the pixel buffer
148-
/// \param task_config The task configuration for the display task
149-
/// \param update_period_ms The update period of the display task
150148
/// \return true if the display was successfully initialized, false otherwise
151149
/// \note This will also allocate two full frame buffers in the SPIRAM
152-
bool initialize_display(size_t pixel_buffer_size,
153-
const espp::Task::BaseConfig &task_config = {.name = "Display",
154-
.stack_size_bytes = 4096,
155-
.priority = 10,
156-
.core_id = 0},
157-
int update_period_ms = 16);
150+
bool initialize_display(size_t pixel_buffer_size);
158151

159152
/// Get the width of the LCD in pixels
160153
/// \return The width of the LCD in pixels

components/esp-box/src/video.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ bool EspBox::initialize_lcd() {
8686
return true;
8787
}
8888

89-
bool EspBox::initialize_display(size_t pixel_buffer_size, const espp::Task::BaseConfig &task_config,
90-
int update_period_ms) {
89+
bool EspBox::initialize_display(size_t pixel_buffer_size) {
9190
if (!lcd_handle_) {
9291
logger_.error(
9392
"LCD not initialized, you must call initialize_lcd() before initialize_display()!");
@@ -104,9 +103,7 @@ bool EspBox::initialize_display(size_t pixel_buffer_size, const espp::Task::Base
104103
.height = lcd_height_,
105104
.flush_callback = DisplayDriver::flush,
106105
.rotation_callback = DisplayDriver::rotate,
107-
.rotation = rotation,
108-
.task_config = task_config,
109-
.update_period = 1ms * update_period_ms},
106+
.rotation = rotation},
110107
Display<Pixel>::LcdConfig{.backlight_pin = backlight_io,
111108
.backlight_on_value = backlight_value},
112109
Display<Pixel>::DynamicMemoryConfig{

components/matouch-rotary-display/include/matouch-rotary-display.hpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,9 @@ class MatouchRotaryDisplay : public BaseComponent {
147147

148148
/// Initialize the display (lvgl display driver)
149149
/// \param pixel_buffer_size The size of the pixel buffer
150-
/// \param task_config The task configuration for the display task
151-
/// \param update_period_ms The update period of the display task
152150
/// \return true if the display was successfully initialized, false otherwise
153151
/// \note This will also allocate two full frame buffers in the SPIRAM
154-
bool initialize_display(size_t pixel_buffer_size,
155-
const espp::Task::BaseConfig &task_config = {.name = "Display",
156-
.stack_size_bytes = 4096,
157-
.priority = 10,
158-
.core_id = 0},
159-
int update_period_ms = 16);
152+
bool initialize_display(size_t pixel_buffer_size);
160153

161154
/// Get the width of the LCD in pixels
162155
/// \return The width of the LCD in pixels

components/matouch-rotary-display/src/matouch-rotary-display.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,7 @@ bool MatouchRotaryDisplay::initialize_lcd() {
283283
return true;
284284
}
285285

286-
bool MatouchRotaryDisplay::initialize_display(size_t pixel_buffer_size,
287-
const espp::Task::BaseConfig &task_config,
288-
int update_period_ms) {
286+
bool MatouchRotaryDisplay::initialize_display(size_t pixel_buffer_size) {
289287
if (!lcd_handle_) {
290288
logger_.error(
291289
"LCD not initialized, you must call initialize_lcd() before initialize_display()!");
@@ -302,9 +300,7 @@ bool MatouchRotaryDisplay::initialize_display(size_t pixel_buffer_size,
302300
.height = lcd_height_,
303301
.flush_callback = DisplayDriver::flush,
304302
.rotation_callback = DisplayDriver::rotate,
305-
.rotation = rotation,
306-
.task_config = task_config,
307-
.update_period = 1ms * update_period_ms},
303+
.rotation = rotation},
308304
Display<Pixel>::LcdConfig{.backlight_pin = backlight_io,
309305
.backlight_on_value = backlight_value},
310306
Display<Pixel>::DynamicMemoryConfig{

components/seeed-studio-round-display/example/main/seeed_studio_round_display_example.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,8 @@ extern "C" void app_main(void) {
6161
}
6262
// set the pixel buffer to be 50 lines high
6363
static constexpr size_t pixel_buffer_size = round_display.lcd_width() * 50;
64-
espp::Task::BaseConfig display_task_config = {
65-
.name = "Display",
66-
.stack_size_bytes = 6 * 1024,
67-
.priority = 10,
68-
.core_id = 0,
69-
};
7064
// initialize the LVGL display for the seeed-studio-round-display
71-
if (!round_display.initialize_display(pixel_buffer_size, display_task_config)) {
65+
if (!round_display.initialize_display(pixel_buffer_size)) {
7266
logger.error("Failed to initialize display!");
7367
return;
7468
}

components/seeed-studio-round-display/include/seeed-studio-round-display.hpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,9 @@ class SsRoundDisplay : public espp::BaseComponent {
164164

165165
/// Initialize the display (lvgl display driver)
166166
/// \param pixel_buffer_size The size of the pixel buffer
167-
/// \param task_config The task configuration for the display task
168-
/// \param update_period_ms The update period of the display task
169167
/// \return true if the display was successfully initialized, false otherwise
170168
/// \note This will also allocate two full frame buffers in the SPIRAM
171-
bool initialize_display(size_t pixel_buffer_size,
172-
const espp::Task::BaseConfig &task_config = {.name = "Display",
173-
.stack_size_bytes = 4096,
174-
.priority = 10,
175-
.core_id = 0},
176-
int update_period_ms = 16);
169+
bool initialize_display(size_t pixel_buffer_size);
177170

178171
/// Get the width of the LCD in pixels
179172
/// \return The width of the LCD in pixels

components/seeed-studio-round-display/src/seeed-studio-round-display.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,7 @@ bool SsRoundDisplay::initialize_lcd() {
243243
return true;
244244
}
245245

246-
bool SsRoundDisplay::initialize_display(size_t pixel_buffer_size,
247-
const espp::Task::BaseConfig &task_config,
248-
int update_period_ms) {
246+
bool SsRoundDisplay::initialize_display(size_t pixel_buffer_size) {
249247
if (!lcd_handle_) {
250248
logger_.error(
251249
"LCD not initialized, you must call initialize_lcd() before initialize_display()!");
@@ -262,9 +260,7 @@ bool SsRoundDisplay::initialize_display(size_t pixel_buffer_size,
262260
.height = lcd_height_,
263261
.flush_callback = DisplayDriver::flush,
264262
.rotation_callback = DisplayDriver::rotate,
265-
.rotation = rotation,
266-
.task_config = task_config,
267-
.update_period = 1ms * update_period_ms},
263+
.rotation = rotation},
268264
Display<Pixel>::LcdConfig{.backlight_pin = pin_config_.lcd_backlight,
269265
.backlight_on_value = backlight_value},
270266
Display<Pixel>::DynamicMemoryConfig{

components/t-deck/include/t-deck.hpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,16 +239,9 @@ class TDeck : public BaseComponent {
239239

240240
/// Initialize the display (lvgl display driver)
241241
/// \param pixel_buffer_size The size of the pixel buffer
242-
/// \param task_config The task configuration for the display task
243-
/// \param update_period_ms The update period of the display task
244242
/// \return true if the display was successfully initialized, false otherwise
245243
/// \note This will also allocate two full frame buffers in the SPIRAM
246-
bool initialize_display(size_t pixel_buffer_size,
247-
const espp::Task::BaseConfig &task_config = {.name = "Display",
248-
.stack_size_bytes = 4096,
249-
.priority = 10,
250-
.core_id = 0},
251-
int update_period_ms = 16);
244+
bool initialize_display(size_t pixel_buffer_size);
252245

253246
/// Get the width of the LCD in pixels
254247
/// \return The width of the LCD in pixels

0 commit comments

Comments
 (0)