Subversion Repositories HomeAutomation

Rev

Rev 1695 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
361 andfri 1
/**
2
 * Timebase software module. Utilizes timer0 to provide a 32bit timebase with
3
 * millisecond-granularity to the application.
4
 *
5
 * @author  Martin Thomas
6
 * @author  Jimmy Myhrman
7
 *
8
 * @date    2006-11-19
9
 */
10
 
11
/*-----------------------------------------------------------------------------
12
 * Includes
13
 *---------------------------------------------------------------------------*/
14
#include <inttypes.h>
15
#include <avr/io.h>
16
#include <avr/interrupt.h>
17
 
18
#include <config.h>
19
#include <drivers/timer/timebase.h>
20
 
21
 
22
/*-----------------------------------------------------------------------------
23
 * Globals
24
 *---------------------------------------------------------------------------*/
25
volatile uint32_t gMilliSecTick;
26
 
27
 
28
/*-----------------------------------------------------------------------------
29
 * Interrupt Service Routines
30
 *---------------------------------------------------------------------------*/
408 andfri 31
#if defined(TIMEBASE_NEW_IMPLEMENTATION)
1468 arune 32
#if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
361 andfri 33
#if defined(TIMER2)
408 andfri 34
ISR(TIMER2_COMPA_vect) {
35
#else //!defined(TIMER2)
36
ISR(TIMER0_COMPA_vect) {
37
#endif //defined(TIMER2)
1468 arune 38
#else //!defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
408 andfri 39
ISR(TIMER2_COMP_vect) {
1468 arune 40
#endif //defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
408 andfri 41
    gMilliSecTick++;
42
}
43
 
44
#else //!defined(TIMEBASE_NEW_IMPLEMENTATION)
45
 
46
#if defined(TIMER2)
1695 arune 47
ISR(TIMER2_OVF_vect) {
361 andfri 48
    TCNT2 = TIMEBASE_RELOAD;
49
    gMilliSecTick++;
50
}
51
#else
1695 arune 52
ISR(TIMER0_OVF_vect) {
361 andfri 53
    TCNT0 = TIMEBASE_RELOAD;
54
    gMilliSecTick++;
55
}
56
#endif
57
 
408 andfri 58
#endif //defined(TIMEBASE_NEW_IMPLEMENTATION)
361 andfri 59
 
408 andfri 60
 
361 andfri 61
/*-----------------------------------------------------------------------------
62
 * Public Functions
63
 *---------------------------------------------------------------------------*/
64
 
65
/**
66
 * Initializes the timebase. The hardware timer interrupt source will be
67
 * enabled, but global interrupts need to be enabled by the application.
68
 */
69
void Timebase_Init() {
408 andfri 70
#if defined(TIMEBASE_NEW_IMPLEMENTATION)
71
 
361 andfri 72
#if defined(TIMER2)
73
    #if defined(__AVR_ATmega8__)
408 andfri 74
    TCCR2 = (1<<WGM21); // CTC mode
361 andfri 75
    #if TIMEBASE_PRESCALE == 64
76
    TCCR2 = (1<<CS22);  // prescaler: 64
77
    #elif TIMEBASE_PRESCALE == 256
78
    TCCR2 = (1<<CS22) | (1<<CS21); // prescaler: 256
79
    #endif
408 andfri 80
    OCR2 = TIMEBASE_HITS_PER_1MS; // set timer period
81
    TIFR  |= (1<<OCF2);  // clear ouput compare match flag
82
    TIMSK |= (1<<OCIE2); // enable output compare match interrupt
83
    #endif
84
 
1468 arune 85
    #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
408 andfri 86
    TCCR2A = (1<<WGM21); // CTC mode
87
    #if TIMEBASE_PRESCALE == 64
88
    TCCR2B = (1<<CS22); // prescaler: 64
89
    #elif TIMEBASE_PRESCALE == 256
90
    TCCR2B = (1<<CS22)|(1<<CS21);               // prescaler: 256
91
    #endif
92
    OCR2A = TIMEBASE_HITS_PER_1MS; // set timer period
93
    TIFR2  |= (1<<OCF2A);  // clear ouput compare match flag
415 noddan 94
    TIMSK2 |= (1<<OCIE2A); // enable output compare match interrupt
408 andfri 95
    #endif
96
#else /* Use timer0 */
97
    #if defined(__AVR_ATmega8__)
98
    #error TIMER0 not supported in ATmega8 with TIMEBASE_NEW_IMPLEMENTATION set!
99
    #endif
100
 
1468 arune 101
    #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
408 andfri 102
    TCCR0A = (1<<WGM01); // CTC mode
103
    #if TIMEBASE_PRESCALE == 64
104
    TCCR0B = (1<<CS01) | (1<<CS00); // prescaler: 64
105
    #elif TIMEBASE_PRESCALE == 256
106
    TCCR0B = (1<<CS02);             // prescaler: 256
107
    #endif
108
    OCR0A = TIMEBASE_HITS_PER_1MS; // set timer period
109
    TIFR0  |= (1<<OCF0A);  // clear ouput compare match flag
492 arune 110
    TIMSK0 |= (1<<OCIE0A); // enable output compare match interrupt
408 andfri 111
    #endif
112
#endif
113
 
114
 
115
#else //!defined(TIMEBASE_NEW_IMPLEMENTATION)
116
 
117
#if defined(TIMER2)
118
    #if defined(__AVR_ATmega8__)
119
    #if TIMEBASE_PRESCALE == 64
120
    TCCR2 = (1<<CS22);  // prescaler: 64
121
    #elif TIMEBASE_PRESCALE == 256
122
    TCCR2 = (1<<CS22) | (1<<CS21); // prescaler: 256
123
    #endif
361 andfri 124
    TCNT2 = TIMEBASE_RELOAD; // set initial reload-value
125
    TIFR  |= (1<<TOV2);  // clear overflow int.
126
    TIMSK |= (1<<TOIE2); // enable overflow-interrupt
127
    #endif
128
 
1468 arune 129
    #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
361 andfri 130
    #if TIMEBASE_PRESCALE == 64
131
    TCCR2B = (1<<CS22); // prescaler: 64
132
    #elif TIMEBASE_PRESCALE == 256
133
    TCCR2B = (1<<CS22)|(1<<CS21);               // prescaler: 256
134
    #endif
135
    TCNT2 = TIMEBASE_RELOAD; // set initial reload-value
136
    TIFR2  |= (1<<TOV2);  // clear overflow int.
137
    TIMSK2 |= (1<<TOIE2); // enable overflow-interrupt
138
    #endif
139
#else /* Use timer0 */
140
    #if defined(__AVR_ATmega8__)
141
    #if TIMEBASE_PRESCALE == 64
142
    TCCR0 = (1<<CS01) | (1<<CS00);  // prescaler: 64
143
    #elif TIMEBASE_PRESCALE == 256
144
    TCCR0 = (1<<CS02);              // prescaler: 256
145
    #endif
146
    TCNT0 = TIMEBASE_RELOAD; // set initial reload-value
147
    TIFR  |= (1<<TOV0);  // clear overflow int.
148
    TIMSK |= (1<<TOIE0); // enable overflow-interrupt
149
    #endif
150
 
2289 arune 151
    #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega64C1__)
361 andfri 152
    #if TIMEBASE_PRESCALE == 64
153
    TCCR0B = (1<<CS01) | (1<<CS00); // prescaler: 64
154
    #elif TIMEBASE_PRESCALE == 256
155
    TCCR0B = (1<<CS02);             // prescaler: 256
156
    #endif
157
    TCNT0 = TIMEBASE_RELOAD; // set initial reload-value
158
    TIFR0  |= (1<<TOV0);  // clear overflow int.
159
    TIMSK0 |= (1<<TOIE0); // enable overflow-interrupt
160
    #endif
161
#endif
408 andfri 162
 
163
#endif //defined(TIMEBASE_NEW_IMPLEMENTATION)
361 andfri 164
}
165
 
166
 
167
/**
168
 * Reads the current time.
169
 *
170
 * @return
171
 *      The current time in milliseconds (32bit value).
172
 */
173
uint32_t Timebase_CurrentTime(void) {
174
    uint8_t sreg;
362 andfri 175
    uint32_t res;
361 andfri 176
    sreg=SREG;
177
    cli();
178
    res = gMilliSecTick;
179
    SREG=sreg;
180
    return res;
181
}
182
 
183
 
184
/**
185
 * Checks how much time has passed since a given timestamp.
186
 *
187
 * @param t0
188
 *      The timestamp.
189
 * @return
190
 *      Number of milliseconds that have passed since t0.
191
 */
192
uint32_t Timebase_PassedTimeMillis(uint32_t t0) {
193
    uint8_t sreg;
362 andfri 194
    uint32_t res;
361 andfri 195
    sreg=SREG;
196
    cli();
362 andfri 197
    res = (uint32_t)(gMilliSecTick-t0);
361 andfri 198
    SREG=sreg;
199
    return res;
200
}