-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclock.c
143 lines (127 loc) · 3.25 KB
/
clock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "clock.h"
static volatile uint32_t clock_ticks;
static volatile uint32_t stopwatch_counter;
/**
* @brief Get the current clock ticks count.
*
* This is the total number of ticks that the clock has been running since the
* last reset.
*
* @note Clock ticks are incemented with the `clock_tick` function.
*
* @return The current clock ticks count.
*/
uint32_t get_clock_ticks(void)
{
return clock_ticks;
}
/**
* @brief Update system clock incrementing the clock tick counter.
*/
void clock_tick(void)
{
clock_ticks++;
}
/**
* @brief Sleep (i.e.: do nothing) for a number of ticks.
*
* @param[in] ticks Sleep period, in ticks.
*
* @note Clock ticks are incemented with the `clock_tick` function.
*/
void sleep_ticks(uint32_t ticks)
{
uint32_t awake = clock_ticks + ticks;
while (awake > clock_ticks)
;
}
/**
* @brief Sleep (i.e.: do nothing) for a number of seconds.
*
* @param[in] seconds Sleep duration, in seconds.
*/
void sleep_seconds(float seconds)
{
sleep_ticks((uint32_t)(seconds * SYSTICK_FREQUENCY_HZ));
}
/**
* @brief Start the stopwatch to measure elapsed time.
*
* To be used with `stopwatch_stop()` function.
*/
void stopwatch_start(void)
{
stopwatch_counter = read_cycle_counter();
}
/**
* @brief Return the elapsed seconds since `stopwatch_start()` was called.
*/
float stopwatch_stop(void)
{
return (float)(read_cycle_counter() - stopwatch_counter) /
(float)SYSCLK_FREQUENCY_HZ;
}
/**
* @brief Sleep for a number of microseconds.
*
* @param[in] us Sleep period, in microseconds.
*/
void sleep_us(uint32_t us)
{
uint32_t initial_cycles = read_cycle_counter();
uint32_t sleep_cycles = (uint32_t)(
SYSCLK_FREQUENCY_HZ * ((float)us / (float)MICROSECONDS_PER_SECOND));
while (read_cycle_counter() - initial_cycles <= sleep_cycles)
;
}
/**
* @brief Sleep for a number of microseconds since `cycle_counter`.
*
* @param[in] cycle_counter Cycle counter value used as starting point.
* @param[in] us Sleep period, in microseconds.
*/
void sleep_us_after(uint32_t cycle_counter, uint32_t us)
{
uint32_t sleep_cycles = (uint32_t)(
SYSCLK_FREQUENCY_HZ * ((float)us / (float)MICROSECONDS_PER_SECOND));
while (read_cycle_counter() - cycle_counter <= sleep_cycles)
;
}
/**
* @brief Execute a function each period during a defined time span.
*
* @param[in] period Execution period, in ticks.
* @param[in] function Function to execute.
* @param[in] during Duration of the time span, in ticks.
*/
void each(uint32_t period, void (*function)(void), uint32_t during)
{
uint32_t ticks_initial;
uint32_t ticks_current;
ticks_initial = get_clock_ticks();
ticks_current = ticks_initial;
while (ticks_current - ticks_initial < during) {
if (ticks_current % period == 0)
function();
sleep_ticks(1);
ticks_current = get_clock_ticks();
}
}
/**
* @brief Wait until the given function returns true, or timeout.
*
* @param[in] timeout Timeout duration, in ticks.
* @param[in] function Function to execute.
*
* @return False if the timeout occurred before the function returned true.
*/
bool wait_until(bool (*function)(void), uint32_t timeout)
{
uint32_t ticks_initial;
ticks_initial = get_clock_ticks();
while (get_clock_ticks() - ticks_initial < timeout) {
if (function())
return true;
}
return false;
}