forked from macano953/uledd
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimer.c
More file actions
121 lines (92 loc) · 2.11 KB
/
timer.c
File metadata and controls
121 lines (92 loc) · 2.11 KB
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
#include <time.h>
#include <stdbool.h>
#include <libubox/list.h>
#include <libubox/uloop.h>
#include "log.h"
#include "timer.h"
static int singular_timer_interval;
static struct uloop_timeout singular_timer;
static struct list_head timers = LIST_HEAD_INIT(timers);
static int tv_diff(struct timeval *t1, struct timeval *t2)
{
return
(t1->tv_sec - t2->tv_sec) * 1000 +
(t1->tv_usec - t2->tv_usec) / 1000;
}
static void led_timer_gettime(struct timeval *tv)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
static void led_process_timers()
{
struct timeval tv;
struct led_timer *t;
led_timer_gettime(&tv);
while (!list_empty(&timers)) {
t = list_first_entry(&timers, struct led_timer, list);
if (tv_diff(&t->time, &tv) > 0)
break;
led_timer_cancel(t);
if (t->cb)
t->cb(t);
}
}
static void singular_timer_cb(struct uloop_timeout *t)
{
led_process_timers();
uloop_timeout_set(&singular_timer, singular_timer_interval);
}
int led_timer_add(struct led_timer *t)
{
struct led_timer *tmp;
struct list_head *h = &timers;
if (t->pending)
return -1;
list_for_each_entry(tmp, &timers, list) {
if (tv_diff(&tmp->time, &t->time) > 0) {
h = &tmp->list;
break;
}
}
list_add_tail(&t->list, h);
t->pending = true;
return 0;
}
int led_timer_set(struct led_timer *t, int msecs)
{
struct timeval *time = &t->time;
if (t->pending)
led_timer_cancel(t);
led_timer_gettime(time);
time->tv_sec += msecs / 1000;
time->tv_usec += (msecs % 1000) * 1000;
if (time->tv_usec > 1000000) {
time->tv_sec++;
time->tv_usec -= 1000000;
}
return led_timer_add(t);
}
int led_timer_cancel(struct led_timer *t)
{
if (!t->pending)
return -1;
list_del(&t->list);
t->pending = false;
return 0;
}
void led_timers_init(int tick_interval)
{
singular_timer.cb = singular_timer_cb;
singular_timer_interval = tick_interval;
uloop_timeout_set(&singular_timer, tick_interval);
}
void led_timers_done()
{
struct led_timer *t, *tmp;
uloop_timeout_cancel(&singular_timer);
list_for_each_entry_safe(t, tmp, &timers, list)
led_timer_cancel(t);
}