Skip to content

Commit

Permalink
Squashed 'avr/cores/MCUdude_corefiles/' changes from fa31758e9..a367b…
Browse files Browse the repository at this point in the history
…8b9a

a367b8b9a Merge pull request #32 from cburstedde/feature-exact-timing
e7f9313ce Merge branch 'master' into feature-exact-timing
c24da8fcb Updated accuracy calculation
7efce6186 Replace bit_is_set with "regular" and operation
5fba4671d Minimal accuracy tweaks
0f33b77ce Merge pull request #31 from cburstedde/feature-exact-timing
d10b60393 Update README
299220515 Exact or very accurate millis/micros/delay always
065732108 Non-functional tweaks
0dd91a679 Update README
25fad398a Add exact timing for 9.216 MHz
19b8514f5 Merge branch 'master' into feature-exact-timing
5d4ba89e8 Correct millis and micros for arbitrary frequencies
8913fb360 Add missing parentheses
b622f9856 Add exact timing for 10 MHz
0333bcea5 Update README
5af5045c8 Add accurate timing for 16.5 MHz
e318ce1ca Add exact timing for 6 MHz
0c0b4f3a8 Remove superfluous cast
aeaadea0f Merge pull request #29 from cburstedde/feature-delayMicroseconds
4e74473d7 Merge pull request #28 from cburstedde/feature-correct-micros
6916530f2 Fix several corner cases in delayMicroseconds()
038385eea It makes a difference using unsigned math!!
912145b81 Go back to long multiply but still optimize
909105605 Use faster unsigned int multiply in micros()
eeb6635e7 Merge pull request #27 from cburstedde/feature-exact-timing
21d1d6fa7 README typo
9be3a3e42 Disable alternate micros algorithm for powers of 2
bcd8baa5a Move timer0_exact static variable def into ISR
745508971 Rename correction #define and variable
9fef70e27 Reduce unnecessary long comparison to char
95166c10e Correct bad idea: access fract with interrupts off
f64aa5d03 Remove unneeded unsigned char in micros()
a91536407 White space in wiring.c
f683310fa Make micros zero-drift based on exact millis
b28acdb84 Make 25 MHz a supported clock frequency
2a6c810ce Comments and README edits
7cde04dd0 Merge pull request #26 from cburstedde/feature-delayMicroseconds
0172627e2 Merge branch 'master' into feature-delayMicroseconds
3b1142ffd Merge pull request #25 from cburstedde/feature-correct-micros
e858df7d8 Merge branch 'master' into feature-correct-micros
b32ca2bc5 Merge pull request #24 from cburstedde/feature-correct-millis
0205fd55b delayMicroseconds() safe for us == 0 and >= 24 MHz
032bed72f Statement on delayMicroseconds() in README
afa0f8f69 Use 60398UL unsigned long constant
9b7291ae3 Add 22.1184 and 18 MHz cases to delayMicroseconds
ec16def12 Add/edit comments for delayMicroseconds()
4a89b74ed Replace abs macro ... with a "safe" version of the original abs macro. Unlike __builtin_abs() this also deals with floats, which is pretty much required to ensure compatibility against the official Arduino core(s).
57b7486af Tune ppm values in README
059d20b18 Optimize away two increments from timing ISR
3d890c22d Improve micros() to 100 ppm for 7.37, 3.68, 1.84
d852091be Tiny README update
39112b389 Simplify millis calculation to fit into long int
d1719372c Improve micros() accuracy for 14.7456, 12, 11.0952
84c8f335d micros() below crystal tolerance for 18.432, 20 MHz
b8002ce05 Update README for new/improved micros()
239425178 Make micros calculation more efficient for 20 MHz
d736735fd Add 18 MHz clock to micros()
21cf2177e Improve accuracy of 24 MHz micros()
3b9aa8990 Add 18 MHz clock to millis() calculation
65aa77f4d Fix timing error for non-power-of-two clocks
0091354f8 Add discussion of micros and delay to README
af3b94c79 Non-functional clarification
2568a3f85 Add millis() discussion to README
56512e963 Add millis () correction to make 22.1184 MHz exact
2d42b729d Add 22.1184 MHz micros () correction
46fa6940c Prevent micros for 32 MHz to enter wrong case
49f5f250a Increase micros () accuracy for 18.432 and 20 MHz
b51058fe1 Supply millis () correction for 24 MHz
993843d4d Add two odd frequencies 7.37 and 3.69 MHz
25c1c988b Correction makes millis() exact for several speeds

git-subtree-dir: avr/cores/MCUdude_corefiles
git-subtree-split: a367b8b9ab17653a379108e48d7696bf1c6ca336
  • Loading branch information
