Igor Skochinsky
/
FastIO
Fast GPIO using C++ templates. Now with port I/O.
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Mon Jul 18 2022 17:38:08 by 1.7.2