@@ -44,13 +44,18 @@ template <typename Pixel> class Display : public BaseComponent {
44
44
/* *
45
45
* @brief Callback for lvgl to flush segments of pixel data from the pixel
46
46
* buffers to the display.
47
+ * @param disp The display to flush data to.
48
+ * @param area The area of the display to flush data to.
49
+ * @param color_map The color data to flush to the display.
47
50
*/
48
- using flush_fn = lv_display_flush_cb_t ;
51
+ typedef std::function<void (lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)>
52
+ flush_fn;
49
53
50
54
/* *
51
55
* @brief Callback for lvgl event handler to reconfigure the display hardware.
56
+ * @param rotation The new rotation setting for the display.
52
57
*/
53
- typedef void (*rotation_fn)( const DisplayRotation &rotation);
58
+ typedef std::function< void ( const DisplayRotation &rotation)> rotation_fn ;
54
59
55
60
/* *
56
61
* @brief Callback for setting the display brightness.
@@ -325,20 +330,64 @@ template <typename Pixel> class Display : public BaseComponent {
325
330
*/
326
331
size_t vram_size_bytes () const { return display_buffer_px_size_ * sizeof (Pixel); }
327
332
333
+ /* *
334
+ * @brief Set the rotation of the display.
335
+ * @note This function is called by the event handler when the display
336
+ * resolution changes, so that the display hardware can be reconfigured
337
+ * to match the new software rotation setting.
338
+ * @param rotation The new rotation setting for the display.
339
+ */
340
+ void set_rotation (DisplayRotation rotation) {
341
+ if (rotation_callback_ != nullptr ) {
342
+ rotation_callback_ (rotation);
343
+ }
344
+ }
345
+
346
+ /* *
347
+ * @brief Flush the data to the display.
348
+ * @warning This function is called by the LVGL flush callback, so it is
349
+ * recommended to not call this function directly.
350
+ * @param disp The display to flush data to.
351
+ * @param area The area of the display to flush data to.
352
+ * @param color_map The color data to flush to the display.
353
+ */
354
+ void flush (lv_display_t *disp, const lv_area_t *area, uint8_t *color_map) {
355
+ if (flush_callback_ != nullptr ) {
356
+ flush_callback_ (disp, area, color_map);
357
+ }
358
+ }
359
+
328
360
protected:
329
361
/* *
330
362
* @brief LVGL event handler.
363
+ * @param event The event to handle.
331
364
*/
332
365
static void event_cb (lv_event_t *event) {
333
366
if (lv_event_get_code (event) == LV_EVENT_RESOLUTION_CHANGED) {
334
- auto rotation = lv_display_get_rotation (lv_display_get_default ());
335
- auto rotation_callback = reinterpret_cast <rotation_fn>(lv_event_get_user_data (event));
336
- if (rotation_callback != nullptr ) {
337
- rotation_callback (static_cast <DisplayRotation>(rotation));
367
+ auto rotation =
368
+ static_cast <DisplayRotation>(lv_display_get_rotation (lv_display_get_default ()));
369
+ auto display = static_cast <Display *>(lv_display_get_user_data (lv_disp_get_default ()));
370
+ if (display != nullptr ) {
371
+ display->set_rotation (rotation);
338
372
}
339
373
}
340
374
};
341
375
376
+ /* *
377
+ * @brief Callback for the LVGL flush function to call when it needs to flush
378
+ * data to the display.
379
+ * @param disp The display to flush data to.
380
+ * @param area The area of the display to flush data to.
381
+ * @param color_map The color data to flush to the display.
382
+ */
383
+ static void flush_cb (lv_display_t *disp, const lv_area_t *area, uint8_t *color_map) {
384
+ // use the display to call the registered flush callback appropriately
385
+ auto display = static_cast <Display *>(lv_display_get_user_data (disp));
386
+ if (display != nullptr ) {
387
+ display->flush (disp, area, color_map);
388
+ }
389
+ }
390
+
342
391
/* *
343
392
* @brief Initialize the lvgl subsystem, display buffer configuration, and
344
393
* display driver. Start the task to run the high-priority lvgl
@@ -350,19 +399,31 @@ template <typename Pixel> class Display : public BaseComponent {
350
399
*/
351
400
void init_gfx (const flush_fn flush_callback, const rotation_fn rotation_callback,
352
401
DisplayRotation rotation, const Task::BaseConfig &task_config) {
402
+ // save the callbacks
403
+ if (flush_callback == nullptr ) {
404
+ logger_.error (" No flush callback provided, cannot initialize display!" );
405
+ assert (false ); // cannot continue without a flush callback
406
+ }
407
+ flush_callback_ = flush_callback;
408
+ if (rotation_callback == nullptr ) {
409
+ logger_.warn (" No rotation callback provided, resolution changed event will not automatically "
410
+ " update the display hardware rotation." );
411
+ }
412
+ rotation_callback_ = rotation_callback;
413
+
353
414
lv_init ();
354
415
355
416
display_ = lv_display_create (width_, height_);
417
+ // store a pointer to this object in the display user data, so that we can
418
+ // access it in the flush callback
419
+ lv_display_set_user_data (display_, this );
356
420
357
421
// Configure the lvgl display buffer with our pixel buffers
358
422
lv_display_set_buffers (display_, vram_0_, vram_1_, vram_size_bytes (),
359
423
LV_DISPLAY_RENDER_MODE_PARTIAL);
360
- lv_display_set_flush_cb (display_, flush_callback );
424
+ lv_display_set_flush_cb (display_, Display::flush_cb );
361
425
362
- if (rotation_callback != nullptr ) {
363
- lv_display_add_event_cb (display_, event_cb, LV_EVENT_RESOLUTION_CHANGED,
364
- reinterpret_cast <void *>(rotation_callback));
365
- }
426
+ lv_display_add_event_cb (display_, event_cb, LV_EVENT_RESOLUTION_CHANGED, this );
366
427
367
428
lv_display_set_rotation (display_, static_cast <lv_display_rotation_t >(rotation));
368
429
@@ -449,6 +510,8 @@ template <typename Pixel> class Display : public BaseComponent {
449
510
std::unique_ptr<Task> task_;
450
511
size_t width_;
451
512
size_t height_;
513
+ flush_fn flush_callback_{nullptr };
514
+ rotation_fn rotation_callback_{nullptr };
452
515
size_t display_buffer_px_size_;
453
516
Pixel *vram_0_{nullptr };
454
517
Pixel *vram_1_{nullptr };
0 commit comments