EV3RT CXX API Reference [English]
An RTOS-based development platform for LEGO Mindstorms EV3.
ev3cxx_time.h
1 #pragma once
2 
6 #include <kernel.h>
7 #include <t_syslog.h>
8 #include <t_stdlib.h>
9 
10 namespace ev3cxx {
11 
12 namespace detail {
13 
14 class us_counter_t {
15 public:
16  typedef SYSUTM time_type;
17  typedef ER error_type;
18 
19  us_counter_t()
20  :m_last_value(0)
21  {}
22 
23  time_type value() {
24  m_error = get_utm(&m_last_value);
25  return m_last_value;
26  }
27 
28  time_type operator()() { return value(); }
29 
30  operator bool() const { return is_ok(); }
31 
32  bool is_ok() const { return m_error == E_OK; }
33 
34  error_type error() const { return m_error; }
35 
36  error_type clear() {
37  error_type e = m_error;
38  m_error = E_OK;
39  return e;
40  }
41 private:
42  time_type m_last_value;
43  error_type m_error;
44 }; // class us_counter_t
45 
46 template <typename Timer>
47 void wait(Timer & timer, typename Timer::time_type time) {
48  typename Timer::time_type base = timer.value();
49  while (time > 0) {
50  typename Timer::time_type new_base = timer.value();
51  typename Timer::time_type difference = new_base - base;
52  if (time < difference)
53  break;
54  time -= difference;
55  base = new_base;
56  tslp_tsk(0);
57  }
58 }
59 
60 template <typename Timer, typename Process>
61 void wait(Timer & timer, typename Timer::time_type time, Process process) {
62  typename Timer::time_type base = timer.value();
63  while (time > 0) {
64  typename Timer::time_type new_base = timer.value();
65  typename Timer::time_type difference = new_base - base;
66  if (time < difference)
67  break;
68  time -= difference;
69  base = new_base;
70  process();
71  tslp_tsk(0);
72  }
73 }
74 
75 template <typename Timer, typename Process>
76 typename Timer::time_type wait(Timer & timer, typename Timer::time_type time, Process process, int) {
77  typename Timer::time_type base = timer.value();
78  if (time == 0)
79  for (;;) {
80  if (process())
81  return timer.value() - base;
82  tslp_tsk(0);
83  }
84  typename Timer::time_type base_time = base;
85  while (time > 0) {
86  typename Timer::time_type new_base = timer.value();
87  typename Timer::time_type difference = new_base - base;
88  if (time < difference)
89  return 0;
90  time -= difference;
91  base = new_base;
92  if (process()) {
93  typename Timer::time_type res = timer.value() - base_time;
94  return res == 0 ? 1 : res;
95  }
96  tslp_tsk(0);
97  }
98  return 0;
99 }
100 
101 template <typename Timer>
103 {
104 public:
105  typedef typename Timer::time_type time_type;
106 
107  stopwatch()
108  : m_timer(0), m_running(false)
109  {}
110 
111  explicit stopwatch(Timer & timer)
112  : m_timer(&timer), m_running(true)
113  {
114  this->clear();
115  }
116 
117  void init(Timer & timer) {
118  m_timer = &timer;
119  m_running = true;
120  m_base = m_timer->value();
121  }
122 
123  void init_stopped(Timer & timer) {
124  m_timer = &timer;
125  m_running = false;
126  m_base = 0;
127  }
128 
129  void clear() {
130  if (m_running)
131  m_base = m_timer->value();
132  else
133  m_base = 0;
134  }
135 
136  bool running() const {
137  return m_running;
138  }
139 
140  void cancel() {
141  m_running = false;
142  m_base = 0;
143  }
144 
145  void restart() {
146  m_running = true;
147  m_base = m_timer->value();
148  }
149 
150  void start() {
151  if (!m_running) {
152  m_base = m_timer->value() - m_base;
153  m_running = true;
154  }
155  }
156 
157  void stop() {
158  if (m_running) {
159  m_base = m_timer->value() - m_base;
160  m_running = false;
161  }
162  }
163 
164  time_type operator()() const { return this->get(); }
165 
166  time_type get() const {
167  if (m_running)
168  return m_timer->value() - m_base;
169  else
170  return m_base;
171  }
172 
173  void set(time_type value) {
174  if (m_running)
175  m_base = m_timer->value() - value;
176  else
177  m_base = value;
178  }
179 
180  void decrease(time_type time) {
181  if (m_running)
182  m_base += time;
183  else
184  m_base -= time;
185  }
186 
187 private:
188  Timer * m_timer;
189  volatile bool m_running;
190  volatile time_type m_base;
191 }; // class stopwatch
192 
193 template <typename Timer>
194 class timeout
195  : public stopwatch<Timer>
196 {
197 public:
198  typedef stopwatch<Timer> base_type;
199  typedef typename base_type::time_type time_type;
200 
201  timeout()
202  {}
203 
204  timeout(Timer & timer, time_type timeout)
205  : stopwatch<Timer>(timer), m_timeout(timeout)
206  {}
207 
208  void init(Timer & timer, time_type timeout) {
209  stopwatch<Timer>::init(timer);
210  m_timeout = timeout;
211  }
212 
213  void init_stopped(Timer & timer, time_type timeout) {
215  m_timeout = timeout;
216  }
217 
218  void force() {
219  this->set(m_timeout + 1);
220  }
221 
222  void ack() {
223  this->decrease(m_timeout);
224  }
225 
226  operator bool() const { return (*this)() > m_timeout; }
227 
228  void set_timeout(const time_type & value) {
229  m_timeout = value;
230  }
231 
232  time_type get_timeout() const { return m_timeout; }
233 
234  void reset(const time_type & new_timeout) {
235  this->clear();
236  m_timeout = new_timeout;
237  }
238 
239  time_type remaining() const { return *this ? 0 : (m_timeout - (*this)()); }
240 
241 private:
242  volatile time_type m_timeout;
243 }; // class timeout
244 
248 extern us_counter_t us_counter;
249 
250 } // namespace detail
251 
252 struct StopWatch
253  :detail::stopwatch<detail::us_counter_t>
254 {
255  StopWatch(const bool& run = true)
256  :detail::stopwatch<detail::us_counter_t>(detail::us_counter)
257  {
258  if (run)
259  return;
260  stop();
261  clear();
262  }
263 
264  bool isRunning()
265  {
266  return running();
267  }
268 
269  void reset(const bool& start = true)
270  {
271  if (start)
272  restart();
273  else
274  cancel();
275  }
276 
277  time_type getMs()
278  {
279  return get() / 1000;
280  }
281 
282  time_type getUs()
283  {
284  return get();
285  }
286 };
287 
288 struct Timeout
289  :detail::timeout<detail::us_counter_t>
290 {
291  Timeout(detail::timeout<detail::us_counter_t>::time_type timeout)
292  :detail::timeout<detail::us_counter_t>(detail::us_counter, timeout)
293  {
294  }
295 };
296 
297 extern void wait(detail::us_counter_t::time_type time);
298 
299 template <typename Process>
300 void wait(detail::us_counter_t::time_type time, Process process)
301 {
302  detail::wait(detail::us_counter, time, process);
303 }
304 
305 template <typename Process>
306 void wait(detail::us_counter_t::time_type time, Process process, int)
307 {
308  detail::wait(detail::us_counter, time, process, 0);
309 }
310 
311 extern void delayMs(const unsigned int& ms);
312 extern void delayUs(const unsigned int& us);
313 
314 extern detail::us_counter_t::time_type usec(detail::us_counter_t::time_type t);
315 extern detail::us_counter_t::time_type msec(detail::us_counter_t::time_type t);
316 extern detail::us_counter_t::time_type sec(detail::us_counter_t::time_type t);
317 
318 } // namespace ev3cxx
Definition: ev3cxx.h:35