Igor Skochinsky
/
FastIO
Fast GPIO using C++ templates. Now with port I/O.
FastIO.h@2:9c4a8c01862c, 2010-05-22 (annotated)
- Committer:
- igorsk
- Date:
- Sat May 22 23:13:55 2010 +0000
- Revision:
- 2:9c4a8c01862c
- Parent:
- 1:8064f8b8cf82
- Child:
- 3:8d217a0bb245
Who changed what in which revision?
User | Revision | Line number | New 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 | 1:8064f8b8cf82 | 9 | // 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 | 10 | // Thus: |
igorsk | 1:8064f8b8cf82 | 11 | // pin = LPC_GPIO0_BASE + port * 32 + bit |
igorsk | 1:8064f8b8cf82 | 12 | // port = (pin - LPC_GPIO0_BASE) / 32 |
igorsk | 1:8064f8b8cf82 | 13 | // bit = (pin - LPC_GPIO0_BASE) % 32 |
igorsk | 1:8064f8b8cf82 | 14 | |
igorsk | 1:8064f8b8cf82 | 15 | #define PORTNO(pin) (((pin) - P0_0)/32) |
igorsk | 1:8064f8b8cf82 | 16 | #define BITNO(pin) (((pin) - P0_0)%32) |
igorsk | 1:8064f8b8cf82 | 17 | |
igorsk | 1:8064f8b8cf82 | 18 | // calculate the GPIO port definition for the pin |
igorsk | 1:8064f8b8cf82 | 19 | // we rely on the fact that port structs are 0x20 bytes apart |
igorsk | 1:8064f8b8cf82 | 20 | #define PORTDEF(pin) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + PORTNO(pin)*0x20)) |
igorsk | 1:8064f8b8cf82 | 21 | |
igorsk | 1:8064f8b8cf82 | 22 | #define PORTDEFPORT(port) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + port*0x20)) |
igorsk | 1:8064f8b8cf82 | 23 | |
igorsk | 1:8064f8b8cf82 | 24 | // calculate the mask for the pin's bit in the port |
igorsk | 1:8064f8b8cf82 | 25 | #define PINMASK(pin) (1UL << BITNO(pin)) |
igorsk | 1:8064f8b8cf82 | 26 | |
igorsk | 1:8064f8b8cf82 | 27 | // each port takes two PINSEL registers (8 bytes or 64 bits) |
igorsk | 1:8064f8b8cf82 | 28 | // so there are 16 pins per PINSEL |
igorsk | 1:8064f8b8cf82 | 29 | #define PINSELREG(pin) (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16))) |
igorsk | 1:8064f8b8cf82 | 30 | #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) ) |
igorsk | 1:8064f8b8cf82 | 31 | |
igorsk | 1:8064f8b8cf82 | 32 | // usage: FastOut<LED2> led2; |
igorsk | 1:8064f8b8cf82 | 33 | // then use the same assignment operators as with DigitalOut |
igorsk | 1:8064f8b8cf82 | 34 | template <PinName pin> class FastOut |
igorsk | 1:8064f8b8cf82 | 35 | { |
igorsk | 1:8064f8b8cf82 | 36 | public: |
igorsk | 1:8064f8b8cf82 | 37 | FastOut() |
igorsk | 1:8064f8b8cf82 | 38 | { |
igorsk | 1:8064f8b8cf82 | 39 | // set PINSEL bits to 0b00 (GPIO) |
igorsk | 1:8064f8b8cf82 | 40 | PINSELREG(pin) &= ~PINSELMASK(pin, 3); |
igorsk | 1:8064f8b8cf82 | 41 | // set FIODIR bit to 1 (output) |
igorsk | 1:8064f8b8cf82 | 42 | PORTDEF(pin)->FIODIR |= PINMASK(pin); |
igorsk | 1:8064f8b8cf82 | 43 | } |
igorsk | 1:8064f8b8cf82 | 44 | void write(int value) |
igorsk | 1:8064f8b8cf82 | 45 | { |
igorsk | 1:8064f8b8cf82 | 46 | if ( value ) |
igorsk | 1:8064f8b8cf82 | 47 | PORTDEF(pin)->FIOSET = PINMASK(pin); |
igorsk | 1:8064f8b8cf82 | 48 | else |
igorsk | 1:8064f8b8cf82 | 49 | PORTDEF(pin)->FIOCLR = PINMASK(pin); |
igorsk | 1:8064f8b8cf82 | 50 | } |
igorsk | 1:8064f8b8cf82 | 51 | int read() |
igorsk | 1:8064f8b8cf82 | 52 | { |
igorsk | 1:8064f8b8cf82 | 53 | return PORTDEF(pin)->FIOPIN & PINMASK(pin) != 0; |
igorsk | 1:8064f8b8cf82 | 54 | } |
igorsk | 1:8064f8b8cf82 | 55 | FastOut& operator= (int value) { write(value); return *this; }; |
igorsk | 1:8064f8b8cf82 | 56 | FastOut& operator= (FastOut& rhs) { return write(rhs.read()); }; |
igorsk | 1:8064f8b8cf82 | 57 | operator int() { return read(); }; |
igorsk | 1:8064f8b8cf82 | 58 | }; |
igorsk | 1:8064f8b8cf82 | 59 | |
igorsk | 1:8064f8b8cf82 | 60 | #define PINSELREG(pin) (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16))) |
igorsk | 1:8064f8b8cf82 | 61 | #define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) ) |
igorsk | 1:8064f8b8cf82 | 62 | |
igorsk | 1:8064f8b8cf82 | 63 | // usage: FastPortOut<0> led2; |
igorsk | 1:8064f8b8cf82 | 64 | // then use the same assignment operators as with DigitalOut |
igorsk | 1:8064f8b8cf82 | 65 | template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class FastPortOut |
igorsk | 1:8064f8b8cf82 | 66 | { |
igorsk | 1:8064f8b8cf82 | 67 | public: |
igorsk | 1:8064f8b8cf82 | 68 | FastPortOut() |
igorsk | 1:8064f8b8cf82 | 69 | { |
igorsk | 1:8064f8b8cf82 | 70 | // init pins selected by the mask |
igorsk | 1:8064f8b8cf82 | 71 | uint32_t pin = LPC_GPIO0_BASE + port * 32; |
igorsk | 1:8064f8b8cf82 | 72 | for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 ) |
igorsk | 1:8064f8b8cf82 | 73 | { |
igorsk | 1:8064f8b8cf82 | 74 | if ( pinmask & 1 ) |
igorsk | 1:8064f8b8cf82 | 75 | { |
igorsk | 1:8064f8b8cf82 | 76 | // set PINSEL bits to 0b00 (GPIO) |
igorsk | 1:8064f8b8cf82 | 77 | PINSELREG(pin) &= ~PINSELMASK(pin, 3); |
igorsk | 1:8064f8b8cf82 | 78 | // set FIODIR bit to 1 (output) |
igorsk | 1:8064f8b8cf82 | 79 | PORTDEF(pin)->FIODIR |= PINMASK(pin); |
igorsk | 1:8064f8b8cf82 | 80 | } |
igorsk | 1:8064f8b8cf82 | 81 | pin++; |
igorsk | 1:8064f8b8cf82 | 82 | } |
igorsk | 1:8064f8b8cf82 | 83 | } |
igorsk | 1:8064f8b8cf82 | 84 | void write(int value) |
igorsk | 1:8064f8b8cf82 | 85 | { |
igorsk | 2:9c4a8c01862c | 86 | PORTDEFPORT(port)->FIOSET = value & mask; |
igorsk | 2:9c4a8c01862c | 87 | PORTDEFPORT(port)->FIOCLR = value & ~mask; |
igorsk | 1:8064f8b8cf82 | 88 | } |
igorsk | 1:8064f8b8cf82 | 89 | int read() |
igorsk | 1:8064f8b8cf82 | 90 | { |
igorsk | 1:8064f8b8cf82 | 91 | return PORTDEFPORT(port)->FIOPIN & mask; |
igorsk | 1:8064f8b8cf82 | 92 | } |
igorsk | 1:8064f8b8cf82 | 93 | FastPortOut& operator= (int value) { write(value); return *this; }; |
igorsk | 1:8064f8b8cf82 | 94 | FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); }; |
igorsk | 1:8064f8b8cf82 | 95 | operator int() { return read(); }; |
igorsk | 1:8064f8b8cf82 | 96 | }; |
igorsk | 1:8064f8b8cf82 | 97 | |
igorsk | 1:8064f8b8cf82 | 98 | #endif |