Skip to content

Commit

Permalink
Squashed 'avr/cores/MCUdude_corefiles/' changes from 3c376f7d..ce0f4cc0
Browse files Browse the repository at this point in the history
ce0f4cc0 Fix attachInterrupt for AT90CAN32, CAN64 and CAN128
43b470ad Fix TIMER2A PWM generation For AT90CAN32/64/128
87171c2c Accurate millis, micros and delay for more weird clocks 14.7456 MHz, 11.0592 MHz, 7.3728 MHz, 3.6864 MHz and 1.8432 MHz added to micros()
0afb5b19 Add AT90CAN32, AT90CAN64 and AT90CAN128
14e2ae53 Merge pull request #17 from Jackjan4/master
bac5a5a5 Corrected comment
d275ec91 Experimental accuracy improvement
daeebfe4 Fixed return and semicolon
3db48eb8 Add more accurate delay() and micros() for 12MHz
040e3ceb Merge pull request #16 from Jackjan4/master
4209b9ef Accurate delay() and delayMicroseconds() for 32MHz
4a6f6c56 Merge pull request #15 from Jackjan4/master
96a19ab3 Increased correction factor again
0e004163 Adapted correction factor to include delayMicros(9)
b7bb1935 tabs...
a598a1d4 removed tab
e4574f60 Rollback of if-statement and lowered entry-barrier for correction
53294c75 Clean up comments & accurate 24MHz timing
933f8387 Increased subtraction factor & switched if
156634c8 Increased subtraction factor
6ea0e65f Removed tab again :P
2b35c453 delayMicroseconds(1) now delays at least 1us
633342e0 Increase subtraction factor
e585c21d Increase multiplication factor
2f4d8a37 Compensate offset from 18.432MHz to 20MHz - Experimental
d91ea048 Remove more function overhead before succeeding to loop
4814c688 Removed accidental tabs
72b96755 Improved accuracy of delayMicroseconds() on 18.432MHz
44853d99 micros() usable on 24+MHz
0c10c80a Add accurate timing on 18.432MHz based on ATTinyCore
1cec1e36 Preparations for accurate 24MHz timing
787f6909 Merge pull request #14 from Jackjan4/master
80d146d3 Reformatting hopefully last time ;)
6a1886b1 Restored original file formatting 4)
b9941087 Merge remote-tracking branch 'origin/master'
69464ab6 Restored original file formatting 3)
c1ac9113 Restored original file formatting 2)
0a3806bc Restored original file formatting #2
25aa05f4 Restored original file formatting
02dd20a2 Removed unnecessary blanks
4d6139d1 Replaced all tabs with spaces
a89db99f Added fix for delay() on 20MHz which provides 99.5% accuracy
3219ce6e Auto-indendent the whole file
23f9c470 Added comments for understanding how time-counting in arduino works
179a74da Preparing the 20MHz precompiler branch in micros()
2d9c31b8 Replace tabs with spaces
28277ab3 Replace ATmega644 with ATmega644A 644A is binary compatible with 644, but has two UARTS
edf8d239 Fix INT2 issue on ATmega8515/162 Turns out that the registers to control INT2 on 8515/162 is different than every other AVR out there.

git-subtree-dir: avr/cores/MCUdude_corefiles
git-subtree-split: ce0f4cc05832ceeb10b461ce7be22bc1f95ae56a
  • Loading branch information
MCUdude committed May 30, 2019
1 parent bae0134 commit e52c021
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void yield(void);

// ATmega164A/P, ATmega324A/P/PA, ATmega644/P, ATmega1284/P
#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644A__) \
|| defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
#define EXTERNAL 0
#define DEFAULT 1 // Default -> AVCC with external capacitor at AREF pin
Expand Down
28 changes: 14 additions & 14 deletions Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,30 +201,30 @@ size_t Print::println(const Printable& x)
// Custom implementation of printf borrowed from the teensy core files
static int16_t printf_putchar(char c, FILE *fp)
{
((class Print *)(fdev_get_udata(fp)))->write((uint8_t)c);
return 0;
((class Print *)(fdev_get_udata(fp)))->write((uint8_t)c);
return 0;
}

int16_t Print::printf(const char *format, ...)
{
FILE f;
va_list ap;
FILE f;
va_list ap;

fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
fdev_set_udata(&f, this);
va_start(ap, format);
return vfprintf(&f, format, ap);
fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
fdev_set_udata(&f, this);
va_start(ap, format);
return vfprintf(&f, format, ap);
}

int16_t Print::printf(const __FlashStringHelper *format, ...)
{
FILE f;
va_list ap;
FILE f;
va_list ap;

fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
fdev_set_udata(&f, this);
va_start(ap, format);
return vfprintf_P(&f, (const char *)format, ap);
fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
fdev_set_udata(&f, this);
va_start(ap, format);
return vfprintf_P(&f, (const char *)format, ap);
}

