Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Revision:
73:4e8ce0b18915
Parent:
48:058ace2aed1d
Child:
77:0b96f6867312
--- a/TinyDigitalIn.h	Wed Jan 04 20:14:12 2017 +0000
+++ b/TinyDigitalIn.h	Sat Jan 21 19:48:30 2017 +0000
@@ -1,8 +1,10 @@
+#include "mbed.h"
+
 // TinyDigitalIn - a simpler verison of DigitalIn that takes less
 // memory.
 //
 // This version uses the same mbed library infrastructure as the
-// regular DigitalIn, but we save a bit of memory by storing only
+// regular DigitalIn, but we save a little memory by storing only
 // the minimum set of fields needed to read the pin.  The mbed
 // DigitalIn has a larger memory footprint because it stores the 
 // full set of machine register pointers for the pin, most of 
@@ -11,9 +13,11 @@
 class TinyDigitalIn
 {
 public:
-    TinyDigitalIn(PinName pin)
+    TinyDigitalIn(PinName pin) { assignPin(pin); }
+    TinyDigitalIn() { assignPin(NC); }
+    
+    void assignPin(PinName pin)
     {
-        // make sure there's a pin connected
         if (pin != NC)
         {
             // initialize the pin as a GPIO Digital In port
@@ -22,19 +26,37 @@
             
             // get the register input port and mask
             pdir = gpio.reg_in;
-            mask = gpio.mask;
-        }
-        else
-        {
-            // no pin - set a null read register
-            pdir = 0;
-        }
+            uint32_t mask = gpio.mask;
+            
+            // Figure the bit shift: find how many right shifts it takes
+            // to shift the mask bit into the 0th bit position.  This lets
+            // us pull out the result value in read() as a 0 or 1 by shifting
+            // the register by this same amount and masking it against 0x01.
+            // The right shift is slightly more efficient than a conditional
+            // to convert a bit in the middle of the register to a canonical
+            // 0 or 1 result, and we have to do the mask anyway to pull out
+            // the one bit, so this makes the overall read slightly faster.
+            for (shift = 0 ; 
+                 mask != 0 && (mask & 0x00000001) == 0 ;
+                 mask >>= 1, shift++) ;
+         }
+         else
+         {
+             // not connected - point to a dummy port that always reads as 0
+             pdir = (volatile uint32_t *)&pdir_nc;
+             shift = 0;
+         }
     }
     
-    inline int read() { return pdir != 0 && (*pdir & mask) ? 1 : 0; }
+    inline int read() { return (*pdir >> shift) & 0x00000001; }
     inline operator int() { return read(); }
     
 private:
-    volatile uint32_t *pdir;
-    uint32_t mask;
-};
+    volatile uint32_t *pdir;    // pointer to GPIO register for this port 
+    uint8_t shift;              // number of bits to shift register value to get our port bit
+    
+    // pointer to dummy location for NC ports - reads as all 1 bits,
+    // as though it were wired to a pull-up port that's not connected
+    // to anything external
+    static const uint32_t pdir_nc;
+} __attribute__((packed));