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

Dependencies:   mbed

Committer:
igorsk
Date:
Sat May 22 22:58:38 2010 +0000
Revision:
1:8064f8b8cf82
Child:
2:9c4a8c01862c

        

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 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 1:8064f8b8cf82 86 if ( value & mask )
igorsk 1:8064f8b8cf82 87 PORTDEFPORT(port)->FIOSET = value & mask;
igorsk 1:8064f8b8cf82 88 if ( value & ~mask )
igorsk 1:8064f8b8cf82 89 PORTDEFPORT(port)->FIOCLR = value & ~mask;
igorsk 1:8064f8b8cf82 90 }
igorsk 1:8064f8b8cf82 91 int read()
igorsk 1:8064f8b8cf82 92 {
igorsk 1:8064f8b8cf82 93 return PORTDEFPORT(port)->FIOPIN & mask;
igorsk 1:8064f8b8cf82 94 }
igorsk 1:8064f8b8cf82 95 FastPortOut& operator= (int value) { write(value); return *this; };
igorsk 1:8064f8b8cf82 96 FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); };
igorsk 1:8064f8b8cf82 97 operator int() { return read(); };
igorsk 1:8064f8b8cf82 98 };
igorsk 1:8064f8b8cf82 99
igorsk 1:8064f8b8cf82 100 #endif