| 
							- // 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/>.
 - //
 - // -----------------------------------------------------------------------------
 - //
 - // Definitions of timer and related PWM registers.
 - 
 - #ifndef AVRLIB_TIMER_H_
 - #define AVRLIB_TIMER_H_
 - 
 - // interrupt.h is not strictly needed here, but .cc files including the timer
 - // classes are likely to also define interrupt handlers (and we have macros for
 - // that).
 - #include <avr/interrupt.h>
 - #include <avr/io.h>
 - 
 - #include "avrlib/avrlib.h"
 - 
 - namespace avrlib {
 - 
 - SpecialFunctionRegister(TCCR0A);
 - SpecialFunctionRegister(TCCR0B);
 - SpecialFunctionRegister(TCCR1A);
 - SpecialFunctionRegister(TCCR1B);
 - SpecialFunctionRegister(TCCR2A);
 - SpecialFunctionRegister(TCCR2B);
 - SpecialFunctionRegister(TIMSK0);
 - SpecialFunctionRegister(TIMSK1);
 - SpecialFunctionRegister(TIMSK2);
 - SpecialFunctionRegister(TCNT0);
 - SpecialFunctionRegister16(TCNT1);
 - SpecialFunctionRegister(TCNT2);
 - SpecialFunctionRegister(OCR0A);
 - SpecialFunctionRegister(OCR0B);
 - SpecialFunctionRegister(OCR1A);
 - SpecialFunctionRegister(OCR1B);
 - SpecialFunctionRegister(OCR2A);
 - SpecialFunctionRegister(OCR2B);
 - 
 - #ifdef HAS_TIMER3
 - SpecialFunctionRegister(TCCR3A);
 - SpecialFunctionRegister(TCCR3B);
 - SpecialFunctionRegister(TIMSK3);
 - SpecialFunctionRegister(TCNT3);
 - SpecialFunctionRegister(OCR3A);
 - SpecialFunctionRegister(OCR3B);
 - #endif  // HAS_TIMER3
 - 
 - enum TimerMode {
 -   TIMER_NORMAL = 0,
 -   TIMER_PWM_PHASE_CORRECT = 1,
 -   TIMER_CTC = 2,
 -   TIMER_FAST_PWM = 3,
 - };
 - 
 - template<typename ControlRegisterA,
 -          typename ControlRegisterB,
 -          typename InterruptRegister,
 -          typename ValueRegister>
 - struct TimerImpl {
 -   typedef ControlRegisterA A;
 -   typedef ControlRegisterB B;
 - 
 -   static inline uint8_t value() {
 -     return *ValueRegister::ptr();
 -   }
 - 
 -   static inline void Start() {
 -     *InterruptRegister::ptr() |= _BV(0);
 -   }
 -   static inline void Stop() {
 -     *InterruptRegister::ptr() &= ~(_BV(0));
 -   }
 -   static inline void StartInputCapture() {
 -     *InterruptRegister::ptr() |= _BV(5);
 -   }
 -   static inline void StopInputCapture() {
 -     *InterruptRegister::ptr() &= ~(_BV(5));
 -   }
 -   static inline void StartCompare() {
 -     *InterruptRegister::ptr() |= _BV(1);
 -   }
 -   static inline void StopCompare() {
 -     *InterruptRegister::ptr() &= ~(_BV(1));
 -   }
 -   
 -   static inline void set_mode(TimerMode mode) {
 -     // Sets the mode registers.
 -     *ControlRegisterA::ptr() = (*ControlRegisterA::ptr() & 0xfc) | mode;
 -   }
 -   
 -   static inline void set_mode(
 -       uint8_t wg_mode_1,
 -       uint8_t wg_mode_2,
 -       uint8_t prescaler) {
 -     // Sets the mode registers.
 -     *ControlRegisterA::ptr() = wg_mode_1;
 -     *ControlRegisterB::ptr() = wg_mode_2 | prescaler;
 -   }
 -   
 -   static inline void set_value(uint16_t value) {
 -     *ValueRegister::ptr() = value;
 -   }
 - 
 -   // These are the values for MCUs clocked at 20 MHz
 -   // 
 -   // Timer speed
 -   // value | fast        | accurate
 -   // --------------------------------------
 -   // 1     | 78.125 kHz  | 39.215 kHz
 -   // 2     | 9.765 kHz   | 4.901 kHz
 -   // 3     | 1220.7 Hz   | 612.7 Hz
 -   // 4     | 305.2 Hz    | 153.2 Hz
 -   // 5     | 76.3 Hz     | 38.3 Hz
 -   static inline void set_prescaler(uint8_t prescaler) {
 -     *ControlRegisterB::ptr() = (*ControlRegisterB::ptr() & 0xf8) | prescaler;
 -   }
 - };
 - 
 - template<int n>
 - struct NumberedTimer { };
 - 
 - template<> struct NumberedTimer<0> {
 -   typedef TimerImpl<
 -       TCCR0ARegister,
 -       TCCR0BRegister,
 -       TIMSK0Register,
 -       TCNT0Register> Impl;
 - };
 - 
 - template<> struct NumberedTimer<1> {
 -   typedef TimerImpl<
 -       TCCR1ARegister,
 -       TCCR1BRegister,
 -       TIMSK1Register,
 -       TCNT1Register> Impl;
 - };
 - 
 - template<> struct NumberedTimer<2> {
 -   typedef TimerImpl<
 -       TCCR2ARegister,
 -       TCCR2BRegister,
 -       TIMSK2Register,
 -       TCNT2Register> Impl;
 - };
 - 
 - #ifdef HAS_TIMER3
 - template<> struct NumberedTimer<3> {
 -   typedef TimerImpl<
 -       TCCR3ARegister,
 -       TCCR3BRegister,
 -       TIMSK3Register,
 -       TCNT3Register> Impl;
 - };
 - #endif  // HAS_TIMER3
 - 
 - template<int n>
 - struct Timer {
 -   typedef typename NumberedTimer<n>::Impl Impl;
 -   static inline uint8_t value() { return Impl::value(); }
 -   static inline void Start() { Impl::Start(); }
 -   static inline void Stop() { Impl::Stop(); }
 -   static inline void StartInputCapture() { Impl::StartInputCapture(); }
 -   static inline void StopInputCapture() { Impl::StopInputCapture(); }
 -   static inline void StartCompare() { Impl::StartCompare(); }
 -   static inline void StopCompare() { Impl::StopCompare(); }
 -   static inline void set_mode(TimerMode mode) { Impl::set_mode(mode); }
 -   static inline void set_mode(uint8_t a, uint8_t b, uint8_t c) {
 -     Impl::set_mode(a, b, c);
 -   }
 -   static inline void set_prescaler(uint8_t prescaler) {
 -     Impl::set_prescaler(prescaler);
 -   }
 - };
 - 
 - template<typename Timer, uint8_t enabled_flag, typename PwmRegister>
 - struct PwmChannel {
 -   typedef BitInRegister<typename Timer::Impl::A, enabled_flag> EnabledBit;
 -   enum {
 -     has_pwm = 1
 -   };
 -   static inline void Start() {
 -     EnabledBit::set();
 -   }
 -   static inline void Stop() {
 -     EnabledBit::clear();
 -   }
 -   static inline void Write(uint8_t value) {
 -     *PwmRegister::ptr() = value;
 -   }
 -   static inline void set_frequency(uint16_t f) {
 -     OCR1A = f;
 -     OCR1B = f >> 1;
 -   }
 -   static inline void set_frequency_pulse(uint16_t f) {
 -     OCR1A = f;
 -     OCR1B = f - (f >> 2);
 -   }
 - };
 - 
 - struct NoPwmChannel {
 -   enum {
 -     has_pwm = 0
 -   };
 -   static inline void Start() { }
 -   static inline void Stop() { }
 -   static inline void Write(uint8_t value) { }
 - };
 - 
 - typedef PwmChannel<Timer<0>, COM0A1, OCR0ARegister> PwmChannel0A;
 - typedef PwmChannel<Timer<0>, COM0B1, OCR0BRegister> PwmChannel0B;
 - typedef PwmChannel<Timer<1>, COM1A1, OCR1ARegister> PwmChannel1A;
 - typedef PwmChannel<Timer<1>, COM1B1, OCR1BRegister> PwmChannel1B;
 - typedef PwmChannel<Timer<2>, COM2A1, OCR2ARegister> PwmChannel2A;
 - typedef PwmChannel<Timer<2>, COM2B1, OCR2BRegister> PwmChannel2B;
 - 
 - // Readable aliases for timer interrupts.
 - #define TIMER_0_TICK ISR(TIMER0_OVF_vect)
 - #define TIMER_1_TICK ISR(TIMER1_OVF_vect)
 - #define TIMER_2_TICK ISR(TIMER2_OVF_vect)
 - 
 - #ifdef HAS_TIMER3
 - #define TIMER_3_TICK ISR(TIMER3_OVF_vect)
 - #endif  // HAS_TIMER3
 - 
 - }  // namespace avrlib
 - 
 - #endif   // AVRLIB_TIMER_H_
 
 
  |