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
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 };
Generated on Wed Jul 13 2022 03:30:10 by 1.7.2