Fast GPIO using C++ templates. Now with port I/O.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastIO.h Source File

FastIO.h

00001 #ifndef __FAST_IO_H
00002 #define __FAST_IO_H
00003 
00004 #include "mbed.h"
00005 
00006 // Super-fast DigitalOut-like class for mbed
00007 //   by Igor Skochinsky
00008 
00009 // includes FastOut, FastPortOut and MaskedPortOut classes
00010 // usage:
00011 //   FastOut<LED2> led2;
00012 //   FastPortOut<Port0, LED_MASK> ledport2;
00013 //   MaskedPortOut<Port0, LED_MASK> ledport3;
00014 //   led2 = 1;
00015 //   ledport2 = LED_MASK;
00016 //   ledport3 = LED_MASK;
00017 // MaskedPortOut works the same way as FastPortOut, but it pre-sets the pin mask so that write can be done in one operation
00018 // this makes things faster but you can't control other pins of the port, even with other classes
00019 
00020 
00021 // pin definitions in PinNames.h start from LPC_GPIO0_BASE for P0_0 and there are 32 pins to a port (0 to 31)
00022 // Thus:
00023 // pin = LPC_GPIO0_BASE + port * 32 + bit
00024 // port = (pin - LPC_GPIO0_BASE) / 32
00025 // bit  = (pin - LPC_GPIO0_BASE) % 32
00026 
00027 #define PORTNO(pin) (((pin) - P0_0)/32)
00028 #define BITNO(pin)  (((pin) - P0_0)%32)
00029 
00030 // calculate the GPIO port definition for the pin
00031 // we rely on the fact that port structs are 0x20 bytes apart
00032 #define PORTDEF(pin) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + PORTNO(pin)*0x20))
00033 
00034 #define PORTDEFPORT(port) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + port*0x20))
00035 
00036 // calculate the mask for the pin's bit in the port
00037 #define PINMASK(pin) (1UL << BITNO(pin))
00038 
00039 // each port takes two PINSEL registers (8 bytes or 64 bits)
00040 // so there are 16 pins per PINSEL
00041 #define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
00042 #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
00043 
00044 // usage: FastOut<LED2> led2;
00045 // then use the same assignment operators as with DigitalOut
00046 template <PinName pin> class FastOut
00047 {
00048 public:
00049     FastOut()
00050     {
00051         // set PINSEL bits to 0b00 (GPIO)
00052         PINSELREG(pin) &= ~PINSELMASK(pin, 3);
00053         // set FIODIR bit to 1 (output)
00054         PORTDEF(pin)->FIODIR |= PINMASK(pin);
00055     }
00056     void write(int value)
00057     { 
00058         if ( value )
00059             PORTDEF(pin)->FIOSET = PINMASK(pin);
00060         else
00061             PORTDEF(pin)->FIOCLR = PINMASK(pin);
00062     } 
00063     int read()
00064     {
00065         return PORTDEF(pin)->FIOPIN & PINMASK(pin) != 0;
00066     }
00067     FastOut& operator= (int value) { write(value); return *this; };
00068     FastOut& operator= (FastOut& rhs) { return write(rhs.read()); };
00069     operator int() { return read(); };
00070 };
00071 
00072 #define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
00073 #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
00074 
00075 // usage: FastPortOut<Port0, mask> led2;
00076 // then use the same assignment operators as with DigitalOut
00077 template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class FastPortOut
00078 {
00079 public:
00080     FastPortOut()
00081     {
00082         // init pins selected by the mask
00083         uint32_t pin = LPC_GPIO0_BASE + port * 32;
00084         for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
00085         {
00086             if ( pinmask & 1 )
00087             {
00088                 // set PINSEL bits to 0b00 (GPIO)
00089                 PINSELREG(pin) &= ~PINSELMASK(pin, 3);
00090                 // set FIODIR bit to 1 (output)
00091                 PORTDEF(pin)->FIODIR |= PINMASK(pin);
00092             }
00093             pin++;
00094         }
00095     }
00096     void write(int value)
00097     {
00098         PORTDEFPORT(port)->FIOSET = value & mask;
00099         PORTDEFPORT(port)->FIOCLR = ~value & mask;
00100     } 
00101     int read()
00102     {
00103         return PORTDEFPORT(port)->FIOPIN & mask;
00104     }
00105     FastPortOut& operator= (int value) { write(value); return *this; };
00106     FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); };
00107     operator int() { return read(); };
00108 };
00109 
00110 // usage: MaskedPortOut<Port0, mask> led2;
00111 // then use the same assignment operators as with DigitalOut
00112 template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class MaskedPortOut
00113 {
00114 public:
00115     MaskedPortOut()
00116     {
00117         // init pins selected by the mask
00118         uint32_t pin = LPC_GPIO0_BASE + port * 32;
00119         for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
00120         {
00121             if ( pinmask & 1 )
00122             {
00123                 // set PINSEL bits to 0b00 (GPIO)
00124                 PINSELREG(pin) &= ~PINSELMASK(pin, 3);
00125                 // set FIODIR bit to 1 (output)
00126                 PORTDEF(pin)->FIODIR |= PINMASK(pin);
00127             }
00128             pin++;
00129         }
00130         // set mask
00131         PORTDEFPORT(port)->FIOMASK = mask;
00132     }
00133     void write(int value)
00134     {
00135         PORTDEFPORT(port)->FIOPIN = value;
00136     } 
00137     int read()
00138     {
00139         return PORTDEFPORT(port)->FIOPIN;
00140     }
00141     MaskedPortOut& operator= (int value) { write(value); return *this; };
00142     MaskedPortOut& operator= (MaskedPortOut& rhs) { return write(rhs.read()); };
00143     operator int() { return read(); };
00144 };
00145 
00146 #endif