// Private Methods /////////////////////////////////////////////////////////////
Expand Down
3 changes: 3 additions & 0 deletions Tone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ Version Modified By Date Comments
#define OCIE2A OCIE2
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#define TIMSK1 TIMSK
#elif defined(__AVR_AT90CAN32__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN128__)
#define TCCR2B TCCR2A
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#endif

// timerx_toggle_count:
Expand Down
20 changes: 13 additions & 7 deletions WInterrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
// Enable interrupt
switch(interruptNum)
{
// ATmega64, ATmega128, ATmega1281, ATmega2561
#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
// ATmega64, ATmega128, ATmega1281, ATmega2561, AT90CAN32, AT90CAN64, AT90CAN128
#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_AT90CAN32__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN128__)
case 0:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
Expand Down Expand Up @@ -190,16 +191,20 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
GICR |= (1 << INT1);
break;
case 2:
#if defined(INT2) // Will exclude ATmega8, since it doesn't have INT2
MCUCSR = (MCUCSR & ~((1 << ISC2))) | ((mode & 0x01) << ISC2);
#if defined(INT2)
#if defined(EMCUCR)
EMCUCR = (EMCUCR & ~((1 << ISC2))) | ((mode & 0x01) << ISC2); // ATmega8515/162
#else
MCUCSR = (MCUCSR & ~((1 << ISC2))) | ((mode & 0x01) << ISC2); // ATmega8535/16/32
#endif
GICR |= (1 << INT2);
#endif
break;

// ATmega164A/P, ATmega324A/P/PA, ATmega644/P, ATmega1284/P
#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324PB__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) \
|| defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) \
|| defined(__AVR_ATmega1284P__)
case 0:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
Expand Down Expand Up @@ -376,8 +381,9 @@ void detachInterrupt(uint8_t interruptNum)
intFunc[interrupt](); \
}

// ATmega64, ATmega128, ATmega1281, ATmega2561
#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
// ATmega64, ATmega128, ATmega1281, ATmega2561, AT90CAN32, AT90CAN64, AT90CAN128
#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_AT90CAN32__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN128__)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
Expand Down
135 changes: 127 additions & 8 deletions wiring.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,39 @@

// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
// 24MHz: An overflow happens every 682.67 microseconds ---> 0.04167, so this results in 682
// 20MHz: An overflow happens every 819.2 microseconds ---> 0,05 (time of a cycle in micros) * 64 (timer0 tick) * 256 (every 256 ticks timer0 overflows), so this results in 819
// 16MHz: An overflow happens every 1024 microseconds
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))

// the whole number of milliseconds per timer0 overflow
// For 20MHz this would be 0 (because of 819)
// For 16MHz this would be 1 (because of 1024)
#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.)
// For 16 MHz: 24 (1024 % 1000) gets shifted right by 3 which results in 3 (precision was lost)
// For 20 MHz: 819 (819 % 1000) gets shifted right by 3 which results in 102 (precision was lost)
// For 24 MHz: 682 (682 % 1000) gets shifted right by 3 which results in
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
// Shift right by 3 to fit in a byte (results in 125)
#define FRACT_MAX (1000 >> 3)

volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;

// timer0 interrupt routine ,- is called every time timer0 overflows
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
// (volatile variables must be read from memory on every access, so this saves time)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;

Expand Down Expand Up @@ -78,10 +88,15 @@ unsigned long millis()

unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;

uint8_t oldSREG = SREG;
// t will be the number where the timer0 counter stopped
uint8_t t;

// Stop all interrupts
cli();
m = timer0_overflow_count;

