Pinscape Controller version 1 fork. This is a fork to allow for ongoing bug fixes to the original controller version, from before the major changes for the expansion board project.

Dependencies:   FastIO FastPWM SimpleDMA mbed

Fork of Pinscape_Controller by Mike R

Revision:
17:ab3cec0c8bf4
Parent:
14:df700b22ca08
Child:
18:5e890ebd0023
--- a/TSL1410R/tsl1410r.h	Mon Dec 29 19:27:52 2014 +0000
+++ b/TSL1410R/tsl1410r.h	Fri Feb 27 04:14:04 2015 +0000
@@ -5,31 +5,60 @@
  */
  
  #include "mbed.h"
+ #include "FastIO.h"
+ #include "FastAnalogIn.h"
  
  #ifndef TSL1410R_H
  #define TSL1410R_H
  
-class TSL1410R
+template <PinName siPin, PinName clockPin> class TSL1410R
 {
 public:
-    // set up with the two DigitalOut ports (SI and clock), and the
-    // analog in port for reading the currently selected pixel value
-    TSL1410R(PinName siPort, PinName clockPort, PinName aoPort);
+    // set up the analog in port for reading the currently selected 
+    // pixel value
+    TSL1410R(PinName aoPin) : ao(aoPin)
+    {
+        // disable continuous conversion mode in FastAnalogIn - since we're
+        // reading discrete pixel values, we want to control when the samples
+        // are taken rather than continuously averaging over time
+        ao.disable();
+
+        // clear out power-on noise by clocking through all pixels twice
+        clear();
+        clear();
+    }
 
-    // Read the pixels.  Fills in pix[] with the pixel values, scaled 0-0xffff.
-    // n is the number of pixels to read; if this is less than the physical
-    // array size (npix), we'll read every mth pixel, where m = npix/n.  E.g.,
-    // if you want 640 pixels out of 1280 on the sensor, we'll read every
-    // other pixel.  If you want 320, we'll read every fourth pixel.
+    // Read the pixels.
+    //
+    // 'n' specifies the number of pixels to sample, and is the size of
+    // the output array 'pix'.  This can be less than the full number
+    // of pixels on the physical device; if it is, we'll spread the
+    // sample evenly across the full length of the device by skipping
+    // one or more pixels between each sampled pixel to pad out the
+    // difference between the sample size and the physical CCD size.
+    // For example, if the physical sensor has 1280 pixels, and 'n' is
+    // 640, we'll read every other pixel and skip every other pixel.
+    // If 'n' is 160, we'll read every 8th pixel and skip 7 between
+    // each sample.
+    // 
+    // The reason that we provide this subset mode (where 'n' is less
+    // than the physical pixel count) is that reading a pixel is the most
+    // time-consuming part of the scan.  For each pixel we read, we have
+    // to wait for the pixel's charge to transfer from its internal smapling
+    // capacitor to the CCD's output pin, for that charge to transfer to
+    // the KL25Z input pin, and for the KL25Z ADC to get a stable reading.
+    // This all takes on the order of 20us per pixel.  Skipping a pixel
+    // only requires a clock pulse, which takes about 350ns.  So we can
+    // skip 60 pixels in the time it takes to sample 1 pixel.
     //
     // We clock an SI pulse at the beginning of the read.  This starts the
     // next integration cycle: the pixel array will reset on the SI, and 
-    // the integration starts 18 clocks later.  So by the time this returns,
-    // the next sample will have been integrating for npix-18 clocks.  In
-    // many cases this is enough time to allow immediately reading the next
-    // sample; if more integration time is required, the caller can simply
+    // the integration starts 18 clocks later.  So by the time this method
+    // returns, the next sample will have been integrating for npix-18 clocks.  
+    // That's usually enough time to allow immediately reading the next
+    // sample.  If more integration time is required, the caller can simply
     // sleep/spin for the desired additional time, or can do other work that
-    // takes the desired additional time.  
+    // takes the desired additional time.
     //
     // If the caller has other work to tend to that takes longer than the
     // desired maximum integration time, it can call clear() to clock out
@@ -38,22 +67,87 @@
     
     // Read with interval callback.  We'll call the callback the given
     // number of times per read cycle.
-    void read(uint16_t *pix, int n, void (*cb)(void *ctx), void *cbctx, int cbcnt);
+    void read(uint16_t *pix, int n, void (*cb)(void *ctx), void *cbctx, int cbcnt)
+    {
+        // start the next integration cycle by pulsing SI and one clock
+        si = 1;
+        clock = 1;
+        si = 0;
+        clock = 0;
+        
+        // figure how many pixels to skip on each read
+        int skip = nPix/n - 1;
+        
+        // figure the callback interval
+        int cbInterval = nPix;
+        if (cb != 0)
+            cbInterval = nPix/(cbcnt+1);
+    
+        // read all of the pixels
+        for (int src = 0, dst = 0 ; src < nPix ; )
+        {
+            // figure the end of this callback interval
+            int srcEnd = src + cbInterval;
+            if (srcEnd > nPix)
+                srcEnd = nPix;
+                
+            // read one callback chunk of pixels
+            for ( ; src < srcEnd ; ++src)
+            {
+                // clock in and read the next pixel
+                clock = 1;
+                ao.enable();
+                wait_us(1);
+                clock = 0;
+                wait_us(11);
+                pix[dst++] = ao.read_u16();
+                ao.disable();
+                
+                // clock skipped pixels
+                for (int i = 0 ; i < skip ; ++i, ++src) 
+                {
+                    clock = 1;
+                    clock = 0;
+                }
+            }
+            
+            // call the callback, if we're not at the last pixel
+            if (cb != 0 && src < nPix)
+                (*cb)(cbctx);
+        }
+        
+        // clock out one extra pixel to leave A1 in the high-Z state
+        clock = 1;
+        clock = 0;
+    }
 
     // Clock through all pixels to clear the array.  Pulses SI at the
     // beginning of the operation, which starts a new integration cycle.
     // The caller can thus immediately call read() to read the pixels 
     // integrated while the clear() was taking place.
-    void clear();
+    void clear()
+    {
+        // clock in an SI pulse
+        si = 1;
+        clock = 1;
+        clock = 0;
+        si = 0;
+        
+        // clock out all pixels
+        for (int i = 0 ; i < nPix + 1 ; ++i) {
+            clock = 1;
+            clock = 0;
+        }
+    }
 
     // number of pixels in the array
     static const int nPix = 1280;
     
     
 private:
-    DigitalOut si;
-    DigitalOut clock;
-    AnalogIn ao;
+    FastOut<siPin> si;
+    FastOut<clockPin> clock;
+    FastAnalogIn ao;
 };
  
 #endif /* TSL1410R_H */