Make TimeKeeper a static member of Display.
This commit is contained in:
		
							parent
							
								
									9140ba5fb4
								
							
						
					
					
						commit
						74404b1a44
					
				@ -12,12 +12,12 @@
 | 
				
			|||||||
// We must use a mutex to protect it.
 | 
					// We must use a mutex to protect it.
 | 
				
			||||||
_lock_t Display::ScopedLock::lv_lock_;
 | 
					_lock_t Display::ScopedLock::lv_lock_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unordered_map<const char *, Display::Timer>
 | 
					// Static TimeKeeper for managing ESP timers across all displays.
 | 
				
			||||||
    Display::TimeKeeper::managed_timers_;
 | 
					Display::TimeKeeper Display::timers_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Display::Display(IPanelDevice &device) :
 | 
					Display::Display(IPanelDevice &device) :
 | 
				
			||||||
    panel_(device),
 | 
					    panel_(device),
 | 
				
			||||||
    lv_tick_timer_(nullptr)
 | 
					    lv_buf_(nullptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (!lv_is_initialized()) {
 | 
					  if (!lv_is_initialized()) {
 | 
				
			||||||
    ESP_LOGI(TAG, "Initialize LVGL");
 | 
					    ESP_LOGI(TAG, "Initialize LVGL");
 | 
				
			||||||
@ -29,30 +29,8 @@ Display::Display(IPanelDevice &device) :
 | 
				
			|||||||
  // associate the i2c panel handle to the display
 | 
					  // associate the i2c panel handle to the display
 | 
				
			||||||
  lv_display_set_user_data(lv_display_, panel_.esp_panel_);
 | 
					  lv_display_set_user_data(lv_display_, panel_.esp_panel_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Create draw buffer.
 | 
					  register_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_));
 | 
					 | 
				
			||||||
  register_lvgl_tick_timer();
 | 
					  register_lvgl_tick_timer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: What is this
 | 
					  // 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()
 | 
					void Display::register_lvgl_tick_timer()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  ESP_LOGI(TAG, "Use esp_timer to increase LVGL tick");
 | 
					  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,
 | 
					      .callback = &Display::lvgl_increase_tick,
 | 
				
			||||||
      .name = "lvgl_tick"
 | 
					      .name = "lvgl_tick"
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  TimeKeeper::start_new_timer_periodic(lvgl_tick_timer_args,
 | 
					  timers_.start_new_timer_periodic(esp_timer_args, LVGL_TICK_PERIOD_MS * 1000);
 | 
				
			||||||
                                       LVGL_TICK_PERIOD_MS * 1000);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,73 @@ class Display {
 | 
				
			|||||||
    esp_timer_handle_t esp_timer_ = nullptr;
 | 
					    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:
 | 
					public:
 | 
				
			||||||
  explicit Display(IPanelDevice &device);
 | 
					  explicit Display(IPanelDevice &device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -71,73 +138,12 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  [[noreturn]] static void lvgl_port_task(void *arg);
 | 
					  [[noreturn]] static void lvgl_port_task(void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  struct TimeKeeper {
 | 
					  // Public static TimeKeeper for managing ESP timers across all displays.
 | 
				
			||||||
    using TimerHandle = Timer *;
 | 
					  static TimeKeeper timers_;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 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:
 | 
					private:
 | 
				
			||||||
 | 
					  void register_draw_buffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void register_lvgl_tick_timer();
 | 
					  void register_lvgl_tick_timer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Panel panel_;
 | 
					  Panel panel_;
 | 
				
			||||||
@ -151,9 +157,6 @@ private:
 | 
				
			|||||||
  // @sa Display::set_text
 | 
					  // @sa Display::set_text
 | 
				
			||||||
  // @sa lv_display_get_screen_active
 | 
					  // @sa lv_display_get_screen_active
 | 
				
			||||||
  std::unordered_map<const char *, lv_obj_t *> lv_objects_;
 | 
					  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
 | 
					#endif // DISPLAY_H
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user