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

Dependencies:   mbed

Revision:
1:8064f8b8cf82
Child:
2:9c4a8c01862c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastIO.h	Sat May 22 22:58:38 2010 +0000
@@ -0,0 +1,100 @@
+#ifndef __FAST_IO_H
+#define __FAST_IO_H
+
+#include "mbed.h"
+
+// Super-fast DigitalOut-like class for mbed
+//   by Igor Skochinsky
+
+// pin definitions in PinNames.h start from LPC_GPIO0_BASE for P0_0 and there are 32 pins to a port (0 to 31)
+// Thus:
+// pin = LPC_GPIO0_BASE + port * 32 + bit
+// port = (pin - LPC_GPIO0_BASE) / 32
+// bit  = (pin - LPC_GPIO0_BASE) % 32
+
+#define PORTNO(pin) (((pin) - P0_0)/32)
+#define BITNO(pin)  (((pin) - P0_0)%32)
+
+// calculate the GPIO port definition for the pin
+// we rely on the fact that port structs are 0x20 bytes apart
+#define PORTDEF(pin) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + PORTNO(pin)*0x20))
+
+#define PORTDEFPORT(port) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + port*0x20))
+
+// calculate the mask for the pin's bit in the port
+#define PINMASK(pin) (1UL << BITNO(pin))
+
+// each port takes two PINSEL registers (8 bytes or 64 bits)
+// so there are 16 pins per PINSEL
+#define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
+#define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
+
+// usage: FastOut<LED2> led2;
+// then use the same assignment operators as with DigitalOut
+template <PinName pin> class FastOut
+{
+public:
+    FastOut()
+    {
+        // set PINSEL bits to 0b00 (GPIO)
+        PINSELREG(pin) &= ~PINSELMASK(pin, 3);
+        // set FIODIR bit to 1 (output)
+        PORTDEF(pin)->FIODIR |= PINMASK(pin);
+    }
+    void write(int value)
+    { 
+        if ( value )
+            PORTDEF(pin)->FIOSET = PINMASK(pin);
+        else
+            PORTDEF(pin)->FIOCLR = PINMASK(pin);
+    } 
+    int read()
+    {
+        return PORTDEF(pin)->FIOPIN & PINMASK(pin) != 0;
+    }
+    FastOut& operator= (int value) { write(value); return *this; };
+    FastOut& operator= (FastOut& rhs) { return write(rhs.read()); };
+    operator int() { return read(); };
+};
+
+#define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
+#define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
+
+// usage: FastPortOut<0> led2;
+// then use the same assignment operators as with DigitalOut
+template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class FastPortOut
+{
+public:
+    FastPortOut()
+    {
+        // init pins selected by the mask
+        uint32_t pin = LPC_GPIO0_BASE + port * 32;
+        for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
+        {
+            if ( pinmask & 1 )
+            {
+                // set PINSEL bits to 0b00 (GPIO)
+                PINSELREG(pin) &= ~PINSELMASK(pin, 3);
+                // set FIODIR bit to 1 (output)
+                PORTDEF(pin)->FIODIR |= PINMASK(pin);
+            }
+            pin++;
+        }
+    }
+    void write(int value)
+    {
+        if ( value & mask )
+            PORTDEFPORT(port)->FIOSET = value & mask;
+        if ( value & ~mask )
+            PORTDEFPORT(port)->FIOCLR = value & ~mask;
+    } 
+    int read()
+    {
+        return PORTDEFPORT(port)->FIOPIN & mask;
+    }
+    FastPortOut& operator= (int value) { write(value); return *this; };
+    FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); };
+    operator int() { return read(); };
+};
+
+#endif
\ No newline at end of file