|
- // Copyright 2009 Olivier Gillet.
- //
- // Author: Olivier Gillet (ol.gillet@gmail.com)
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
- // -----------------------------------------------------------------------------
- //
- // Real time clock.
-
- #ifndef AVRLIB_TIME_H_
- #define AVRLIB_TIME_H_
-
- #include <avr/delay.h>
-
- #include "avrlib/base.h"
-
- namespace avrlib {
-
- uint32_t milliseconds();
- uint32_t Delay(uint32_t delay);
-
- #define ConstantDelay(x) _delay_ms((x))
-
- void InitClock();
-
- const uint32_t microseconds_per_timer0_overflow =
- (64 * 256) / (F_CPU / 1000000L);
- const uint32_t milliseconds_increment =
- microseconds_per_timer0_overflow / 1000;
-
- const uint32_t fractional_increment = (
- microseconds_per_timer0_overflow % 1000) >> 3;
-
- const uint8_t fractional_max = 1000 >> 3;
-
- // The timer count is stored as an union instead of a mere uint32_t because we
- // need access to the individual 16-bit parts of the value.
- extern volatile LongWord timer0_milliseconds;
-
- extern uint8_t timer0_fractional;
-
- inline void TickSystemClock() {
- // Compile-time optimization: with a 20Mhz clock rate, milliseconds_increment
- // is always null, so we have to increment it only when there's a
- // fractional overflow!
- if (milliseconds_increment) {
- timer0_milliseconds.value += milliseconds_increment;
- }
- timer0_fractional += fractional_increment;
- if (timer0_fractional >= fractional_max) {
- timer0_fractional -= fractional_max;
- // The next lines are equivalent to: ++timer0_fractional. Why am I not
- // using ++timer0_fractional? The reason is in the way gcc compiles this.
- // 32-bits values are always loaded into contiguous registers. This code is
- // called from an ISR, so this means 4 contiguous registers are going to
- // be pushed/popped in the ISR. This costs 4 pairs of push/pops (16 cycles).
- // On the other hand, this weird implementation only requires 2 adjacent
- // registers, and they are probably already used for something else in the
- // ISR. There's no free lunch, though: this code is less efficient than
- // a++. However, when it is called every 16th or 32th entry in an ISR, the
- // time saved by avoiding the extra push/pops makes it a better choice.
- //
- // Rule: when you *occasionnally* do something complicated from within an
- // ISR, the code doing the complicated thing should really try to minimize
- // the number of registers it uses, even if it takes more cycles to do
- // the work.
- ++timer0_milliseconds.words[0];
- if (timer0_milliseconds.words[0] == 0) {
- ++timer0_milliseconds.words[1];
- }
- }
- }
-
- } // namespace avrlib
-
- #endif // AVRLIB_TIME_H_
|