Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Revision:
100:1ff35c07217c
Child:
102:41d49e78c253
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AEAT6012/AEAT6012.h	Thu Nov 28 23:18:23 2019 +0000
@@ -0,0 +1,113 @@
+// AEAT-6012-A06 interface
+//
+// The Broadcom AEAT-6012-A06 is a magnetic absolute rotary position encoder
+// with a 12-bit digital position output.  It encodes the rotational angle of
+// magnet, which is meant to be attached to a shaft that's positioned 
+// perpendicular to the sensor.  The 12-bit reporting means that the angle
+// is resolved to one part in 4096 around one 360 degree rotation of the
+// shaft, so each increment represents 360/4096 = 0.088 degrees of arc.
+//
+// For Pinscape purposes, we can use this sensor to track the position of
+// a plunger by mechanically translating the linear motion of the plunger
+// to rotational motion around a fixed point somewhere off the axis of the
+// plunger:
+//
+//    =X=======================|===   <- plunger, X = connector attachment point
+//      \
+//       \                            <- connector between plunger and shaft
+//        \
+//         *                          <- rotating shaft, at a fixed position
+//
+// As the plunger moves, the angle of the connector relative to the fixed
+// shaft position changes in a predictable way, so by measuring the rotational
+// position of the shaft at any given time, we can infer the plunger's
+// linear position.  The relationship between the plunger position and shaft
+// angle isn't precisely linear - it's sinusoidal.  So we need to apply a
+// little trigonometry to recover the linear position from the angle.
+//
+// The AEAT-6012-A06 has an extremely simple electronic interface.  It uses
+// a three-wire serial protocol: CS (chip select), CLK (data clock), and
+// DO (digital data out).  The data transmission is one-way - device to
+// host - and simply consists of the 12-bit position reading.  There aren't
+// any "commands" or other fancy business to deal with.  Between readings,
+// CS is held high; to intiate a reading, hold CS low, then toggle CLK to
+// clock out the bits.  The bits are clocked out from MSb to LSb.  After
+// clocking out the 12 bits, we take CS high again to reset the cycle.
+// There are also some timing requirements spelled out in the data sheet
+// that we have to observe for minimum clock pulse time, time before DO 
+// is valid, etc.
+//
+// There's a 10-bit variant of the sensor (AEAT-6010) that's otherwise 
+// identical, so we've made the data size a parameter so that the code can
+// be re-used for both sensor types (as well as any future variations with
+// other resolutions).
+
+template<int nBits> class AEAT601X
+{
+public:
+    AEAT601X(PinName csPin, PinName clkPin, PinName doPin) :
+        cs(csPin), clk(clkPin), DO(doPin)
+    {
+        // hold CS and CLK high between readings
+        cs = 1;
+        clk = 1;
+    }
+    
+    // take a reading, returning an unsigned integer result from 0 to 2^bits-1
+    int readAngle()
+    {
+        // Note on timings: the data sheet lists a number of minimum timing
+        // parameters for the serial protocol.  The parameters of interest
+        // here are all sub-microsecond, from 100ns to 500ns.  The mbed 
+        // library doesn't have a nanosecond "wait", just the microsecond
+        // wait, so we can't wait for precisely the minimum times.  But we
+        // don't have to; the parameters are all minimum waits to ensure
+        // that the sensor is ready for the next operation, so it's okay
+        // to wait longer than the minimum.  And since we only have to move
+        // a small number of bits (10-12 for the current sensor generation),
+        // we don't have to be ruthlessly efficient about it; we can afford
+        // to putter around for a leisurely microsecond at each step.  The 
+        // total delay time for the 12-bit sensor even with the microsecond
+        // delays only amounts to 25us, which is negligible for the plunger
+        // read operation.
+        
+        // hold CS low for at least t[CLKFE] = 500ns per data sheet
+        cs = 0;
+        wait_us(1);
+        
+        // clock in the bits
+        int result = 0;
+        for (int i = 0; i < nBits; ++i)
+        {
+            // take clock low for >= T[CLK/2] = 500ns
+            clk = 0;
+            wait_us(1);
+            
+            // take clock high
+            clk = 1;
+            
+            // wait for the data to become valid, T[DOvalid] = 375ns
+            wait_us(1);
+            
+            // read the bit
+            result <<= 1;
+            result |= (DO ? 1 : 0);
+        }
+        
+        // done - leave CS high between readings
+        cs = 1;
+        
+        // return the result
+        return result;
+    }
+    
+protected:
+    // CS (chip select) pin
+    DigitalOut cs;
+    
+    // CLK (serial clock) pin
+    DigitalOut clk;
+    
+    // DO (serial data) pin
+    DigitalIn DO;
+};