Add Timer and TimeKeeper to Display.

This commit is contained in:
Shaun Reed 2025-02-16 08:58:40 -05:00
parent c9ec16d70c
commit 9140ba5fb4
2 changed files with 100 additions and 15 deletions

View File

@ -12,6 +12,9 @@
// 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_;
Display::Display(IPanelDevice &device) :
panel_(device),
lv_tick_timer_(nullptr)
@ -152,15 +155,13 @@ void Display::lvgl_increase_tick(void *)
}
}
void Display::register_lvgl_tick_timer() // NOLINT(*-convert-member-functions-to-static)
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 = {
.callback = &Display::lvgl_increase_tick,
.name = "lvgl_tick"
};
esp_timer_handle_t lvgl_tick_timer = nullptr;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer,
LVGL_TICK_PERIOD_MS * 1000));
TimeKeeper::start_new_timer_periodic(lvgl_tick_timer_args,
LVGL_TICK_PERIOD_MS * 1000);
}

View File

@ -5,6 +5,7 @@
#include <unordered_map>
#include <esp_timer.h>
#include <memory>
#include "panel.h"
@ -13,6 +14,33 @@
#define LVGL_TASK_PRIORITY 2
class Display {
struct ScopedLock {
explicit ScopedLock() { _lock_acquire(&lv_lock_); }
~ScopedLock() { _lock_release(&lv_lock_); }
// LVGL library is not thread-safe, this example calls LVGL APIs from tasks.
// We must use a mutex to protect it.
static _lock_t lv_lock_;
};
struct Timer {
explicit Timer(esp_timer_create_args_t args) : args_(args)
{
ESP_LOGI(TAG, "Creating esp_timer with name: %s", args.name);
ESP_ERROR_CHECK(esp_timer_create(&args, &esp_timer_));
}
~Timer()
{
ESP_ERROR_CHECK(esp_timer_delete(esp_timer_));
}
[[maybe_unused]] esp_timer_create_args_t args_{};
esp_timer_handle_t esp_timer_ = nullptr;
};
public:
explicit Display(IPanelDevice &device);
@ -43,6 +71,72 @@ 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_;
};
private:
void register_lvgl_tick_timer();
@ -60,16 +154,6 @@ private:
// TODO: This could be a private struct
esp_timer_handle_t lv_tick_timer_;
struct ScopedLock {
explicit ScopedLock() { _lock_acquire(&lv_lock_); }
~ScopedLock() { _lock_release(&lv_lock_); }
// LVGL library is not thread-safe, this example calls LVGL APIs from tasks.
// We must use a mutex to protect it.
static _lock_t lv_lock_;
};
};
#endif // DISPLAY_H