Skip to content

Commit

Permalink
Merge pull request #18 from MCUdude/improved_micros
Browse files Browse the repository at this point in the history
Significantly improve micros (#17)
  • Loading branch information
MCUdude committed May 6, 2017
2 parents 63b83e6 + 8f4ffb7 commit 65b6528
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 52 deletions.
16 changes: 9 additions & 7 deletions avr/cores/microcore/core_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ need, in order to free up some space.
// accurate down to 1 ms, but will increase with steps of 16.
#define ENABLE_MILLIS

// WARNING!! Enabling micros() will cause the processor to interrupt every 256 clock cycle, and will mess
// up timing functions such as delay() and _delay_ms(). E.g delay(1) will actually last 1.3 ms instead.
// Do you really want this? The choice is always yours ;)
// Enabling micros() will cause the processor to interrupt more often (every 2048th clock cycle if
// F_CPU < 4.8 MHz, every 16384th clock cycle if F_CPU >= 4.8 MHz. This will add some overhead when F_CPU is
// less than 4.8 MHz. It's disabled by default because it occupies precious flash space and loads the CPU with
// additional interrupts and calculations. Also note that micros() very aren't precise for frequencies that 64
// doesn't divide evenly by.
//#define ENABLE_MICROS

// If you're not using the analog pins or want to set it up yourself, you can disable it here
Expand All @@ -38,17 +40,17 @@ need, in order to free up some space.

// Here's the PWM settings for Timer0
// These settings will also be disabled if SETUP_PWM is commented out
#define PRESCALER_8 // PWM frequency = (F_CPU/256) / 8 <-- DEFAULT
// Note that ENABLE_MICROS will override this setting
#define PRESCALER_DEFAULT // Selects the "best suited" prescaler based on F_CPU
//#define PRESCALER_NONE // PWM frequency = (F_CPU/256) / 1
//#define PRESCALER_8 // PWM frequency = (F_CPU/256) / 8
//#define PRESCALER_64 // PWM frequency = (F_CPU/256) / 64
//#define PRESCALER_256 // PWM frequency = (F_CPU/256) / 256
//#define PRESCALER_1024 // PWM frequency = (F_CPU/256) / 1024

// These are the waveform generation settings for timer0
#define PWM_FAST // <-- DEFAULT
//#define PWM_NORMAL
#define PWM_FAST // <-- DEFAULT
//#define PWM_PHASE_CORRECT
//#define PWM_CTC


#endif
123 changes: 78 additions & 45 deletions avr/cores/microcore/wiring.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,48 +48,70 @@ uint32_t millis()
#ifdef ENABLE_MICROS
volatile uint32_t timer0_overflow = 0;

// This will cause an interrupt every 256 clock cycle
// This will cause an interrupt every 256/64 clock cycle
ISR(TIM0_OVF_vect)
{
timer0_overflow++; // Increment counter by one
}


uint32_t micros()
{
uint32_t x;
// Preserve old SREG vale
uint8_t oldSREG = SREG;
// Disable global interrupts
cli();
#if F_CPU == 16000
x = timer0_overflow * 16000;
#elif F_CPU < 150000 && F_CPU > 80000
x = timer0_overflow * 2000;
#elif F_CPU == 600000
x = timer0_overflow * 427;
#elif F_CPU == 1000000
x = timer0_overflow * 256;
#elif F_CPU == 1200000
x = timer0_overflow * 213;
#elif F_CPU == 4000000
x = timer0_overflow * 64;
#elif F_CPU == 4800000
x = timer0_overflow * 53;
#elif F_CPU == 8000000
x = timer0_overflow * 32;
#elif F_CPU == 9600000
x = timer0_overflow * 27;
#elif F_CPU == 10000000
x = timer0_overflow * 26;
#elif F_CPU == 12000000
x = timer0_overflow * 21;
#elif F_CPU == 16000000
x = timer0_overflow * 16;
#else
#error
#warning This CPU frequency is not defined (choose 128 kHz or more)
sei();
return 0;
#endif
sei();
// Variable to hold the return value
uint32_t x;

#if F_CPU == 20000000L
// Each timer tick is 1/(16MHz/64) = 3.2us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 3.2us long,
// we multiply by 3 at the end
x = ((timer0_overflow << 8) + TCNT0) * 3;
#elif F_CPU == 16000000L
// Each timer tick is 1/(16MHz/64) = 4us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 4us long,
// we multiply by 4 at the end
x = ((timer0_overflow << 8) + TCNT0) * 4;
#elif F_CPU == 1200000L
// Each timer tick is 1/(12MHz/64) = 5.333us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 5.333us long,
// we multiply by 5 at the end
x = ((timer0_overflow << 8) + TCNT0) * 5;
#elif F_CPU == 9600000L
// Each timer tick is 1/(9.6MHz/64) = 6.666us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 6.666us long,
// we multiply by 7 at the end
x = ((timer0_overflow << 8) + TCNT0) * 7;
#elif F_CPU == 80000000L
// Each timer tick is 1/(8MHz/64) = 8us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 8us long,
// we multiply by 8 at the end
x = ((timer0_overflow << 8) + TCNT0) * 8;
#elif F_CPU == 4800000L
// Each timer tick is 1/(4.8MHz/64) = 13.333us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 13.333us long,
// we multiply by 13 at the end
x = ((timer0_overflow << 8) + TCNT0) * 13;
#elif F_CPU == 1200000L
// Each timer tick is 1/(1.2MHz/8) = 6.666us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 6.666us long,
// we multiply by 7 at the end
x = ((timer0_overflow << 8) + TCNT0) * 7;
#elif F_CPU == 1000000L
// Each timer tick is 1/(1MHz/8) = 8us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 8us long,
// we multiply by 8 at the end
x = ((timer0_overflow << 8) + TCNT0) * 8;
#elif F_CPU == 600000L
// Each timer tick is 1/(600kHz/8) = 13.333us long. We multiply the timer0_overflow variable
// by 256 (bitshift 8 times) and we add the current timer count TCNT0. Since each tick is 13.333us long,
// we multiply by 13 at the end
x = ((timer0_overflow << 8) + TCNT0) * 13;
#endif

// Restore SREG
SREG = oldSREG;
return x;
}
#endif // ENABLE_MICROS
Expand All @@ -112,28 +134,30 @@ void init()
{
#ifdef SETUP_PWM
// Set Timer0 prescaler
#if defined(PRESCALER_NONE) // PWM frequency = (F_CPU/256) / 1
#if defined(PRESCALER_DEFAULT)
#if F_CPU >= 4800000L
TCCR0B |= _BV(CS00) | _BV(CS01); // PWM frequency = (F_CPU/256) / 64
#else
TCCR0B |= _BV(CS01); // PWM frequency = (F_CPU/256) / 8
#endif
#elif defined(PRESCALER_NONE) // PWM frequency = (F_CPU/256) / 1
TCCR0B |= _BV(CS00);
#elif defined(PRESCALER_8) // PWM frequency = (F_CPU/256) / 8
#elif defined(PRESCALER_8) // PWM frequency = (F_CPU/256) / 8
TCCR0B |= _BV(CS01);
#elif defined(PRESCALER_64) // PWM frequency = (F_CPU/256) / 64
#elif defined(PRESCALER_64) // PWM frequency = (F_CPU/256) / 64
TCCR0B |= _BV(CS00) | _BV(CS01);
#elif defined(PRESCALER_256) // PWM frequency = (F_CPU/256) / 256
#elif defined(PRESCALER_256) // PWM frequency = (F_CPU/256) / 256
TCCR0B |= _BV(CS02);
#elif defined(PRESCALER_1024) // PWM frequency = (F_CPU/256) / 1024
#elif defined(PRESCALER_1024) // PWM frequency = (F_CPU/256) / 1024
TCCR0B |= _BV(CS00) | _BV(CS02);
#endif

// Set waveform generation mode
#if defined(PWM_FAST)
TCCR0A |= _BV(WGM00) | _BV(WGM01);
#elif defined(PWM_NORMAL)
TCCR0A &= ~_BV(WGM00) | ~_BV(WGM01);
#elif defined(PWM_PHASE_CORRECT)
TCCR0A |= _BV(WGM00);
#elif defined(PWM_CTC)
TCCR0A |= _BV(WGM01);
#endif
#endif
#endif

// Enable WDT interrupt and enable global interrupts
Expand All @@ -148,8 +172,17 @@ void init()
sei();
#endif

// WARNING! Enabling micros() will affect timing functions heavily!
// WARNING! Enabling micros() will affect timing functions!
#ifdef ENABLE_MICROS

// Clear all Timer0 settings
TCCR0B = 0;
// Set a suited prescaler based on F_CPU
#if F_CPU >= 4800000L
TCCR0B |= _BV(CS00) | _BV(CS01); // F_CPU/64
#else
TCCR0B |= _BV(CS01); // F_CPU/8
#endif
// Enable overflow interrupt on Timer0
TIMSK0 |= _BV(TOIE0);
// Set timer0 couter to zero
Expand Down

0 comments on commit 65b6528

Please sign in to comment.