2222
2323#include "wiring_private.h"
2424
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
2626// 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 ;
2929
3030uint32_t F_CPU_CORRECTED = F_CPU ;
3131
32- // the whole number of milliseconds per timerb0 overflow
32+ // the whole number of milliseconds per timer overflow
3333uint16_t millis_inc ;
3434
35- // the fractional number of milliseconds per timerb0 overflow
35+ // the fractional number of milliseconds per timer overflow
3636uint16_t fract_inc ;
3737#define FRACT_MAX (1000)
3838
39- // whole number of microseconds per timerb0 tick
39+ // whole number of microseconds per timer tick
4040
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 ;
4444
4545inline uint16_t clockCyclesPerMicrosecondComp (uint32_t clk ){
4646 return ( (clk ) / 1000000L );
@@ -58,12 +58,31 @@ inline unsigned long microsecondsToClockCycles(unsigned long microseconds){
5858 return ( microseconds * clockCyclesPerMicrosecond () );
5959}
6060
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 )
6173ISR (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
6281{
6382 // copy these to local variables so they can be stored in registers
6483 // (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 ;
6786
6887 m += millis_inc ;
6988 f += fract_inc ;
@@ -73,12 +92,12 @@ ISR(TCB0_INT_vect)
7392 m += 1 ;
7493 }
7594
76- timerb0_fract = f ;
77- timerb0_millis = m ;
78- timerb0_overflow_count ++ ;
95+ timer_fract = f ;
96+ timer_millis = m ;
97+ timer_overflow_count ++ ;
7998
8099 /* Clear flag */
81- TCB0 . INTFLAGS = TCB_CAPT_bm ;
100+ _timer -> INTFLAGS = TCB_CAPT_bm ;
82101}
83102
84103unsigned long millis ()
@@ -89,7 +108,7 @@ unsigned long millis()
89108 // inconsistent value (e.g. in the middle of a write to timer0_millis)
90109 uint8_t status = SREG ;
91110 cli ();
92- m = timerb0_millis ;
111+ m = timer_millis ;
93112
94113 SREG = status ;
95114
@@ -105,22 +124,22 @@ unsigned long micros() {
105124 cli ();
106125
107126 /* 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 ;
110129
111130 /* If the timer overflow flag is raised, we just missed it,
112131 increment to account for it, & read new ticks */
113- if (TCB0 . INTFLAGS & TCB_CAPT_bm ){
132+ if (_timer -> INTFLAGS & TCB_CAPT_bm ){
114133 overflows ++ ;
115- ticks = TCB0 . CNTL ;
134+ ticks = _timer -> CNTL ;
116135 }
117136
118137 /* Restore state */
119138 SREG = status ;
120139
121140 /* 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 ));
124143 return microseconds ;
125144}
126145
@@ -355,27 +374,27 @@ void init()
355374
356375 setup_timers ();
357376
358- /********************* TCB0 for system time tracking **************************/
377+ /********************* TIMER for system time tracking **************************/
359378
360379 /* 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 ;
363382
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 ));
366385
367386 /* Default Periodic Interrupt Mode */
368387 /* TOP value for overflow every 1024 clock cycles */
369- TCB0 . CCMP = TIME_TRACKING_TIMER_PERIOD ;
388+ _timer -> CCMP = TIME_TRACKING_TIMER_PERIOD ;
370389
371- /* Enable TCB0 interrupt */
372- TCB0 . INTCTRL |= TCB_CAPT_bm ;
390+ /* Enable timer interrupt */
391+ _timer -> INTCTRL |= TCB_CAPT_bm ;
373392
374393 /* Clock selection -> same as TCA (F_CPU/64 -- 250kHz) */
375- TCB0 . CTRLA = TCB_CLKSEL_CLKTCA_gc ;
394+ _timer -> CTRLA = TCB_CLKSEL_CLKTCA_gc ;
376395
377396 /* 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 */
379398
380399/*************************** ENABLE GLOBAL INTERRUPTS *************************/
381400
0 commit comments