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