| 
							- // 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/>.
 - //
 - // -----------------------------------------------------------------------------
 - //
 - // An alternative gpio library based on templates.
 - //
 - // Examples of use:
 - //
 - // NumberedGpio<3>::set_mode(DIGITAL_INPUT)
 - // NumberedGpio<4>::set_mode(DIGITAL_OUTPUT)
 - // NumberedGpio<3>::value()
 - // NumberedGpio<4>::High()
 - // NumberedGpio<4>::Low()
 - // NumberedGpio<4>::set_value(1)
 - // NumberedGpio<4>::set_value(0)
 - 
 - #ifndef AVRLIB_GPIO_H_
 - #define AVRLIB_GPIO_H_
 - 
 - #include <avr/io.h>
 - 
 - #include "avrlib/avrlib.h"
 - #include "avrlib/timer.h"
 - 
 - namespace avrlib {
 - 
 - enum PinMode {
 -   DIGITAL_INPUT = 0,
 -   DIGITAL_OUTPUT = 1,
 -   PWM_OUTPUT = 2
 - };
 - 
 - // All the registers used in the following definitions are wrapped here.
 - IORegister(DDRB);
 - IORegister(DDRC);
 - IORegister(DDRD);
 - 
 - IORegister(PORTB);
 - IORegister(PORTC);
 - IORegister(PORTD);
 - 
 - IORegister(PINB);
 - IORegister(PINC);
 - IORegister(PIND);
 - 
 - // Represents a i/o port, which has input, output and mode registers.
 - template<typename InputRegister, typename OutputRegister,
 -          typename ModeRegister>
 - struct Port {
 -   typedef InputRegister Input;
 -   typedef OutputRegister Output;
 -   typedef ModeRegister Mode;
 - };
 - 
 - // Definition of I/O ports.
 - typedef Port<PINBRegister, PORTBRegister, DDRBRegister> PortB;
 - typedef Port<PINCRegister, PORTCRegister, DDRCRegister> PortC;
 - typedef Port<PINDRegister, PORTDRegister, DDRDRegister> PortD;
 - 
 - #if defined(ATMEGA164P) || defined(ATMEGA324P) || defined(ATMEGA644P) || defined(ATMEGA1284P) || defined(ATMEGA2560)
 - 
 - IORegister(DDRA);
 - IORegister(PORTA);
 - IORegister(PINA);
 - typedef Port<PINARegister, PORTARegister, DDRARegister> PortA;
 - 
 - #endif
 - 
 - #if defined (ATMEGA640) || defined (ATMEGA1280) || defined(ATMEGA2560)
 - IORegister(DDRE);
 - IORegister(DDRF);
 - IORegister(DDRG);
 - IORegister(DDRH);
 - IORegister(DDRJ);
 - IORegister(DDRK);
 - IORegister(DDRL);
 - 
 - IORegister(PORTE);
 - IORegister(PORTF);
 - IORegister(PORTG);
 - IORegister(PORTH);
 - IORegister(PORTJ);
 - IORegister(PORTK);
 - IORegister(PORTL);
 - 
 - IORegister(PINE);
 - IORegister(PINF);
 - IORegister(PING);
 - IORegister(PINH);
 - IORegister(PINJ);
 - IORegister(PINK);
 - IORegister(PINL);
 - 
 - typedef Port<PINERegister, PORTERegister, DDRERegister> PortE;
 - typedef Port<PINFRegister, PORTFRegister, DDRFRegister> PortF;
 - typedef Port<PINGRegister, PORTGRegister, DDRGRegister> PortG;
 - typedef Port<PINHRegister, PORTHRegister, DDRHRegister> PortH;
 - typedef Port<PINJRegister, PORTJRegister, DDRJRegister> PortJ;
 - typedef Port<PINKRegister, PORTKRegister, DDRKRegister> PortK;
 - typedef Port<PINLRegister, PORTLRegister, DDRLRegister> PortL;
 - 
 - #endif
 - 
 - 
 - // The actual implementation of a pin, not very convenient to use because it
 - // requires the actual parameters of the pin to be passed as template
 - // arguments.
 - template<typename Port, typename PwmChannel, uint8_t bit>
 - struct GpioImpl {
 -   typedef BitInRegister<typename Port::Mode, bit> ModeBit;
 -   typedef BitInRegister<typename Port::Output, bit> OutputBit;
 -   typedef BitInRegister<typename Port::Input, bit> InputBit;
 -   typedef PwmChannel Pwm;
 - 
 -   static inline void set_mode(uint8_t mode) {
 -     if (mode == DIGITAL_INPUT) {
 -       ModeBit::clear();
 -     } else if (mode == DIGITAL_OUTPUT || mode == PWM_OUTPUT) {
 -       ModeBit::set();
 -     }
 -     if (mode == PWM_OUTPUT) {
 -       PwmChannel::Start();
 -     } else {
 -       PwmChannel::Stop();
 -     }
 -   }
 - 
 -   static inline void High() {
 -     OutputBit::set();
 -   }
 -   static inline void Low() {
 -     OutputBit::clear();
 -   }
 -   static inline void Toggle() {
 -     OutputBit::toggle();
 -   }
 -   static inline void set_value(uint8_t value) {
 -     if (value == 0) {
 -       Low();
 -     } else {
 -       High();
 -     }
 -   }
 -   
 -   static inline void set_pwm_value(uint8_t value) {
 -     if (PwmChannel::has_pwm) {
 -       PwmChannel::Write(value);
 -     } else {
 -       set_value(value);
 -     }
 -   }
 - 
 -   static inline uint8_t value() {
 -     return InputBit::value();
 -   }
 -   static inline uint8_t is_high() {
 -     return InputBit::value();
 -   }
 -   static inline uint8_t is_low() {
 -     return InputBit::value() == 0;
 -   }
 - };
 - 
 - 
 - template<typename port, uint8_t bit>
 - struct Gpio {
 -   typedef GpioImpl<port, NoPwmChannel, bit> Impl;
 -   static void High() { Impl::High(); }
 -   static void Low() { Impl::Low(); }
 -   static void Toggle() { Impl::Toggle(); }
 -   static void set_mode(uint8_t mode) { Impl::set_mode(mode); }
 -   static void set_value(uint8_t value) { Impl::set_value(value); }
 -   static void set_pwm_value(uint8_t value) { Impl::set_pwm_value(value); }
 -   static uint8_t value() { return Impl::value(); }
 -   static uint8_t is_low() { return Impl::is_low(); }
 -   static uint8_t is_high() { return Impl::is_high(); }
 - };
 - 
 - struct DummyGpio {
 -   static void High() { }
 -   static void Low() { }
 -   static void set_mode(uint8_t mode) { }
 -   static void set_value(uint8_t value) { }
 -   static void set_pwm_value(uint8_t value) { }
 -   static uint8_t value() { return 0; }
 -   static uint8_t is_low() { return 0; }
 -   static uint8_t is_high() { return 0; }
 - };
 - 
 - template<typename Gpio>
 - struct Inverter {
 -   static void High() { Gpio::Low(); }
 -   static void Low() { Gpio::High(); }
 -   static void set_mode(uint8_t mode) { Gpio::set_mode(mode); }
 -   static void set_value(uint8_t value) { Gpio::set_value(!value); }
 -   static void set_pwm_value(uint8_t value) { Gpio::set_pwm_value(~value); }
 -   static uint8_t value() { return !Gpio::value(); }
 -   static uint8_t is_low() { return !Gpio::is_low(); }
 -   static uint8_t is_high() { return !Gpio::is_high(); }
 - };
 - 
 - template<typename gpio>
 - struct DigitalInput {
 -   enum {
 -     buffer_size = 0,
 -     data_size = 1,
 -   };
 -   static void Init() {
 -     gpio::set_mode(DIGITAL_INPUT);
 -   }
 -   static void EnablePullUpResistor() {
 -     gpio::High();
 -   }
 -   static void DisablePullUpResistor() {
 -     gpio::Low();
 -   }
 -   static uint8_t Read() {
 -     return gpio::value();
 -   }
 - };
 - 
 - // A template that will be specialized for each pin, allowing the pin number to
 - // be specified as a template parameter.
 - template<int n>
 - struct NumberedGpioInternal { };
 - 
 - // Macro to make the pin definitions (template specializations) easier to read.
 - #define SetupGpio(n, port, timer, bit) \
 - template<> struct NumberedGpioInternal<n> { \
 -   typedef GpioImpl<port, timer, bit> Impl; };
 - 
 - // Pin definitions for ATmega lineup
 - 
 - #if defined(ATMEGA48P) || defined(ATMEGA88P) || defined(ATMEGA168P) || defined(ATMEGA328P)
 - 
 - SetupGpio(0, PortD, NoPwmChannel, 0);
 - SetupGpio(1, PortD, NoPwmChannel, 1);
 - SetupGpio(2, PortD, NoPwmChannel, 2);
 - SetupGpio(3, PortD, PwmChannel2B, 3);
 - SetupGpio(4, PortD, NoPwmChannel, 4);
 - SetupGpio(5, PortD, PwmChannel0B, 5);
 - SetupGpio(6, PortD, PwmChannel0A, 6);
 - SetupGpio(7, PortD, NoPwmChannel, 7);
 - SetupGpio(8, PortB, NoPwmChannel, 0);
 - SetupGpio(9, PortB, PwmChannel1A, 1);
 - SetupGpio(10, PortB, PwmChannel1B, 2);
 - SetupGpio(11, PortB, PwmChannel2A, 3);
 - SetupGpio(12, PortB, NoPwmChannel, 4);
 - SetupGpio(13, PortB, NoPwmChannel, 5);
 - SetupGpio(14, PortC, NoPwmChannel, 0);
 - SetupGpio(15, PortC, NoPwmChannel, 1);
 - SetupGpio(16, PortC, NoPwmChannel, 2);
 - SetupGpio(17, PortC, NoPwmChannel, 3);
 - SetupGpio(18, PortC, NoPwmChannel, 4);
 - SetupGpio(19, PortC, NoPwmChannel, 5);
 - 
 - SetupGpio(255, PortB, NoPwmChannel, 0);
 - 
 - typedef Gpio<PortB, 5> SpiSCK;
 - typedef Gpio<PortB, 4> SpiMISO;
 - typedef Gpio<PortB, 3> SpiMOSI;
 - typedef Gpio<PortB, 2> SpiSS;
 - 
 - typedef Gpio<PortD, 4> UartSpi0XCK;
 - typedef Gpio<PortD, 1> UartSpi0TX;
 - typedef Gpio<PortD, 0> UartSpi0RX;
 - 
 - #define HAS_USART0
 - 
 - #elif defined(ATMEGA164P) || defined(ATMEGA324P) || defined(ATMEGA644P) || defined(ATMEGA1284P)
 - 
 - SetupGpio(0,  PortB, NoPwmChannel, 0);
 - SetupGpio(1,  PortB, NoPwmChannel, 1);
 - SetupGpio(2,  PortB, NoPwmChannel, 2);
 - SetupGpio(3,  PortB, PwmChannel0A, 3);
 - SetupGpio(4,  PortB, PwmChannel0B, 4);
 - SetupGpio(5,  PortB, NoPwmChannel, 5);
 - SetupGpio(6,  PortB, NoPwmChannel, 6);
 - SetupGpio(7,  PortB, NoPwmChannel, 7);
 - 
 - SetupGpio(8,  PortD, NoPwmChannel, 0);
 - SetupGpio(9,  PortD, NoPwmChannel, 1);
 - SetupGpio(10, PortD, NoPwmChannel, 2);
 - SetupGpio(11, PortD, NoPwmChannel, 3);
 - SetupGpio(12, PortD, PwmChannel1B, 4);
 - SetupGpio(13, PortD, PwmChannel1A, 5);
 - SetupGpio(14, PortD, PwmChannel2B, 6);
 - SetupGpio(15, PortD, PwmChannel2A, 7);
 - 
 - SetupGpio(16, PortC, NoPwmChannel, 0);
 - SetupGpio(17, PortC, NoPwmChannel, 1);
 - SetupGpio(18, PortC, NoPwmChannel, 2);
 - SetupGpio(19, PortC, NoPwmChannel, 3);
 - SetupGpio(20, PortC, NoPwmChannel, 4);
 - SetupGpio(21, PortC, NoPwmChannel, 5);
 - SetupGpio(22, PortC, NoPwmChannel, 6);
 - SetupGpio(23, PortC, NoPwmChannel, 7);
 - 
 - SetupGpio(255, PortB, NoPwmChannel, 0);
 - 
 - typedef Gpio<PortB, 7> SpiSCK;
 - typedef Gpio<PortB, 6> SpiMISO;
 - typedef Gpio<PortB, 5> SpiMOSI;
 - typedef Gpio<PortB, 4> SpiSS;
 - 
 - typedef Gpio<PortB, 0> UartSpi0XCK;
 - typedef Gpio<PortD, 1> UartSpi0TX;
 - typedef Gpio<PortD, 0> UartSpi0RX;
 - 
 - typedef Gpio<PortD, 4> UartSpi1XCK;
 - typedef Gpio<PortD, 3> UartSpi1TX;
 - typedef Gpio<PortD, 2> UartSpi1RX;
 - 
 - #define HAS_USART0
 - #define HAS_USART1
 - 
 - #if defined(ATMEGA1284P) || defined(ATMEGA640) || defined(ATMEGA1280)  \
 - 	|| defined(ATMEGA2560)
 - #define HAS_TIMER3
 - #endif
 - 
 - #elif defined (ATMEGA640) || defined(ATMEGA1280) || defined(ATMEGA2560)
 - 
 - SetupGpio(0,  PortB, NoPwmChannel, 0);
 - SetupGpio(1,  PortB, NoPwmChannel, 1);
 - SetupGpio(2,  PortB, NoPwmChannel, 2);
 - SetupGpio(3,  PortB, NoPwmChannel, 3);
 - SetupGpio(4,  PortB, PwmChannel2A, 4);
 - SetupGpio(5,  PortB, PwmChannel1A, 5);
 - SetupGpio(6,  PortB, PwmChannel1B, 6);
 - SetupGpio(7,  PortB, PwmChannel0A, 7);
 - 
 - SetupGpio(8,  PortD, NoPwmChannel, 0);
 - SetupGpio(9,  PortD, NoPwmChannel, 1);
 - SetupGpio(10, PortD, NoPwmChannel, 2);
 - SetupGpio(11, PortD, NoPwmChannel, 3);
 - SetupGpio(12, PortD, NoPwmChannel, 4);
 - SetupGpio(13, PortD, NoPwmChannel, 5);
 - SetupGpio(14, PortD, NoPwmChannel, 6);
 - SetupGpio(15, PortD, NoPwmChannel, 7);
 - 
 - SetupGpio(16, PortC, NoPwmChannel, 0);
 - SetupGpio(17, PortC, NoPwmChannel, 1);
 - SetupGpio(18, PortC, NoPwmChannel, 2);
 - SetupGpio(19, PortC, NoPwmChannel, 3);
 - SetupGpio(20, PortC, NoPwmChannel, 4);
 - SetupGpio(21, PortC, NoPwmChannel, 5);
 - SetupGpio(22, PortC, NoPwmChannel, 6);
 - SetupGpio(23, PortC, NoPwmChannel, 7);
 - 
 - SetupGpio(24, PortE, NoPwmChannel, 0);
 - SetupGpio(25, PortE, NoPwmChannel, 1);
 - SetupGpio(26, PortE, NoPwmChannel, 2);
 - SetupGpio(27, PortE, NoPwmChannel, 3);
 - SetupGpio(28, PortE, NoPwmChannel, 4);
 - SetupGpio(29, PortE, NoPwmChannel, 5);
 - SetupGpio(30, PortE, NoPwmChannel, 6);
 - SetupGpio(31, PortE, NoPwmChannel, 7);
 - 
 - SetupGpio(32, PortF, NoPwmChannel, 0);
 - SetupGpio(33, PortF, NoPwmChannel, 1);
 - SetupGpio(34, PortF, NoPwmChannel, 2);
 - SetupGpio(35, PortF, NoPwmChannel, 3);
 - SetupGpio(36, PortF, NoPwmChannel, 4);
 - SetupGpio(37, PortF, NoPwmChannel, 5);
 - SetupGpio(38, PortF, NoPwmChannel, 6);
 - SetupGpio(39, PortF, NoPwmChannel, 7);
 - 
 - SetupGpio(40, PortG, NoPwmChannel, 0);
 - SetupGpio(41, PortG, NoPwmChannel, 1);
 - SetupGpio(42, PortG, NoPwmChannel, 2);
 - SetupGpio(43, PortG, NoPwmChannel, 3);
 - SetupGpio(44, PortG, NoPwmChannel, 4);
 - SetupGpio(45, PortG, NoPwmChannel, 5);
 - SetupGpio(46, PortG, NoPwmChannel, 6);
 - SetupGpio(47, PortG, NoPwmChannel, 7);
 - 
 - SetupGpio(48, PortH, NoPwmChannel, 0);
 - SetupGpio(49, PortH, NoPwmChannel, 1);
 - SetupGpio(50, PortH, NoPwmChannel, 2);
 - SetupGpio(51, PortH, NoPwmChannel, 3);
 - SetupGpio(52, PortH, NoPwmChannel, 4);
 - SetupGpio(53, PortH, NoPwmChannel, 5);
 - SetupGpio(54, PortH, NoPwmChannel, 6);
 - SetupGpio(55, PortH, NoPwmChannel, 7);
 - 
 - SetupGpio(56, PortJ, NoPwmChannel, 0);
 - SetupGpio(57, PortJ, NoPwmChannel, 1);
 - SetupGpio(58, PortJ, NoPwmChannel, 2);
 - SetupGpio(59, PortJ, NoPwmChannel, 3);
 - SetupGpio(60, PortJ, NoPwmChannel, 4);
 - SetupGpio(61, PortJ, NoPwmChannel, 5);
 - SetupGpio(62, PortJ, NoPwmChannel, 6);
 - SetupGpio(63, PortJ, NoPwmChannel, 7);
 - 
 - SetupGpio(64, PortK, NoPwmChannel, 0);
 - SetupGpio(65, PortK, NoPwmChannel, 1);
 - SetupGpio(66, PortK, NoPwmChannel, 2);
 - SetupGpio(67, PortK, NoPwmChannel, 3);
 - SetupGpio(68, PortK, NoPwmChannel, 4);
 - SetupGpio(69, PortK, NoPwmChannel, 5);
 - SetupGpio(70, PortK, NoPwmChannel, 6);
 - SetupGpio(71, PortK, NoPwmChannel, 7);
 - 
 - SetupGpio(72, PortL, NoPwmChannel, 0);
 - SetupGpio(73, PortL, NoPwmChannel, 1);
 - SetupGpio(74, PortL, NoPwmChannel, 2);
 - SetupGpio(75, PortL, NoPwmChannel, 3);
 - SetupGpio(76, PortL, NoPwmChannel, 4);
 - SetupGpio(77, PortL, NoPwmChannel, 5);
 - SetupGpio(78, PortL, NoPwmChannel, 6);
 - SetupGpio(79, PortL, NoPwmChannel, 7);
 - 
 - typedef Gpio<PortB, 0> SpiSS;
 - typedef Gpio<PortB, 1> SpiSCK;
 - typedef Gpio<PortB, 2> SpiMOSI;
 - typedef Gpio<PortB, 3> SpiMISO;
 - 
 - typedef Gpio<PortE, 2> UartSpi0XCK;
 - typedef Gpio<PortE, 1> UartSpi0TX;
 - typedef Gpio<PortE, 0> UartSpi0RX;
 - 
 - typedef Gpio<PortD, 5> UartSpi1XCK;
 - typedef Gpio<PortD, 3> UartSpi1TX;
 - typedef Gpio<PortD, 2> UartSpi1RX;
 - 
 - typedef Gpio<PortH, 2> UartSpi2XCK;
 - typedef Gpio<PortH, 1> UartSpi2TX;
 - typedef Gpio<PortH, 0> UartSpi2RX;
 - 
 - typedef Gpio<PortJ, 2> UartSpi3XCK;
 - typedef Gpio<PortJ, 1> UartSpi3TX;
 - typedef Gpio<PortJ, 0> UartSpi3RX;
 - 
 - #define HAS_USART0
 - #define HAS_USART1
 - #define HAS_USART2
 - #define HAS_USART3
 - 
 - #else
 - 
 - #error Unsupported MCU type
 - 
 - #endif
 - 
 - // Two specializations of the numbered pin template, one which clears the timer
 - // for each access to the PWM pins, as does the original Arduino wire lib,
 - // the other that does not (use with care!).
 - template<int n>
 - struct NumberedGpio {
 -   typedef typename NumberedGpioInternal<n>::Impl Impl;
 -   static void High() { Impl::High(); }
 -   static void Low() { Impl::Low(); }
 -   static void set_mode(uint8_t mode) { Impl::set_mode(mode); }
 -   static void set_value(uint8_t value) { Impl::set_value(value); }
 -   static void set_pwm_value(uint8_t value) { Impl::set_pwm_value(value); }
 -   static uint8_t value() { return Impl::value(); }
 - };
 - 
 - template<int n>
 - struct PwmOutput {
 -   enum {
 -     buffer_size = 0,
 -     data_size = 8,
 -   };
 -   static void Init() {
 -     NumberedGpio<n>::set_mode(PWM_OUTPUT);
 -   }
 -   static void Write(uint8_t value) {
 -     return NumberedGpio<n>::set_pwm_value(value);
 -   }
 -   static void Stop() {
 -     NumberedGpio<n>::Impl::Pwm::Stop();
 -   }
 -   static void Start() {
 -     NumberedGpio<n>::Impl::Pwm::Start();
 -   }
 - };
 - 
 - }  // namespace avrlib
 - 
 - #endif   // AVRLIB_GPIO_H_
 
 
  |