An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.

Dependencies:   mbed FastIO FastPWM USBDevice

Fork of Pinscape_Controller by Mike R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AEAT6012.h Source File

AEAT6012.h

00001 // AEAT-6012-A06 interface
00002 //
00003 // The Broadcom AEAT-6012-A06 is a magnetic absolute rotary position encoder
00004 // with a 12-bit digital position output.  It encodes the rotational angle of
00005 // magnet, which is meant to be attached to a shaft that's positioned 
00006 // perpendicular to the sensor.  The 12-bit reporting means that the angle
00007 // is resolved to one part in 4096 around one 360 degree rotation of the
00008 // shaft, so each increment represents 360/4096 = 0.088 degrees of arc.
00009 //
00010 // For Pinscape purposes, we can use this sensor to track the position of
00011 // a plunger by mechanically translating the linear motion of the plunger
00012 // to rotational motion around a fixed point somewhere off the axis of the
00013 // plunger:
00014 //
00015 //    =X=======================|===   <- plunger, X = connector attachment point
00016 //      \
00017 //       \                            <- connector between plunger and shaft
00018 //        \
00019 //         *                          <- rotating shaft, at a fixed position
00020 //
00021 // As the plunger moves, the angle of the connector relative to the fixed
00022 // shaft position changes in a predictable way, so by measuring the rotational
00023 // position of the shaft at any given time, we can infer the plunger's
00024 // linear position.  The relationship between the plunger position and shaft
00025 // angle isn't precisely linear - it's sinusoidal.  So we need to apply a
00026 // little trigonometry to recover the linear position from the angle.
00027 //
00028 // The AEAT-6012-A06 has an extremely simple electronic interface.  It uses
00029 // a three-wire serial protocol: CS (chip select), CLK (data clock), and
00030 // DO (digital data out).  The data transmission is one-way - device to
00031 // host - and simply consists of the 12-bit position reading.  There aren't
00032 // any "commands" or other fancy business to deal with.  Between readings,
00033 // CS is held high; to intiate a reading, hold CS low, then toggle CLK to
00034 // clock out the bits.  The bits are clocked out from MSb to LSb.  After
00035 // clocking out the 12 bits, we take CS high again to reset the cycle.
00036 // There are also some timing requirements spelled out in the data sheet
00037 // that we have to observe for minimum clock pulse time, time before DO 
00038 // is valid, etc.
00039 //
00040 // There's a 10-bit variant of the sensor (AEAT-6010) that's otherwise 
00041 // identical, so we've made the data size a parameter so that the code can
00042 // be re-used for both sensor types (as well as any future variations with
00043 // other resolutions).
00044 
00045 template<int nBits> class AEAT601X
00046 {
00047 public:
00048     AEAT601X(PinName csPin, PinName clkPin, PinName doPin) :
00049         cs(csPin), clk(clkPin), DO(doPin)
00050     {
00051         // hold CS and CLK high between readings
00052         cs = 1;
00053         clk = 1;
00054     }
00055     
00056     // take a reading, returning an unsigned integer result from 0 to 2^bits-1
00057     int readAngle()
00058     {
00059         // Note on timings: the data sheet lists a number of minimum timing
00060         // parameters for the serial protocol.  The parameters of interest
00061         // here are all sub-microsecond, from 100ns to 500ns.  The mbed 
00062         // library doesn't have a nanosecond "wait", just the microsecond
00063         // wait, so we can't wait for precisely the minimum times.  But we
00064         // don't have to; the parameters are all minimum waits to ensure
00065         // that the sensor is ready for the next operation, so it's okay
00066         // to wait longer than the minimum.  And since we only have to move
00067         // a small number of bits (10-12 for the current sensor generation),
00068         // we don't have to be ruthlessly efficient about it; we can afford
00069         // to putter around for a leisurely microsecond at each step.  The 
00070         // total delay time for the 12-bit sensor even with the microsecond
00071         // delays only amounts to 25us, which is negligible for the plunger
00072         // read operation.
00073         
00074         // hold CS low for at least t[CLKFE] = 500ns per data sheet
00075         cs = 0;
00076         wait_us(1);
00077         
00078         // clock in the bits
00079         int result = 0;
00080         for (int i = 0; i < nBits; ++i)
00081         {
00082             // take clock low for >= T[CLK/2] = 500ns
00083             clk = 0;
00084             wait_us(1);
00085             
00086             // take clock high
00087             clk = 1;
00088             
00089             // wait for the data to become valid, T[DOvalid] = 375ns
00090             wait_us(1);
00091             
00092             // read the bit
00093             result <<= 1;
00094             result |= (DO ? 1 : 0);
00095         }
00096         
00097         // done - leave CS high between readings
00098         cs = 1;
00099         
00100         // The orientation in our mounting design reads the angle in the
00101         // reverse of the direction we want, so flip it.
00102         result = 4095 - result;
00103         
00104         // return the result
00105         return result;
00106     }
00107     
00108 protected:
00109     // CS (chip select) pin
00110     DigitalOut cs;
00111     
00112     // CLK (serial clock) pin
00113     DigitalOut clk;
00114     
00115     // DO (serial data) pin
00116     DigitalIn DO;
00117 };