22
22
23
23
#include "wiring_private.h"
24
24
25
- // the prescaler is set so that timerb0 ticks every 64 clock cycles, and the
25
+ // the prescaler is set so that timer ticks every 64 clock cycles, and the
26
26
// the overflow handler is called every 256 ticks.
27
- volatile uint16_t microseconds_per_timerb0_overflow ;
28
- volatile uint16_t microseconds_per_timerb0_tick ;
27
+ volatile uint16_t microseconds_per_timer_overflow ;
28
+ volatile uint16_t microseconds_per_timer_tick ;
29
29
30
30
uint32_t F_CPU_CORRECTED = F_CPU ;
31
31
32
- // the whole number of milliseconds per timerb0 overflow
32
+ // the whole number of milliseconds per timer overflow
33
33
uint16_t millis_inc ;
34
34
35
- // the fractional number of milliseconds per timerb0 overflow
35
+ // the fractional number of milliseconds per timer overflow
36
36
uint16_t fract_inc ;
37
37
#define FRACT_MAX (1000)
38
38
39
- // whole number of microseconds per timerb0 tick
39
+ // whole number of microseconds per timer tick
40
40
41
- volatile uint32_t timerb0_overflow_count = 0 ;
42
- volatile uint32_t timerb0_millis = 0 ;
43
- static uint16_t timerb0_fract = 0 ;
41
+ volatile uint32_t timer_overflow_count = 0 ;
42
+ volatile uint32_t timer_millis = 0 ;
43
+ static uint16_t timer_fract = 0 ;
44
44
45
45
inline uint16_t clockCyclesPerMicrosecondComp (uint32_t clk ){
46
46
return ( (clk ) / 1000000L );
@@ -58,12 +58,31 @@ inline unsigned long microsecondsToClockCycles(unsigned long microseconds){
58
58
return ( microseconds * clockCyclesPerMicrosecond () );
59
59
}
60
60
61
+ static volatile TCB_t * _timer =
62
+ #if defined(MILLIS_USE_TIMERB0 )
63
+ & TCB0 ;
64
+ #elif defined(MILLIS_USE_TIMERB1 )
65
+ & TCB1 ;
66
+ #elif defined(MILLIS_USE_TIMERB2 )
67
+ & TCB2 ;
68
+ #else
69
+ & TCB3 ;
70
+ #endif
71
+
72
+ #if defined(MILLIS_USE_TIMERB0 )
61
73
ISR (TCB0_INT_vect )
74
+ #elif defined(MILLIS_USE_TIMERB1 )
75
+ ISR (TCB1_INT_vect )
76
+ #elif defined(MILLIS_USE_TIMERB2 )
77
+ ISR (TCB2_INT_vect )
78
+ #else
79
+ ISR (TCB3_INT_vect )
80
+ #endif
62
81
{
63
82
// copy these to local variables so they can be stored in registers
64
83
// (volatile variables must be read from memory on every access)
65
- uint32_t m = timerb0_millis ;
66
- uint16_t f = timerb0_fract ;
84
+ uint32_t m = timer_millis ;
85
+ uint16_t f = timer_fract ;
67
86
68
87
m += millis_inc ;
69
88
f += fract_inc ;
@@ -73,12 +92,12 @@ ISR(TCB0_INT_vect)
73
92
m += 1 ;
74
93
}
75
94
76
- timerb0_fract = f ;
77
- timerb0_millis = m ;
78
- timerb0_overflow_count ++ ;
95
+ timer_fract = f ;
96
+ timer_millis = m ;
97
+ timer_overflow_count ++ ;
79
98
80
99
/* Clear flag */
81
- TCB0 . INTFLAGS = TCB_CAPT_bm ;
100
+ _timer -> INTFLAGS = TCB_CAPT_bm ;
82
101
}
83
102
84
103
unsigned long millis ()
@@ -89,7 +108,7 @@ unsigned long millis()
89
108
// inconsistent value (e.g. in the middle of a write to timer0_millis)
90
109
uint8_t status = SREG ;
91
110
cli ();
92
- m = timerb0_millis ;
111
+ m = timer_millis ;
93
112
94
113
SREG = status ;
95
114
@@ -105,22 +124,22 @@ unsigned long micros() {
105
124
cli ();
106
125
107
126
/* Get current number of overflows and timer count */
108
- overflows = timerb0_overflow_count ;
109
- ticks = TCB0 . CNTL ;
127
+ overflows = timer_overflow_count ;
128
+ ticks = _timer -> CNTL ;
110
129
111
130
/* If the timer overflow flag is raised, we just missed it,
112
131
increment to account for it, & read new ticks */
113
- if (TCB0 . INTFLAGS & TCB_CAPT_bm ){
132
+ if (_timer -> INTFLAGS & TCB_CAPT_bm ){
114
133
overflows ++ ;
115
- ticks = TCB0 . CNTL ;
134
+ ticks = _timer -> CNTL ;
116
135
}
117
136
118
137
/* Restore state */
119
138
SREG = status ;
120
139
121
140
/* Return microseconds of up time (resets every ~70mins) */
122
- microseconds = ((overflows * microseconds_per_timerb0_overflow )
123
- + (ticks * microseconds_per_timerb0_tick ));
141
+ microseconds = ((overflows * microseconds_per_timer_overflow )
142
+ + (ticks * microseconds_per_timer_tick ));
124
143
return microseconds ;
125
144
}
126
145
@@ -355,27 +374,27 @@ void init()
355
374
356
375
setup_timers ();
357
376
358
- /********************* TCB0 for system time tracking **************************/
377
+ /********************* TIMER for system time tracking **************************/
359
378
360
379
/* Calculate relevant time tracking values */
361
- microseconds_per_timerb0_overflow = clockCyclesToMicroseconds (TIME_TRACKING_CYCLES_PER_OVF );
362
- microseconds_per_timerb0_tick = microseconds_per_timerb0_overflow /TIME_TRACKING_TIMER_PERIOD ;
380
+ microseconds_per_timer_overflow = clockCyclesToMicroseconds (TIME_TRACKING_CYCLES_PER_OVF );
381
+ microseconds_per_timer_tick = microseconds_per_timer_overflow /TIME_TRACKING_TIMER_PERIOD ;
363
382
364
- millis_inc = microseconds_per_timerb0_overflow / 1000 ;
365
- fract_inc = ((microseconds_per_timerb0_overflow % 1000 ));
383
+ millis_inc = microseconds_per_timer_overflow / 1000 ;
384
+ fract_inc = ((microseconds_per_timer_overflow % 1000 ));
366
385
367
386
/* Default Periodic Interrupt Mode */
368
387
/* TOP value for overflow every 1024 clock cycles */
369
- TCB0 . CCMP = TIME_TRACKING_TIMER_PERIOD ;
388
+ _timer -> CCMP = TIME_TRACKING_TIMER_PERIOD ;
370
389
371
- /* Enable TCB0 interrupt */
372
- TCB0 . INTCTRL |= TCB_CAPT_bm ;
390
+ /* Enable timer interrupt */
391
+ _timer -> INTCTRL |= TCB_CAPT_bm ;
373
392
374
393
/* Clock selection -> same as TCA (F_CPU/64 -- 250kHz) */
375
- TCB0 . CTRLA = TCB_CLKSEL_CLKTCA_gc ;
394
+ _timer -> CTRLA = TCB_CLKSEL_CLKTCA_gc ;
376
395
377
396
/* Enable & start */
378
- TCB0 . CTRLA |= TCB_ENABLE_bm ; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */
397
+ _timer -> CTRLA |= TCB_ENABLE_bm ; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */
379
398
380
399
/*************************** ENABLE GLOBAL INTERRUPTS *************************/
381
400
0 commit comments