-
Notifications
You must be signed in to change notification settings - Fork 4
/
timer.c
92 lines (77 loc) · 1.82 KB
/
timer.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
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
// here we hook to timer 5 which is not used in any of the primary arduino pins
// its 16 bit and allows us a decent resolution
#include "timer.h"
// just 1 timer for the user
// we hook to timer 5
#define NUM_TIMERS 1
typedef struct Timer{
int timer_num;
uint16_t duration_ms;
TimerFn fn;
void* args;
} Timer;
static Timer timers[NUM_TIMERS];
void Timers_init(void){
memset(timers, 0, sizeof(timers));
for (int i=0; i<NUM_TIMERS; ++i)
timers[i].timer_num=i;
}
// creates a timer that has a duration of ms milliseconds
// bound to the device device
// each duration_ms the function timer_fn will be called
// with arguments timer args
Timer* Timer_create(char* device,
uint16_t duration_ms,
TimerFn timer_fn,
void* timer_args){
Timer* timer=0;
if (!strcmp(device,"timer_0"))
timer=timers;
else
return 0;
timer->duration_ms=duration_ms;
timer->timer_num=0;
timer->fn=timer_fn;
timer->args=timer_args;
return timer;
}
// stops and destroyes a timer
void Timer_destroy(struct Timer* timer){
Timer_stop(timer);
cli();
int timer_num=timer->timer_num;
memset(timer, 0, sizeof(Timer));
timer->timer_num=timer_num;
sei();
}
void _timer0_start(struct Timer* timer){
uint16_t ocrval=(uint16_t)(15.62*timer->duration_ms);
TCCR1A = 0;
TCCR1B = 0;
OCR1A = ocrval;
TCCR1B |= (1 << WGM12) | (1 << CS10) | (1 << CS12);
TIMSK1 |= (1 << OCIE1A);
}
// starts a timer
void Timer_start(struct Timer* timer){
cli();
if (timer->timer_num==0)
_timer0_start(timer);
sei();
}
// stops a timer
void Timer_stop(struct Timer* timer){
if (timer->timer_num!=0)
return;
cli();
TIMSK1 &= ~(1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect) {
TCNT1 = 0;
if(timers[0].fn)
(*timers[0].fn)(timers[0].args);
}