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 | } |