zpp
Zephyr C++20 Framework
timer.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2019 Erwin Rol <erwin@erwinrol.com>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 #ifndef ZPP_INCLUDE_ZPP_TIMER_HPP
8 #define ZPP_INCLUDE_ZPP_TIMER_HPP
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include <chrono>
14 #include <functional>
15 #include <type_traits>
16 
17 #include <zpp/clock.hpp>
18 
19 namespace zpp {
20 
24 class timer_base {
25 protected:
26  timer_base() noexcept
27  {
28  }
29 public:
34  {
35  stop();
36  }
37 
44  template<class T_Rep1, class T_Period1, class T_Rep2, class T_Period2>
45  void start(const std::chrono::duration<T_Rep1, T_Period1>& duration,
46  const std::chrono::duration<T_Rep2, T_Period2>& period) noexcept
47  {
48  using namespace std::chrono;
49 
50  k_timer_start(&m_timer, to_timeout(duration), to_timeout(period));
51  }
52 
58  template<class T_Rep, class T_Period>
59  void start(const std::chrono::duration<T_Rep, T_Period>& duration) noexcept
60  {
61  using namespace std::chrono;
62 
63  k_timer_start(&m_timer, to_timeout(duration), K_NO_WAIT);
64  }
65 
69  void stop () noexcept
70  {
71  k_timer_stop(&m_timer);
72  }
73 
79  auto status() noexcept
80  {
81  return k_timer_status_get(&m_timer);
82  }
83 
87  auto sync() noexcept
88  {
89  return k_timer_status_sync(&m_timer);
90  }
91 
97  std::chrono::nanoseconds remaining_time() noexcept
98  {
99  auto t = k_timer_remaining_ticks(&m_timer);
100  return std::chrono::nanoseconds(k_ticks_to_ns_floor64(t));
101  }
102 
108  auto native_handle() noexcept
109  {
110  return &m_timer;
111  }
112 private:
113  struct k_timer m_timer { };
114 public:
115  timer_base(const timer_base&) = delete;
116  timer_base(timer_base&&) = delete;
117  timer_base& operator=(const timer_base&) = delete;
119 };
120 
127 template<class T_ExpireCallback, class T_StopCallback>
128 class timer : public timer_base
129 {
130 public:
131  timer() = delete;
132 
139  explicit timer(T_ExpireCallback ecb, T_StopCallback scb) noexcept
140  : timer_base()
141  , m_expire_callback(ecb)
142  , m_stop_callback(scb)
143  {
144  k_timer_expiry_t ecb_func = [](struct k_timer* t) noexcept {
145  auto self = get_user_data(t);
146  if (self != nullptr) {
147  std::invoke(self->m_expire_callback, self);
148  }
149  };
150 
151  k_timer_stop_t scb_func = [](struct k_timer* t) noexcept {
152  auto self = get_user_data(t);
153  if (self != nullptr) {
154  std::invoke(self->m_stop_callback, self);
155  }
156  };
157 
158  k_timer_init( native_handle(), ecb_func, scb_func);
159  k_timer_user_data_set( native_handle(), this);
160  }
161 private:
162  static timer* get_user_data(struct k_timer* t) noexcept
163  {
164  return static_cast<timer*>(k_timer_user_data_get(t));
165  }
166 private:
167  T_ExpireCallback m_expire_callback;
168  T_StopCallback m_stop_callback;
169 };
170 
171 
177 template<class T_ExpireCallback>
178 class basic_timer : public timer_base
179 {
180 public:
181  basic_timer() = delete;
182 
188  explicit basic_timer(T_ExpireCallback ecb) noexcept
189  : timer_base()
190  , m_expire_callback(ecb)
191  {
192  k_timer_expiry_t ecb_func = [](struct k_timer* t) noexcept {
193  auto self = get_user_data(t);
194  if (self != nullptr) {
195  std::invoke(self->m_expire_callback, self);
196  }
197  };
198 
199  k_timer_init( native_handle(), ecb_func, nullptr);
200  k_timer_user_data_set( native_handle(), this);
201  }
202 private:
203  static basic_timer* get_user_data(struct k_timer* t) noexcept
204  {
205  return static_cast<basic_timer*>(k_timer_user_data_get(t));
206  }
207 private:
208  T_ExpireCallback m_expire_callback;
209 };
210 
211 
215 class sync_timer : public timer_base
216 {
217 public:
221  sync_timer() noexcept
222  : timer_base()
223  {
224  k_timer_init(native_handle(), nullptr, nullptr);
225  }
226 };
227 
233 inline auto make_timer() noexcept
234 {
235  return sync_timer();
236 }
237 
245 template<class T_ExpireCallback>
246 inline auto make_timer(T_ExpireCallback&& ecb) noexcept
247 {
248  return basic_timer(std::forward<T_ExpireCallback>(ecb));
249 }
250 
259 template<class T_ExpireCallback, class T_StopCallback>
260 inline auto make_timer(T_ExpireCallback&& ecb, T_StopCallback&& scb) noexcept
261 {
262  return timer(std::forward<T_ExpireCallback>(ecb), std::forward<T_StopCallback>(scb));
263 }
264 
265 } // namespace zpp
266 
267 #endif // ZPP_INCLUDE_ZPP_TIMER_HPP
timer class with only an expire callback
Definition: timer.hpp:179
basic_timer(T_ExpireCallback ecb) noexcept
construct timer with an expire callback
Definition: timer.hpp:188
basic_timer()=delete
timer class with no callbacks used for syncing only
Definition: timer.hpp:216
sync_timer() noexcept
constuctor for the sync timer
Definition: timer.hpp:221
base class for the timer class
Definition: timer.hpp:24
timer_base(timer_base &&)=delete
timer_base() noexcept
Definition: timer.hpp:26
std::chrono::nanoseconds remaining_time() noexcept
Get remaining time.
Definition: timer.hpp:97
timer_base & operator=(const timer_base &)=delete
void start(const std::chrono::duration< T_Rep, T_Period > &duration) noexcept
Start a single shot timer with duration.
Definition: timer.hpp:59
void start(const std::chrono::duration< T_Rep1, T_Period1 > &duration, const std::chrono::duration< T_Rep2, T_Period2 > &period) noexcept
Start a timer with duration and period.
Definition: timer.hpp:45
void stop() noexcept
Stop the timer.
Definition: timer.hpp:69
timer_base & operator=(timer_base &&)=delete
auto sync() noexcept
sync with the timer
Definition: timer.hpp:87
~timer_base()
Destructor that stops the timer.
Definition: timer.hpp:33
auto status() noexcept
get the timer status
Definition: timer.hpp:79
auto native_handle() noexcept
Zephyr native handle.
Definition: timer.hpp:108
timer_base(const timer_base &)=delete
timer class with expire and stop callbacks
Definition: timer.hpp:129
timer()=delete
timer(T_ExpireCallback ecb, T_StopCallback scb) noexcept
construct timer with expire and stop callback
Definition: timer.hpp:139
constexpr k_timeout_t to_timeout(const std::chrono::duration< T_Rep, T_Period > &d) noexcept
convert a duration to tick
Definition: clock.hpp:88
auto make_timer() noexcept
create sync_timer object
Definition: timer.hpp:233