// TCNT0 : The Timer Counter Register
#if defined(TCNT0)
t = TCNT0;
#elif defined(TCNT0L)
Expand All @@ -90,17 +105,69 @@ unsigned long micros() {
#error TIMER 0 not defined
#endif

// Timer0 Interrupt Flag Register
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
m++;
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif

// Restore SREG
SREG = oldSREG;


#if F_CPU >= 24000000L && F_CPU < 32000000L
// m needs to be multiplied by 682.67
// and t by 2.67
m = (m << 8) + t;
return (m << 1) + (m >> 1) + (m >> 3) + (m >> 4); // Multiply by 2.6875
#elif F_CPU >= 20000000L
// m needs to be multiplied by 819.2
// t needs to be multiplied by 3.2
m = (m << 8) + t;
return m + (m << 1) + (m >> 2) - (m >> 4); // Multiply by 3.1875
#elif F_CPU >= 18432000L
// m needs to be multiplied by 888.88
// and t by 3.47
m = (m << 8) + t;
return m + (m << 1) + (m >> 1); // Multiply by 3.5
#elif F_CPU >= 14745600L && F_CPU != 16000000L
// m needs to be multiplied by 1111.1
// and t by 4.34
m = (m << 8) + t;
return (m << 2) + (m >> 1) - (m >> 3) - (m >> 4); // Multiply by 4.3125
#elif F_CPU >= 12000000L && F_CPU != 16000000L
// m needs to be multiplied by 1365.33
// and t by 5.33
m = (m << 8) + t;
return m + (m << 2) + (m >> 2) + (m >> 3) - (m >> 4) + (m >> 5); // Multiply by 5.3437
#elif F_CPU >= 11059200L && F_CPU != 16000000L
// m needs to be multiplied by 1481.48
// and t by 5.78
m = (m << 8) + t;
return (m << 2) + (m << 1) - (m >> 2) + (m >> 5); // Multiply by 5.78125
#elif F_CPU == 7372800L
// m needs to be multiplied by 2222.22
// and t by 8.68
m = (m << 8) + t;
return (m << 3) + m - (m >> 2) - (m >> 3); // Multiply by 8.625
#elif F_CPU == 3686400L
// m needs to be multiplied by 4444.44
// and t by 17.36
m = (m << 8) + t;
return (m << 4) + m + (m >> 1) - (m >> 3) - (m >> 6); // Multiply by 17.359375
#elif F_CPU == 1843200L
// m needs to be multiplied by 8888.88
// and t by 34.72
m = (m << 8) + t;
return (m << 5) + (m << 1) + (m >> 1) + (m >> 2); // Multiply by 34.75
#else
// 32 MHz, 24 MHz, 16 MHz, 8 MHz, 4 MHz, 1 MHz
// Shift by 8 to the left (multiply by 256) so t (which is 1 byte in size) can fit in
// m & t are multiplied by 4 (since it was already multiplied by 256)
// t is multiplied by 4
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
#endif
}

void delay(unsigned long ms)
Expand All @@ -116,15 +183,31 @@ void delay(unsigned long ms)
}
}

/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 18.432, 20, 24 or 32 MHz clock. */
void delayMicroseconds(unsigned int us)
{
// call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)

// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
#if F_CPU >= 24000000L
#if F_CPU >= 32000000L
// for the 32 MHz clock for the extreme users, trying to overclock to the max

// zero delay fix
if (!us) return; // = 3 cycles, (4 when true)

// the following loop takes a 1/8 of a microsecond (4 cycles)
// per iteration, so execute it eight times for each microsecond of
// delay requested.
us <<= 3; // x8 us, = 6 cycles

// account for the time taken in the preceeding commands.
// we just burned 21 (23) cycles above, remove 5, (5*4=20)
// us is at least 8 so we can substract 5
us -= 5; //=2 cycles

#elif F_CPU >= 24000000L
// for the 24 MHz clock for the aventurous ones, trying to overclock

// zero delay fix
Expand Down Expand Up @@ -162,6 +245,40 @@ void delayMicroseconds(unsigned int us)
// us is at least 10 so we can substract 7
us -= 7; // 2 cycles

#elif F_CPU >= 18432000L
// for a one-microsecond delay, simply return. the overhead
// of the function call takes 17 (19) cycles, which is aprox. 1us
__asm__ __volatile__ (
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop"); //just waiting 4 cycles

if (us <= 1) return; // = 3 cycles, (4 when true)

// the following loop takes nearly 1/5 (0.217%) of a microsecond (4 cycles)
// per iteration, so execute it five times for each microsecond of
// delay requested.
us = (us << 2) + us; // x5 us, = 7 cycles

// user wants to wait longer than 9us - here we can use approximation with multiplication
if (us > 36) { // 3 cycles
// Since the loop is not accurately 1/5 of a microsecond we need
// to multiply us by 0,9216 (18.432 / 20)
us = (us >> 1) + (us >> 2) + (us >> 3) + (us >> 4); // x0.9375 us, = 20 cycles (TODO: the cycle count needs to be validated)

// account for the time taken in the preceeding commands.
// we just burned 45 (47) cycles above, remove 12, (12*4=48) (TODO: calculate real number of cycles burned)
// additionaly, since we are not 100% precise (we are slower), subtract a bit more to fit for small values
// us is at least 46, so we can substract 18
us -= 19; // 2 cycles
} else {
// account for the time taken in the preceeding commands.
// we just burned 30 (32) cycles above, remove 8, (8*4=32)
// us is at least 10, so we can substract 8
us -= 8; // 2 cycles
}

#elif F_CPU >= 16000000L
// for the 16 MHz clock on most Arduino boards

Expand Down Expand Up @@ -226,7 +343,7 @@ void delayMicroseconds(unsigned int us)
// per iteration, so execute it us/4 times
// us is at least 4, divided by 4 gives us 1 (no zero delay bug)
us >>= 2; // us div 4, = 4 cycles


#endif

Expand Down Expand Up @@ -316,6 +433,8 @@ void init()
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
#elif defined(TCCR2A) && defined(CS22)
sbi(TCCR2A, CS22);
//#else
// Timer 2 not finished (may not be present on this CPU)
#endif
Expand Down

0 comments on commit e52c021

Please sign in to comment.