mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-27 21:54:30 +01:00
Optimizing the timer0 overflow handler (for millis()), based on work by WestFW and help from mikalhart. Increasing precision of math constants.
This commit is contained in:
parent
60ad594d7b
commit
a2b3da7698
@ -24,32 +24,53 @@
|
|||||||
|
|
||||||
#include "wiring_private.h"
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
|
||||||
|
// the overflow handler is called every 256 ticks.
|
||||||
|
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
|
||||||
|
|
||||||
|
// the whole number of milliseconds per timer0 overflow
|
||||||
|
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
|
||||||
|
|
||||||
|
// the fractional number of milliseconds per timer0 overflow. we shift right
|
||||||
|
// by three to fit these numbers into a byte. (for the clock speeds we care
|
||||||
|
// about - 8 and 16 MHz - this doesn't lose precision.)
|
||||||
|
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
|
||||||
|
#define FRACT_MAX (1000 >> 3)
|
||||||
|
|
||||||
volatile unsigned long timer0_overflow_count = 0;
|
volatile unsigned long timer0_overflow_count = 0;
|
||||||
volatile unsigned long timer0_clock_cycles = 0;
|
|
||||||
volatile unsigned long timer0_millis = 0;
|
volatile unsigned long timer0_millis = 0;
|
||||||
|
static unsigned char timer0_fract = 0;
|
||||||
|
|
||||||
SIGNAL(TIMER0_OVF_vect)
|
SIGNAL(TIMER0_OVF_vect)
|
||||||
{
|
{
|
||||||
timer0_overflow_count++;
|
// copy these to local variables so they can be stored in registers
|
||||||
// timer 0 prescale factor is 64 and the timer overflows at 256
|
// (volatile variables must be read from memory on every access)
|
||||||
timer0_clock_cycles += 64UL * 256UL;
|
unsigned long m = timer0_millis;
|
||||||
while (timer0_clock_cycles > clockCyclesPerMicrosecond() * 1000UL) {
|
unsigned char f = timer0_fract;
|
||||||
timer0_clock_cycles -= clockCyclesPerMicrosecond() * 1000UL;
|
|
||||||
timer0_millis++;
|
m += MILLIS_INC;
|
||||||
|
f += FRACT_INC;
|
||||||
|
if (f >= FRACT_MAX) {
|
||||||
|
f -= FRACT_MAX;
|
||||||
|
m += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer0_fract = f;
|
||||||
|
timer0_millis = m;
|
||||||
|
timer0_overflow_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long millis()
|
unsigned long millis()
|
||||||
{
|
{
|
||||||
unsigned long m;
|
unsigned long m;
|
||||||
uint8_t oldSREG = SREG;
|
uint8_t oldSREG = SREG;
|
||||||
|
|
||||||
// disable interrupts while we read timer0_millis or we might get an
|
// disable interrupts while we read timer0_millis or we might get an
|
||||||
// inconsistent value (e.g. in the middle of the timer0_millis++)
|
// inconsistent value (e.g. in the middle of a write to timer0_millis)
|
||||||
cli();
|
cli();
|
||||||
m = timer0_millis;
|
m = timer0_millis;
|
||||||
SREG = oldSREG;
|
SREG = oldSREG;
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ extern "C"{
|
|||||||
#define true 0x1
|
#define true 0x1
|
||||||
#define false 0x0
|
#define false 0x0
|
||||||
|
|
||||||
#define PI 3.14159265
|
#define PI 3.1415926535897932384626433832795
|
||||||
#define HALF_PI 1.57079
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
#define TWO_PI 6.283185
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
#define DEG_TO_RAD 0.01745329
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
#define RAD_TO_DEG 57.2957786
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
|
||||||
#define SERIAL 0x0
|
#define SERIAL 0x0
|
||||||
#define DISPLAY 0x1
|
#define DISPLAY 0x1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user