-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmillis.c
172 lines (143 loc) · 3.32 KB
/
millis.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <util/atomic.h>
#include "millis.h"
#ifndef F_CPU
#error "F_CPU not defined!"
#endif
#if F_CPU < 256 || F_CPU >= 32640000
#error "Bad F_CPU setting (<256 or >=32640000)"
#endif
#ifndef MILLIS_TIMER
#error "Bad MILLIS_TIMER set"
#endif
// Decide what what prescaler and registers to use
#if MILLIS_TIMER == MILLIS_TIMER0
// Timer0
#if F_CPU > 16320000 // 16.32MHz - 65.28MHz
#define CLOCKSEL (_BV(CS20))
#define PRESCALER 256
#elif F_CPU > 2040000 // 2.04MHz - 16.32MHz
#define CLOCKSEL (_BV(CS01)|_BV(CS00))
#define PRESCALER 64
#elif F_CPU > 255 // 256Hz - 2.04MHz
#define CLOCKSEL (_BV(CS01))
#define PRESCALER 8
#endif
#define REG_TCCRA TCCR0A
#define REG_TCCRB TCCR0B
#define REG_TIMSK TIMSK0
#define REG_OCR OCR0A
#define BIT_WGM WGM01
#define BIT_OCIE OCIE0A
#define ISR_VECT TIMER0_COMPA_vect
#define pwr_enable() power_timer0_enable()
#define pwr_disable() power_timer0_disable()
#define SET_TCCRA() (REG_TCCRA = _BV(BIT_WGM))
#define SET_TCCRB() (REG_TCCRB = CLOCKSEL)
#elif MILLIS_TIMER == MILLIS_TIMER1
// Timer1
// 1KHz - 65.28MHz
#define CLOCKSEL (_BV(CS10))
#define PRESCALER 1
#define REG_TCCRA TCCR1A
#define REG_TCCRB TCCR1B
#define REG_TIMSK TIMSK1
#define REG_OCR OCR1A
#define BIT_WGM WGM12
#define BIT_OCIE OCIE1A
#define ISR_VECT TIMER1_COMPA_vect
#define pwr_enable() power_timer1_enable()
#define pwr_disable() power_timer1_disable()
#define SET_TCCRA() (REG_TCCRA = 0)
#define SET_TCCRB() (REG_TCCRB = _BV(BIT_WGM)|CLOCKSEL)
#elif MILLIS_TIMER == MILLIS_TIMER2
// Timer2
#if F_CPU > 16320000 // 16.32MHz - 32.64MHz
#define CLOCKSEL (_BV(CS22)|_BV(CS20))
#define PRESCALER 128
#elif F_CPU > 8160000 // 8.16MHz - 16.32MHz
#define CLOCKSEL (_BV(CS22))
#define PRESCALER 64
#elif F_CPU > 2040000 // 2.04MHz - 8.16MHz
#define CLOCKSEL (_BV(CS21)|_BV(CS20))
#define PRESCALER 32
#elif F_CPU > 255 // 256Hz - 2.04MHz
#define CLOCKSEL (_BV(CS21))
#define PRESCALER 8
#endif
#define REG_TCCRA TCCR2A
#define REG_TCCRB TCCR2B
#define REG_TIMSK TIMSK2
#define REG_OCR OCR2A
#define BIT_WGM WGM21
#define BIT_OCIE OCIE2A
#define ISR_VECT TIMER2_COMPA_vect
#define pwr_enable() power_timer2_enable()
#define pwr_disable() power_timer2_disable()
#define SET_TCCRA() (REG_TCCRA = _BV(BIT_WGM))
#define SET_TCCRB() (REG_TCCRB = CLOCKSEL)
#else
#error "Bad MILLIS_TIMER set"
#endif
static volatile millis_t milliseconds;
// Initialise library
void millis_init()
{
// Timer settings
SET_TCCRA();
SET_TCCRB();
REG_TIMSK = _BV(BIT_OCIE);
REG_OCR = ((F_CPU / PRESCALER) / 1000);
}
// Get current milliseconds
millis_t millis_get()
{
millis_t ms;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
ms = milliseconds;
}
return ms;
}
// Turn on timer and resume time keeping
void millis_resume()
{
pwr_enable();
REG_TIMSK |= _BV(BIT_OCIE);
}
// Pause time keeping and turn off timer to save power
void millis_pause()
{
REG_TIMSK &= ~_BV(BIT_OCIE);
pwr_disable();
}
// Reset milliseconds count to 0
void millis_reset()
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
milliseconds = 0;
}
}
// Add time
void millis_add(millis_t ms)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
milliseconds += ms;
}
}
// Subtract time
void millis_subtract(millis_t ms)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
milliseconds -= ms;
}
}
ISR(ISR_VECT)
{
++milliseconds;
}