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

Dependencies:   mbed

Committer:
igorsk
Date:
Tue May 25 08:35:39 2010 +0000
Revision:
4:b8e40f2a0aac
Parent:
3:8d217a0bb245

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igorsk 1:8064f8b8cf82 1 #ifndef __FAST_IO_H
igorsk 1:8064f8b8cf82 2 #define __FAST_IO_H
igorsk 1:8064f8b8cf82 3
igorsk 1:8064f8b8cf82 4 #include "mbed.h"
igorsk 1:8064f8b8cf82 5
igorsk 1:8064f8b8cf82 6 // Super-fast DigitalOut-like class for mbed
igorsk 1:8064f8b8cf82 7 // by Igor Skochinsky
igorsk 1:8064f8b8cf82 8
igorsk 3:8d217a0bb245 9 // includes FastOut, FastPortOut and MaskedPortOut classes
igorsk 3:8d217a0bb245 10 // usage:
igorsk 3:8d217a0bb245 11 // FastOut<LED2> led2;
igorsk 3:8d217a0bb245 12 // FastPortOut<Port0, LED_MASK> ledport2;
igorsk 3:8d217a0bb245 13 // MaskedPortOut<Port0, LED_MASK> ledport3;
igorsk 3:8d217a0bb245 14 // led2 = 1;
igorsk 3:8d217a0bb245 15 // ledport2 = LED_MASK;
igorsk 3:8d217a0bb245 16 // ledport3 = LED_MASK;
igorsk 3:8d217a0bb245 17 // MaskedPortOut works the same way as FastPortOut, but it pre-sets the pin mask so that write can be done in one operation
igorsk 3:8d217a0bb245 18 // this makes things faster but you can't control other pins of the port, even with other classes
igorsk 3:8d217a0bb245 19
igorsk 3:8d217a0bb245 20
igorsk 1:8064f8b8cf82 21 // pin definitions in PinNames.h start from LPC_GPIO0_BASE for P0_0 and there are 32 pins to a port (0 to 31)
igorsk 1:8064f8b8cf82 22 // Thus:
igorsk 1:8064f8b8cf82 23 // pin = LPC_GPIO0_BASE + port * 32 + bit
igorsk 1:8064f8b8cf82 24 // port = (pin - LPC_GPIO0_BASE) / 32
igorsk 1:8064f8b8cf82 25 // bit = (pin - LPC_GPIO0_BASE) % 32
igorsk 1:8064f8b8cf82 26
igorsk 1:8064f8b8cf82 27 #define PORTNO(pin) (((pin) - P0_0)/32)
igorsk 1:8064f8b8cf82 28 #define BITNO(pin) (((pin) - P0_0)%32)
igorsk 1:8064f8b8cf82 29
igorsk 1:8064f8b8cf82 30 // calculate the GPIO port definition for the pin
igorsk 1:8064f8b8cf82 31 // we rely on the fact that port structs are 0x20 bytes apart
igorsk 1:8064f8b8cf82 32 #define PORTDEF(pin) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + PORTNO(pin)*0x20))
igorsk 1:8064f8b8cf82 33
igorsk 1:8064f8b8cf82 34 #define PORTDEFPORT(port) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + port*0x20))
igorsk 1:8064f8b8cf82 35
igorsk 1:8064f8b8cf82 36 // calculate the mask for the pin's bit in the port
igorsk 1:8064f8b8cf82 37 #define PINMASK(pin) (1UL << BITNO(pin))
igorsk 1:8064f8b8cf82 38
igorsk 1:8064f8b8cf82 39 // each port takes two PINSEL registers (8 bytes or 64 bits)
igorsk 1:8064f8b8cf82 40 // so there are 16 pins per PINSEL
igorsk 1:8064f8b8cf82 41 #define PINSELREG(pin) (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
igorsk 1:8064f8b8cf82 42 #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
igorsk 1:8064f8b8cf82 43
igorsk 1:8064f8b8cf82 44 // usage: FastOut<LED2> led2;
igorsk 1:8064f8b8cf82 45 // then use the same assignment operators as with DigitalOut
igorsk 1:8064f8b8cf82 46 template <PinName pin> class FastOut
igorsk 1:8064f8b8cf82 47 {
igorsk 1:8064f8b8cf82 48 public:
igorsk 1:8064f8b8cf82 49 FastOut()
igorsk 1:8064f8b8cf82 50 {
igorsk 1:8064f8b8cf82 51 // set PINSEL bits to 0b00 (GPIO)
igorsk 1:8064f8b8cf82 52 PINSELREG(pin) &= ~PINSELMASK(pin, 3);
igorsk 1:8064f8b8cf82 53 // set FIODIR bit to 1 (output)
igorsk 1:8064f8b8cf82 54 PORTDEF(pin)->FIODIR |= PINMASK(pin);
igorsk 1:8064f8b8cf82 55 }
igorsk 1:8064f8b8cf82 56 void write(int value)
igorsk 1:8064f8b8cf82 57 {
igorsk 1:8064f8b8cf82 58 if ( value )
igorsk 1:8064f8b8cf82 59 PORTDEF(pin)->FIOSET = PINMASK(pin);
igorsk 1:8064f8b8cf82 60 else
igorsk 1:8064f8b8cf82 61 PORTDEF(pin)->FIOCLR = PINMASK(pin);
igorsk 1:8064f8b8cf82 62 }
igorsk 1:8064f8b8cf82 63 int read()
igorsk 1:8064f8b8cf82 64 {
igorsk 1:8064f8b8cf82 65 return PORTDEF(pin)->FIOPIN & PINMASK(pin) != 0;
igorsk 1:8064f8b8cf82 66 }
igorsk 1:8064f8b8cf82 67 FastOut& operator= (int value) { write(value); return *this; };
igorsk 1:8064f8b8cf82 68 FastOut& operator= (FastOut& rhs) { return write(rhs.read()); };
igorsk 1:8064f8b8cf82 69 operator int() { return read(); };
igorsk 1:8064f8b8cf82 70 };
igorsk 1:8064f8b8cf82 71
igorsk 1:8064f8b8cf82 72 #define PINSELREG(pin) (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
igorsk 1:8064f8b8cf82 73 #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
igorsk 1:8064f8b8cf82 74
igorsk 3:8d217a0bb245 75 // usage: FastPortOut<Port0, mask> led2;
igorsk 1:8064f8b8cf82 76 // then use the same assignment operators as with DigitalOut
igorsk 1:8064f8b8cf82 77 template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class FastPortOut
igorsk 1:8064f8b8cf82 78 {
igorsk 1:8064f8b8cf82 79 public:
igorsk 1:8064f8b8cf82 80 FastPortOut()
igorsk 1:8064f8b8cf82 81 {
igorsk 1:8064f8b8cf82 82 // init pins selected by the mask
igorsk 1:8064f8b8cf82 83 uint32_t pin = LPC_GPIO0_BASE + port * 32;
igorsk 1:8064f8b8cf82 84 for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
igorsk 1:8064f8b8cf82 85 {
igorsk 1:8064f8b8cf82 86 if ( pinmask & 1 )
igorsk 1:8064f8b8cf82 87 {
igorsk 1:8064f8b8cf82 88 // set PINSEL bits to 0b00 (GPIO)
igorsk 1:8064f8b8cf82 89 PINSELREG(pin) &= ~PINSELMASK(pin, 3);
igorsk 1:8064f8b8cf82 90 // set FIODIR bit to 1 (output)
igorsk 1:8064f8b8cf82 91 PORTDEF(pin)->FIODIR |= PINMASK(pin);
igorsk 1:8064f8b8cf82 92 }
igorsk 1:8064f8b8cf82 93 pin++;
igorsk 1:8064f8b8cf82 94 }
igorsk 1:8064f8b8cf82 95 }
igorsk 1:8064f8b8cf82 96 void write(int value)
igorsk 1:8064f8b8cf82 97 {
igorsk 2:9c4a8c01862c 98 PORTDEFPORT(port)->FIOSET = value & mask;
igorsk 4:b8e40f2a0aac 99 PORTDEFPORT(port)->FIOCLR = ~value & mask;
igorsk 1:8064f8b8cf82 100 }
igorsk 1:8064f8b8cf82 101 int read()
igorsk 1:8064f8b8cf82 102 {
igorsk 1:8064f8b8cf82 103 return PORTDEFPORT(port)->FIOPIN & mask;
igorsk 1:8064f8b8cf82 104 }
igorsk 1:8064f8b8cf82 105 FastPortOut& operator= (int value) { write(value); return *this; };
igorsk 1:8064f8b8cf82 106 FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); };
igorsk 1:8064f8b8cf82 107 operator int() { return read(); };
igorsk 1:8064f8b8cf82 108 };
igorsk 1:8064f8b8cf82 109
igorsk 3:8d217a0bb245 110 // usage: MaskedPortOut<Port0, mask> led2;
igorsk 3:8d217a0bb245 111 // then use the same assignment operators as with DigitalOut
igorsk 3:8d217a0bb245 112 template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class MaskedPortOut
igorsk 3:8d217a0bb245 113 {
igorsk 3:8d217a0bb245 114 public:
igorsk 3:8d217a0bb245 115 MaskedPortOut()
igorsk 3:8d217a0bb245 116 {
igorsk 3:8d217a0bb245 117 // init pins selected by the mask
igorsk 3:8d217a0bb245 118 uint32_t pin = LPC_GPIO0_BASE + port * 32;
igorsk 3:8d217a0bb245 119 for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
igorsk 3:8d217a0bb245 120 {
igorsk 3:8d217a0bb245 121 if ( pinmask & 1 )
igorsk 3:8d217a0bb245 122 {
igorsk 3:8d217a0bb245 123 // set PINSEL bits to 0b00 (GPIO)
igorsk 3:8d217a0bb245 124 PINSELREG(pin) &= ~PINSELMASK(pin, 3);
igorsk 3:8d217a0bb245 125 // set FIODIR bit to 1 (output)
igorsk 3:8d217a0bb245 126 PORTDEF(pin)->FIODIR |= PINMASK(pin);
igorsk 3:8d217a0bb245 127 }
igorsk 3:8d217a0bb245 128 pin++;
igorsk 3:8d217a0bb245 129 }
igorsk 3:8d217a0bb245 130 // set mask
igorsk 3:8d217a0bb245 131 PORTDEFPORT(port)->FIOMASK = mask;
igorsk 3:8d217a0bb245 132 }
igorsk 3:8d217a0bb245 133 void write(int value)
igorsk 3:8d217a0bb245 134 {
igorsk 3:8d217a0bb245 135 PORTDEFPORT(port)->FIOPIN = value;
igorsk 3:8d217a0bb245 136 }
igorsk 3:8d217a0bb245 137 int read()
igorsk 3:8d217a0bb245 138 {
igorsk 3:8d217a0bb245 139 return PORTDEFPORT(port)->FIOPIN;
igorsk 3:8d217a0bb245 140 }
igorsk 3:8d217a0bb245 141 MaskedPortOut& operator= (int value) { write(value); return *this; };
igorsk 3:8d217a0bb245 142 MaskedPortOut& operator= (MaskedPortOut& rhs) { return write(rhs.read()); };
igorsk 3:8d217a0bb245 143 operator int() { return read(); };
igorsk 3:8d217a0bb245 144 };
igorsk 3:8d217a0bb245 145
igorsk 1:8064f8b8cf82 146 #endif