#include "wiring_private.h"
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
#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_millis = 0;
static unsigned char timer0_fract = 0;
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
SIGNAL(TIM0_OVF_vect)
#else
SIGNAL(TIMER0_OVF_vect)
#endif
{
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
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 m;
uint8_t oldSREG = SREG;
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;
cli();
m = timer0_overflow_count;
#if defined(TCNT0)
t = TCNT0;
#elif defined(TCNT0L)
t = TCNT0L;
#else
#error TIMER 0 not defined
#endif
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
m++;
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
uint16_t start = (uint16_t)micros();
while (ms > 0) {
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
void delayMicroseconds(unsigned int us)
{
#if F_CPU >= 20000000L
__asm__ __volatile__ (
"nop" "\n\t"
"nop"); if (--us == 0)
return;
us = (us<<2) + us;
us -= 2;
#elif F_CPU >= 16000000L
if (--us == 0)
return;
us <<= 2;
us -= 2;
#else
if (--us == 0)
return;
if (--us == 0)
return;
us <<= 1;
us--;
#endif
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" "brne 1b" : "=w" (us) : "0" (us) );
}
void init()
{
sei();
#if defined(TCCR0A) && defined(WGM01)
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
#endif
#if defined(__AVR_ATmega128__)
sbi(TCCR0, CS02);
#elif defined(TCCR0) && defined(CS01) && defined(CS00)
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
sbi(TCCR0A, CS01);
sbi(TCCR0A, CS00);
#else
#error Timer 0 prescale factor 64 not set correctly
#endif
#if defined(TIMSK) && defined(TOIE0)
sbi(TIMSK, TOIE0);
#elif defined(TIMSK0) && defined(TOIE0)
sbi(TIMSK0, TOIE0);
#else
#error Timer 0 overflow interrupt not set correctly
#endif
#if defined(TCCR1B) && defined(CS11) && defined(CS10)
TCCR1B = 0;
sbi(TCCR1B, CS11);
#if F_CPU >= 8000000L
sbi(TCCR1B, CS10);
#endif
#elif defined(TCCR1) && defined(CS11) && defined(CS10)
sbi(TCCR1, CS11);
#if F_CPU >= 8000000L
sbi(TCCR1, CS10);
#endif
#endif
#if defined(TCCR1A) && defined(WGM10)
sbi(TCCR1A, WGM10);
#elif defined(TCCR1)
#warning this needs to be finished
#endif
#if defined(TCCR2) && defined(CS22)
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
#else
#warning Timer 2 not finished (may not be present on this CPU)
#endif
#if defined(TCCR2) && defined(WGM20)
sbi(TCCR2, WGM20);
#elif defined(TCCR2A) && defined(WGM20)
sbi(TCCR2A, WGM20);
#else
#warning Timer 2 not finished (may not be present on this CPU)
#endif
#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
sbi(TCCR3B, CS31); sbi(TCCR3B, CS30);
sbi(TCCR3A, WGM30); #endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D)
sbi(TCCR4B, CS42); sbi(TCCR4B, CS41);
sbi(TCCR4B, CS40);
sbi(TCCR4D, WGM40); sbi(TCCR4A, PWM4A); sbi(TCCR4C, PWM4D); #else
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
sbi(TCCR4B, CS41); sbi(TCCR4B, CS40);
sbi(TCCR4A, WGM40); #endif
#endif
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
sbi(TCCR5B, CS51); sbi(TCCR5B, CS50);
sbi(TCCR5A, WGM50); #endif
#if defined(ADCSRA)
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
sbi(ADCSRA, ADEN);
#endif
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
#endif
}