An input/output controller for virtual pinball machines, with plunger position tracking, accelerometer-based nudge sensing, button input encoding, and feedback device control.

Dependencies:   USBDevice mbed FastAnalogIn FastIO FastPWM SimpleDMA

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tsl1410r.h Source File

tsl1410r.h

00001 /*
00002  *  TSL1410R interface class.
00003  *
00004  *  This provides a high-level interface for the Taos TSL1410R linear CCD array sensor.
00005  */
00006  
00007  #include "mbed.h"
00008  #include "config.h"
00009  #include "FastIO.h"
00010  #include "FastAnalogIn.h"
00011  
00012  #ifndef TSL1410R_H
00013  #define TSL1410R_H
00014  
00015 template <PinName siPin, PinName clockPin> class TSL1410R
00016 {
00017 public:
00018     // set up the analog in port for reading the currently selected 
00019     // pixel value
00020     TSL1410R(PinName aoPin) : ao(aoPin)
00021     {
00022         // disable continuous conversion mode in FastAnalogIn - since we're
00023         // reading discrete pixel values, we want to control when the samples
00024         // are taken rather than continuously averaging over time
00025         ao.disable();
00026 
00027         // clear out power-on noise by clocking through all pixels twice
00028         clear();
00029         clear();
00030     }
00031 
00032     // Read the pixels.
00033     //
00034     // 'n' specifies the number of pixels to sample, and is the size of
00035     // the output array 'pix'.  This can be less than the full number
00036     // of pixels on the physical device; if it is, we'll spread the
00037     // sample evenly across the full length of the device by skipping
00038     // one or more pixels between each sampled pixel to pad out the
00039     // difference between the sample size and the physical CCD size.
00040     // For example, if the physical sensor has 1280 pixels, and 'n' is
00041     // 640, we'll read every other pixel and skip every other pixel.
00042     // If 'n' is 160, we'll read every 8th pixel and skip 7 between
00043     // each sample.
00044     // 
00045     // The reason that we provide this subset mode (where 'n' is less
00046     // than the physical pixel count) is that reading a pixel is the most
00047     // time-consuming part of the scan.  For each pixel we read, we have
00048     // to wait for the pixel's charge to transfer from its internal smapling
00049     // capacitor to the CCD's output pin, for that charge to transfer to
00050     // the KL25Z input pin, and for the KL25Z ADC to get a stable reading.
00051     // This all takes on the order of 20us per pixel.  Skipping a pixel
00052     // only requires a clock pulse, which takes about 350ns.  So we can
00053     // skip 60 pixels in the time it takes to sample 1 pixel.
00054     //
00055     // We clock an SI pulse at the beginning of the read.  This starts the
00056     // next integration cycle: the pixel array will reset on the SI, and 
00057     // the integration starts 18 clocks later.  So by the time this method
00058     // returns, the next sample will have been integrating for npix-18 clocks.  
00059     // That's usually enough time to allow immediately reading the next
00060     // sample.  If more integration time is required, the caller can simply
00061     // sleep/spin for the desired additional time, or can do other work that
00062     // takes the desired additional time.
00063     //
00064     // If the caller has other work to tend to that takes longer than the
00065     // desired maximum integration time, it can call clear() to clock out
00066     // the current pixels and start a fresh integration cycle.
00067     void read(uint16_t *pix, int n)
00068     {
00069         // start the next integration cycle by pulsing SI and one clock
00070         si = 1;
00071         clock = 1;
00072         si = 0;
00073         clock = 0;
00074         
00075         // figure how many pixels to skip on each read
00076         int skip = nPix/n - 1;
00077         
00078         // read all of the pixels
00079         for (int src = 0, dst = 0 ; src < nPix ; ++src)
00080         {
00081             // clock in and read the next pixel
00082             clock = 1;
00083             ao.enable();
00084             wait_us(1);
00085             clock = 0;
00086             wait_us(11);
00087             pix[dst++] = ao.read_u16();
00088             ao.disable();
00089             
00090             // clock skipped pixels
00091             for (int i = 0 ; i < skip ; ++i, ++src) 
00092             {
00093                 clock = 1;
00094                 clock = 0;
00095             }
00096         }
00097         
00098         // clock out one extra pixel to leave A1 in the high-Z state
00099         clock = 1;
00100         clock = 0;
00101     }
00102 
00103     // Clock through all pixels to clear the array.  Pulses SI at the
00104     // beginning of the operation, which starts a new integration cycle.
00105     // The caller can thus immediately call read() to read the pixels 
00106     // integrated while the clear() was taking place.
00107     void clear()
00108     {
00109         // clock in an SI pulse
00110         si = 1;
00111         clock = 1;
00112         clock = 0;
00113         si = 0;
00114         
00115         // clock out all pixels
00116         for (int i = 0 ; i < nPix + 1 ; ++i) {
00117             clock = 1;
00118             clock = 0;
00119         }
00120     }
00121 
00122     // number of pixels in the array
00123     static const int nPix = CCD_NPIXELS;
00124     
00125     
00126 private:
00127     FastOut<siPin> si;
00128     FastOut<clockPin> clock;
00129     FastAnalogIn ao;
00130 };
00131  
00132 #endif /* TSL1410R_H */