MCUdude committed Feb 19, 2021
1 parent 4ee8e2d commit caf26c7
Show file tree
Hide file tree
Showing 4 changed files with 489 additions and 82 deletions.
8 changes: 4 additions & 4 deletions Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ void yield(void);
#undef abs
#endif

#define abs(x) __builtin_abs(x)
#define abs(x) ({ typeof (x) _x = (x); _x > 0 ? _x : -x; })
#define sq(x) ({ typeof (x) _x = (x); _x * _x; })
#define min(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a < _b ? _a : _b; })
#define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
#define round(x) ({ typeof (x) _x = (x); _x >= 0 ? (long)_x + 0.5 : (long)_x - 0.5; })
#define min(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a < _b ? _a : _b; })
#define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
#define round(x) ({ typeof (x) _x = (x); _x >= 0 ? (long)(_x + 0.5) : (long)(_x - 0.5); })
#define radians(deg) ((deg) * DEG_TO_RAD)
#define degrees(rad) ((rad) * RAD_TO_DEG)
#define constrain(x,low,high) ({ \
Expand Down
76 changes: 75 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,102 @@

This repo contains the Arduino corefiles used with [MightyCore](https://github.com/MCUdude/MightyCore), [MegaCore](https://github.com/MCUdude/MegaCore), [MiniCore](https://github.com/MCUdude/MiniCore) and [MajorCore](https://github.com/MCUdude/MightyCore).


## Supported devices

* ATmega640, ATmega1280, ATmega2560
* ATmega64, ATmega128, ATmega1281, ATmega2561
* AT90CAN32, AT90CAN64, AT90CAN128
* ATmega8535, ATmega16, ATmega32, ATmega164A/P, ATmega324A/P/PA/PB, ATmega644/P, ATmega1284/P
* ATmega8515, ATmega162
* ATmega8, ATmega48/P/PA/PB, ATmega88/P/PA/PB, ATmega168/P/PA/PB, ATmega328/P/PA/PB


## Supported clock frequencies
By supported I mean clocks that accurate timing is implemented for (millis, micros, delay, delayMicroseconds).

By supported I mean clocks that accurate timing is implemented for (millis,
micros, delay, delayMicroseconds).

* 32 MHz
* 25 MHz
* 24 MHz
* 22.1184 MHz
* 20 MHz
* 18.432 MHz
* 18 MHz
* 16.5 MHz
* 16 MHz
* 14.7456 MHz
* 12 MHz
* 11.0592 MHz
* 10 MHz
* 9.216 MHz
* 8 MHz
* 7.3728 MHz
* 6 MHz
* 4 MHz
* 3.6864 MHz
* 2 MHz
* 1.8432 MHz
* 1 MHz


### Adding further clock frequencies

The calculation of `millis()`, `micros()` and `delay()` is automatic for
arbitrary frequencies.
Depending on the prime factors of the frequency, it is either exact or
approximate to 60 ppm accuracy (worst-case).
The only thing required is adding support in `delayMicroseconds()`.


### Exactness of `delayMicroseconds()`

The `delayMicroseconds(unsigned int us)` implementation is exact up to a few
cycles for the frequencies listed above.

The maximum input parameter to work reliably is 10000 for 10 milliseconds.
Its result is affected by interrupts occurring, which may prolong the delay.


### Exactness of `micros()` and `delay()`

For the clock speeds listed above, `micros()` is corrected to zero drift.
Even for very long run times, the `micros()` function will precisely follow the
oscillator used.

Frequencies not listed above are either exact or corrected to below 60 ppm drift
and in exact sync with `millis()`.

Note that the result of `micros()` may jump up by several microseconds between
consecutive calls and rolls over after one hour and eleven minutes.

The `delay()` function uses `micros()` internally and inherits its drift accuracy
with slight variations due to function call overhead and processing.
It is immune to interrupts and thus long-term accurate.


### Exactness of `millis()`

For the clock speeds listed above, `millis()` is corrected to zero drift.
Even for very long run times, the `millis()` function will precisely follow the
oscillator used.

Frequencies not listed above are either exact or corrected to below 60 ppm drift
and in exact sync with `micros()` and `delay()`.

We do not register the rollover of the `unsigned long` millis counter that
occurs every 49.7 days; such would have to be done in the user's program.
Often this is not necessary: The code

if (millis() - millis_old >= interval) {
/* do something */
millis_old += interval;
}

is long-term accurate even when rolling over provided `millis_old` is of type
`unsigned long`.

For clock speeds of 16 MHz and below, the return value of `millis()`
occasionally jumps up by more than one (notwithstanding low/zero drift).
Thus, when relying on consecutive returns, run at 16.5 MHz or higher.
Loading

0 comments on commit caf26c7

Please sign in to comment.