]>
Commit | Line | Data |
---|---|---|
4307b86a | 1 | /* $Id: timers.c,v 1.2 2010/07/25 20:40:44 simimeie Exp $ |
10ee5c5d | 2 | * Functions for timing. |
3 | * This mainly allows you to get a timestamp value | |
4 | */ | |
5 | ||
6 | #include <avr/io.h> | |
7 | #include <avr/interrupt.h> | |
8 | #include "timers.h" | |
9 | ||
10 | /* Internal ticks */ | |
11 | static volatile uint16_t ticks = 0; | |
12 | ||
4307b86a | 13 | void ledpwm_TIMER1OVF_hook(void); |
10ee5c5d | 14 | |
15 | /* Executes every 65536 cpu cycles when the timer overflows */ | |
16 | ISR(TIMER1_OVF_vect) | |
17 | { | |
18 | ticks++; | |
4307b86a | 19 | ledpwm_TIMER1OVF_hook(); |
10ee5c5d | 20 | } |
21 | ||
22 | uint16_t getticks(void) | |
23 | { | |
24 | uint16_t res; | |
25 | cli(); | |
26 | res = ticks; | |
27 | sei(); | |
28 | return res; | |
29 | } | |
30 | ||
31 | uint16_t getticks_noirq(void) | |
32 | { | |
33 | return ticks; | |
34 | } | |
35 | ||
36 | struct timestamp gettimestamp(void) | |
37 | { | |
38 | uint16_t cou1, cou2, tick1; | |
39 | struct timestamp res; | |
40 | /* Low byte must be read first for 16bit registers */ | |
41 | cou1 = TCNT1L; | |
42 | cou1 |= (uint16_t)(TCNT1H) << 8; | |
43 | tick1 = getticks(); /* enables interrupts! */ | |
44 | cou2 = TCNT1L; | |
45 | cou2 |= (uint16_t)(TCNT1H) << 8; | |
46 | if (cou1 > cou2) { /* An overflow occured in between */ | |
47 | /* get new ticks value - we could already have it, but we do not know | |
48 | * for sure. If we get another one now, we do - because there is no | |
49 | * way we're going to need another 65k cpu cycles. */ | |
50 | res.ticks = getticks(); | |
51 | } else { /* no overflow. */ | |
52 | res.ticks = tick1; | |
53 | } | |
54 | res.partticks = cou2; | |
55 | return res; | |
56 | } | |
57 | ||
58 | struct timestamp gettimestamp_noirq(void) | |
59 | { | |
60 | uint16_t cou1, cou2; uint8_t ovf; | |
61 | struct timestamp res; | |
62 | /* Low byte must be read first for 16bit registers */ | |
63 | cou1 = TCNT1L; | |
64 | cou1 |= (uint16_t)(TCNT1H) << 8; | |
65 | /* Check if there is an overflow pending */ | |
66 | ovf = TIFR1 & _BV(TOV1); | |
67 | if (ovf) { | |
68 | /* Overflow pending, reread the counter to be sure */ | |
69 | cou2 = TCNT1L; | |
70 | cou2 |= (uint16_t)(TCNT1H) << 8; | |
71 | res.ticks = ticks + 1; | |
72 | res.partticks = cou2; | |
73 | } else { | |
74 | res.ticks = ticks; | |
75 | res.partticks = cou1; | |
76 | } | |
77 | return res; | |
78 | } | |
79 | ||
80 | void timers_init(void) | |
81 | { | |
82 | /* Enable counter1, no prescaling (1 increment per clock cycle!) */ | |
83 | TCCR1B |= _BV(CS10); | |
84 | /* Enable interrupt when timer overflows (at 65536) */ | |
85 | TIMSK1 |= _BV(TOIE1); | |
86 | } |