Make TimeKeeper a static member of Display.

This commit is contained in:
Shaun Reed 2025-02-16 09:12:24 -05:00
parent 9140ba5fb4
commit 74404b1a44
2 changed files with 105 additions and 97 deletions

View File

@ -12,12 +12,12 @@
// We must use a mutex to protect it.
_lock_t Display::ScopedLock::lv_lock_;
std::unordered_map<const char *, Display::Timer>
Display::TimeKeeper::managed_timers_;
// Static TimeKeeper for managing ESP timers across all displays.
Display::TimeKeeper Display::timers_;
Display::Display(IPanelDevice &device) :
panel_(device),
lv_tick_timer_(nullptr)
lv_buf_(nullptr)
{
if (!lv_is_initialized()) {
ESP_LOGI(TAG, "Initialize LVGL");
@ -29,30 +29,8 @@ Display::Display(IPanelDevice &device) :
// associate the i2c panel handle to the display
lv_display_set_user_data(lv_display_, panel_.esp_panel_);
// Create draw buffer.
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers");
lv_buf_ = heap_caps_calloc(1, panel_.device_->lv_buf_size_,
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
assert(lv_buf_);
register_draw_buffer();
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);
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);
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,
};
ESP_ERROR_CHECK(
esp_lcd_panel_io_register_event_callbacks(panel_.esp_io_, &cbs,
lv_display_));
register_lvgl_tick_timer();
// TODO: What is this
@ -155,13 +133,40 @@ void Display::lvgl_increase_tick(void *)
}
}
void Display::register_draw_buffer()
{
// Create draw buffer.
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers");
lv_buf_ = heap_caps_calloc(1, panel_.device_->lv_buf_size_,
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
assert(lv_buf_);
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);
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);
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,
};
ESP_ERROR_CHECK(
esp_lcd_panel_io_register_event_callbacks(panel_.esp_io_, &cbs,
lv_display_));
}
void Display::register_lvgl_tick_timer()
{
ESP_LOGI(TAG, "Use esp_timer to increase LVGL tick");
const esp_timer_create_args_t lvgl_tick_timer_args = {
const esp_timer_create_args_t esp_timer_args = {
.callback = &Display::lvgl_increase_tick,
.name = "lvgl_tick"
};
TimeKeeper::start_new_timer_periodic(lvgl_tick_timer_args,
LVGL_TICK_PERIOD_MS * 1000);
timers_.start_new_timer_periodic(esp_timer_args, LVGL_TICK_PERIOD_MS * 1000);
}

View File

@ -41,6 +41,73 @@ class Display {
esp_timer_handle_t esp_timer_ = nullptr;
};
struct TimeKeeper {
using TimerHandle = Timer *;
// Timers should only be accessed using this method.
// For this reason managed_timers_ is private.
TimerHandle get_handle(const char *name)
{
return &managed_timers_.at(name);
}
TimerHandle operator[](const char * name) { return get_handle(name); }
TimerHandle create_timer(esp_timer_create_args_t args)
{
auto rt = managed_timers_.emplace(args.name, args);
if (!rt.second) {
ESP_LOGE(TAG, "Failed to insert timer into Display::managed_timers_");
return nullptr;
}
return &rt.first->second;
}
[[maybe_unused]] void stop_timer(const char *name)
{
ESP_ERROR_CHECK(esp_timer_stop(get_handle(name)->esp_timer_));
}
[[maybe_unused]] void delete_timer(const char *name)
{
managed_timers_.erase(name);
}
[[maybe_unused]] void
start_new_timer_periodic(esp_timer_create_args_t args,
uint64_t period)
{
start_timer_periodic(create_timer(args)->args_.name, period);
}
[[maybe_unused]] void start_timer_periodic(const char *name,
uint64_t period)
{
ESP_ERROR_CHECK(
esp_timer_start_periodic(get_handle(name)->esp_timer_, period));
}
[[maybe_unused]] void
start_new_timer_once(esp_timer_create_args_t args,
uint64_t timeout_us)
{
start_timer_once(create_timer(args)->args_.name, timeout_us);
}
[[maybe_unused]] void start_timer_once(const char *name,
uint64_t timeout_us)
{
ESP_ERROR_CHECK(
esp_timer_start_once(get_handle(name)->esp_timer_, timeout_us));
}
private:
// Timers should only be accessed using the get_handle method.
// ~Timer() will delete the timer if called.
std::unordered_map<const char *, Timer> managed_timers_;
};
public:
explicit Display(IPanelDevice &device);
@ -71,73 +138,12 @@ public:
[[noreturn]] static void lvgl_port_task(void *arg);
struct TimeKeeper {
using TimerHandle = Timer *;
// Timers should only be accessed using this method.
// For this reason managed_timers_ is private.
static TimerHandle get_handle(const char *name)
{
return &managed_timers_.at(name);
}
static TimerHandle create_timer(esp_timer_create_args_t args)
{
auto rt = managed_timers_.emplace(args.name, args);
if (!rt.second) {
ESP_LOGE(TAG, "Failed to insert timer into Display::managed_timers_");
return nullptr;
}
return &rt.first->second;
}
[[maybe_unused]] static void stop_timer(const char *name)
{
ESP_ERROR_CHECK(esp_timer_stop(get_handle(name)->esp_timer_));
}
[[maybe_unused]] static void delete_timer(const char *name)
{
managed_timers_.erase(name);
}
[[maybe_unused]] static void
start_new_timer_periodic(esp_timer_create_args_t args,
uint64_t period)
{
start_timer_periodic(create_timer(args)->args_.name, period);
}
[[maybe_unused]] static void start_timer_periodic(const char *name,
uint64_t period)
{
ESP_ERROR_CHECK(
esp_timer_start_periodic(get_handle(name)->esp_timer_, period));
}
[[maybe_unused]] static void
start_new_timer_once(esp_timer_create_args_t args,
uint64_t timeout_us)
{
start_timer_once(create_timer(args)->args_.name, timeout_us);
}
[[maybe_unused]] static void start_timer_once(const char *name,
uint64_t timeout_us)
{
ESP_ERROR_CHECK(
esp_timer_start_once(get_handle(name)->esp_timer_, timeout_us));
}
// TODO start_timer_once
private:
// Timers should only be accessed using the get_handle method.
// ~Timer() will delete the timer if called.
static std::unordered_map<const char *, Timer> managed_timers_;
};
// Public static TimeKeeper for managing ESP timers across all displays.
static TimeKeeper timers_;
private:
void register_draw_buffer();
void register_lvgl_tick_timer();
Panel panel_;
@ -151,9 +157,6 @@ private:
// @sa Display::set_text
// @sa lv_display_get_screen_active
std::unordered_map<const char *, lv_obj_t *> lv_objects_;
// TODO: This could be a private struct
esp_timer_handle_t lv_tick_timer_;
};
#endif // DISPLAY_H