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 TSL14xx.h Source File

TSL14xx.h

00001 /*
00002  *  AMS/TAOS TSL14xx series photodiode array interface class.
00003  *
00004  *  This provides a high-level interface for the AMS/TAOS TSLxx series
00005  *  of photodiode arrays.  This class works with most of the sensors
00006  *  in this series, which differ only in pixel array sizes.  This code
00007  *  has been tested with the following sensors from the series:
00008  *
00009  *  TSL1410R  - 1280 pixels, 400dpi
00010  *  TSL1412S  - 1536 pixels, 400dpi
00011  *  TSL1401CL - 128 pixels, 400dpi
00012  *
00013  *  All of these sensors have the same electrical interface, consisting
00014  *  of a clock input (CLK), start pulse input (SI), and analog pixel
00015  *  output (AO).  The sensors are equipped with hold capacitors and
00016  *  shift registers that allow simultaneous sampling of all pixels, and
00017  *  serial access to the pixel values.
00018  *
00019  *  (Note on the plunger sensor class hierarchy: this class is for the
00020  *  sensor only, not for the plunger application.  This class is meant
00021  *  to be reusable in other contexts that just need to read raw pixel
00022  *  data from the sensor.  Plunger/tslxxSensor.h implements the 
00023  *  specializations of the plunger interface class for these sensors.)
00024  *
00025  *
00026  *  *** Double buffering ***
00027  *
00028  *  Our API is based on a double-buffered asynchronous read.  The caller
00029  *  can access a completed buffer, containing the pixels from the last image 
00030  *  frame, while the sensor is transferring data asynchronously (using the 
00031  *  microcontroller's DMA capability) into the other buffer.  Each time a
00032  *  new read is started, we swap buffers, making the last completed buffer 
00033  *  available to the client and handing the other buffer to the DMA
00034  *  controller to fill asynchronously.
00035  *
00036  *  In a way, there are actually THREE frames in our pipeline at any given
00037  *  time:
00038  *
00039  *   - a live image integrating light on the photo receptors on the sensor
00040  *   - the prior image, held in the sensor's shift register and being 
00041  *     transferred via DMA into one of our buffers (the "DMA" buffer)
00042  *   - the second prior image, in our other buffer (the "stable" buffer),
00043  *     available for the client to process
00044  *
00045  *  The integration process on the sensor starts when we begin the transfer
00046  *  of an image via DMA.  That frame's integration period ends when the next 
00047  *  transfer starts.  So the minimum integration time is also the DMA pixel
00048  *  transfer time.  Longer integration times can be achieved by waiting
00049  *  for an additional interval after a DMA transfer finishes, before starting
00050  *  the next transfer.  We make provision for this added time to allow for
00051  *  longer exposure times to optimize image quality.
00052  *
00053  *
00054  *  *** Optimizing pixel transfer speed ***
00055  *
00056  *  For Pinscape purposes, we want the fastest possible frame rate, as we're
00057  *  trying to accurately capture the motion of a fast-moving object (the 
00058  *  plunger).  The TSL14xx sensors can achieve a frame rate up to about
00059  *  1000 frames per second, if everything is clocked at the limits in the
00060  *  data sheet.  The KL25Z, however, can't achieve that fast a rate.  The
00061  *  limiting factor is the KL25Z's ADC.  We have to take an ADC sample for
00062  *  every pixel, and the minimum sampling time for the ADC on the KL25Z is
00063  *  about 2us.  With the 1280-pixel TSL1410R, that gives us a minimum
00064  *  pixel transfer time of about 2.6ms.  And it's actually very difficult
00065  *  to achieve that speed - my original, naive implementation took more
00066  *  like 30ms (!!!) to transfer each frame.
00067  *
00068  *  As a rule, I don't like tricky code, because it's hard to understand
00069  *  and hard to debug.  But in this case it's justified.  For good plunger
00070  *  tracking, it's critical to achieve a minimum frame rate of around 200 
00071  *  fps (5ms per frame).  I'm pretty sure there's no way to even get close 
00072  *  to this rate without the complex setup described below.
00073  *
00074  *  Here's our approach for fast data transfer:
00075  * 
00076  *  First, we put the analog input port (the ADC == Analog-to-Digital 
00077  *  Converter) in "continuous" mode, at the highest clock speed we can 
00078  *  program with the available clocks and the fastest read cycle 
00079  *  available in the ADC hardware.  (The analog input port is the 
00080  *  GPIO pin attached to the sensor's AO == Analog Output pin, where 
00081  *  it outputs each pixel's value, one at a time, as an analog voltage 
00082  *  level.)  In continuous mode, every time the ADC finishes taking a 
00083  *  sample, it stores the result value in its output register and then 
00084  *  immediately starts taking a new sample.  This means that no MCU 
00085  *  (or even DMA) action is required to start each new sample.  This 
00086  *  is where most of the speedup comes from, since it takes significant
00087  *  time (multiple microseconds) to move data through the peripheral 
00088  *  registers, and it takes more time (also multiple microseconds) for
00089  *  the ADC to spin up for each new sample when in single-sample mode.
00090  *  We cut out about 7us this way and get the time per sample down to 
00091  *  about 2us.  This is close to the documented maximum speed for the
00092  *  ADC hardware.
00093  *
00094  *  Second, we use the DMA controller to read the ADC result register
00095  *  and store each sample in a memory array for processing.  The ADC
00096  *  hardware is designed to work with the DMA controller by signaling
00097  *  the DMA controller when a new sample is ready; this allows DMA to
00098  *  move each sample immediately when it's available without any CPU
00099  *  involvement.
00100  *
00101  *  Third - and this is where it really gets tricky - we use two
00102  *  additional "linked" DMA channels to generate the clock signal
00103  *  to the CCD sensor.  The clock signal is how we tell the CCD when
00104  *  to place the next pixel voltage on its AO pin, so the clock has
00105  *  to be generated in lock step with the ADC sampling cycle.  The
00106  *  ADC timing isn't perfectly uniform or predictable, so we can't 
00107  *  just generate the pixel clock with a *real* clock.  We have to
00108  *  time the signal exactly with the ADC, which means that we have 
00109  *  to generate it from the ADC "sample is ready" signal.  Fortunately,
00110  *  there is just such a signal, and in fact we're already using it,
00111  *  as described above, to tell the DMA when to move each result from
00112  *  the ADC output register to our memory array.  So how do we use this
00113  *  to generate the CCD clock?  The answer lies in the DMA controller's
00114  *  channel linking feature.  This allows one DMA channel to trigger a
00115  *  second DMA channel each time the first channel completes one
00116  *  transfer.  And we can use DMA to control our clock GPIO pin by
00117  *  using the pin's GPIO IPORT register as the DMA destination address.
00118  *  Specifically, we can take the clock high by writing our pin's bit 
00119  *  pattern to the PSOR ("set output") register, and we can take the 
00120  *  clock low by writing to the PCOR ("clear output") register.  We 
00121  *  use one DMA channel for each of these operations.
00122  *
00123  *  Putting it all together, the cascade of linked DMA channels
00124  *  works like this:
00125  *
00126  *   - We kick off the first ADC sample.
00127  *
00128  *   - When the ADC sample completes, the ADC DMA trigger fires,
00129  *     which triggers channel 1, the "Clock Up" channel.  This 
00130  *     performs one transfer of the clock GPIO bit to the clock 
00131  *     PSOR register, taking the clock high, which causes the CCD 
00132  *     to move the next pixel onto AO.
00133  *
00134  *   - After the Clock Up channel does its transfer, it triggers
00135  *     its link to channel 2, the ADC transfer channel.  This
00136  *     channel moves the ADC output register value to our memory
00137  *     array.
00138  *
00139  *   - After the ADC channel does its transfer, it triggers channel
00140  *     3, the "Clock Down" channel.  This performs one transfer of
00141  *     the clock GPIO bit to the clock PCOR register, taking the
00142  *     clock low.
00143  *
00144  *  Note that the order of the channels - Clock Up, ADC, Clock Down -
00145  *  is important.  It ensures that we don't toggle the clock line
00146  *  too quickly.  The CCD has a minimum pulse duration of 50ns for
00147  *  the clock signal.  The DMA controller is so fast that it might
00148  *  toggle the clock faster than this limit if we did the Up and 
00149  *  Down transfers back-to-back.
00150  *
00151  *  Note also that it's important for Clock Up to be the very first
00152  *  operation after the DMA trigger.  The ADC is in continuous mode, 
00153  *  meaning that it starts taking a new sample immediately upon 
00154  *  finishing the previous one.  So when the ADC DMA signal fires, 
00155  *  the new sample is already starting.  We therefore have to get 
00156  *  the next pixel onto the sampling pin immediately, or as close
00157  *  to immediately as possible.  The sensor's "analog output 
00158  *  settling time" is 120ns - this is the time for a new pixel 
00159  *  voltage to stabilize on AO after a clock rising edge.  So 
00160  *  assuming that the ADC raises the DMA signal immediately on
00161  *  sample completion, and the DMA controller responds within a 
00162  *  couple of MCU clock cycles, we should have the new pixel voltage 
00163  *  stable on the sampling pin by about 200ns after the new ADC 
00164  *  sample cycle starts.  The sampling cycle with our current 
00165  *  parameters is about 2us, so the voltage level is stable for 
00166  *  90% of the cycle.  
00167  *
00168  *  Also, note that it's okay that the ADC sample transfer doesn't
00169  *  happen until after the Clock Up DMA transfer.  The ADC output 
00170  *  register holds the last result until the next sample completes, 
00171  *  so we have about 2us to grab it.  The first Clock Up DMA 
00172  *  transfer only takes a couple of clocks - order of 100ns - so 
00173  *  we get to it with time to spare.
00174  *
00175  *  (Note that it would nicer to handle the clock with a single DMA
00176  *  channel, since DMA channels are a limited resource.  We could
00177  *  conceivably consolidate the clock generator one DMA channel by
00178  *  switching the DMA destination to the PTOR "toggle" register, and
00179  *  writing *two* times per trigger - once to toggle the clock up, 
00180  *  and a second time to toggle it down.  But I haven't found a way 
00181  *  to make this work.  The obstacle is that the DMA controller can 
00182  *  only do one transfer per trigger in the fully autonomous mode 
00183  *  we're using, and to make this toggle scheme work, we'd have to do 
00184  *  two writes per trigger.  Maybe even three or four:  I think we'd
00185  *  have to throw in one or two no-op writes (of all zeroes) between 
00186  *  the two toggles, to pad the timing to ensure that the clock pulse 
00187  *  width is over the sensor's 50ns minimum.  But it's the same issue 
00188  *  whether it's two writes or four.  The DMA controller does have a 
00189  *  "continuous" mode that does an entire transfer on a single trigger,
00190  *  but it can't reset itself after such a transfer; CPU intervention 
00191  *  is required to do that, which means we'd have to service an 
00192  *  interrupt on every ADC cycle to set up the next clock write.  
00193  *  Given the 2us cycle time, an interrupt would create a ton of CPU 
00194  *  load, and I don't think the CPU is fast enough to reliably complete
00195  *  the work we'd have to do on each 2us cycle.  Fortunately, at
00196  *  the moment we can afford to dedicate three channels to this
00197  *  module.  We only have one other module using the DMA at all
00198  *  (the TLC5940 PWM controller interface), and it only needs one
00199  *  channel.  So the KL25Z's complement of four DMA channels is just
00200  *  enough for all of our needs for the moment.)
00201  *
00202  *  Note that some of the sensors in this series (TSL1410R, TSL1412S)
00203  *  have a "parallel" readout mode that lets them physically deliver 
00204  *  two pixels at once the MCU, via separate physical connections.  This 
00205  *  could provide a 2X speedup on an MCU equipped with two independent 
00206  *  ADC samplers.  Unfortunately, the KL25Z is not so equipped; even 
00207  *  though it might appear at first glance to support multiple ADC 
00208  *  "channels", all of the channels internally multiplex into a single 
00209  *  converter unit, so the hardware can ultimately perform only one 
00210  *  conversion at a time.  Paradoxically, using the sensor's parallel 
00211  *  mode is actually *slower* with a KL25Z than using its serial mode,
00212  *  because we can only maintain the higher throughput of the KL25Z ADC's
00213  *  continuous sampling mode by reading all samples thorugh a single
00214  *  channel.  Switching channels on alternating samples involves a
00215  *  bunch of setup overhead within the ADC hardware that adds lots of
00216  *  clocks compared to single-channel continuous mode.
00217  */
00218  
00219 #include "mbed.h"
00220 #include "config.h"
00221 #include "AltAnalogIn.h"
00222 #include "SimpleDMA.h"
00223 #include "DMAChannels.h"
00224  
00225 #ifndef TSL14XX_H
00226 #define TSL14XX_H
00227 
00228 
00229 // To allow DMA access to the clock pin, we need to point the DMA
00230 // controller to the IOPORT registers that control the pin.  PORT_BASE()
00231 // gives us the address of the register group for the 32 GPIO pins with
00232 // the same letter name as our target pin (e.g., PTA0 through PTA31), 
00233 // and PINMASK gives us the bit pattern to write to those registers to
00234 // access our single GPIO pin.  Each register group has three special
00235 // registers that update the pin in particular ways:  PSOR ("set output 
00236 // register") turns pins on, PCOR ("clear output register") turns pins 
00237 // off, and PTOR ("toggle output register") toggle pins to the opposite
00238 // of their current values.  These registers have special semantics:
00239 // writing a bit as 0 has no effect on the corresponding pin, while
00240 // writing a bit as 1 performs the register's action on the pin.  This
00241 // allows a single GPIO pin to be set, cleared, or toggled with a
00242 // 32-bit write to one of these registers, without affecting any of the
00243 // other pins addressed by the register.  (It also allows changing any
00244 // group of pins with a single write, although we don't use that
00245 // feature here.)
00246 //
00247 // - To turn a pin ON:  PORT_BASE(pin)->PSOR = PINMASK(pin)
00248 // - To turn a pin OFF: PORT_BASE(pin)->PCOR = PINMASK(pin)
00249 // - To toggle a pin:   PORT_BASE(pin)->PTOR = PINMASK(pin)
00250 //
00251 #define GPIO_PORT(pin)        (((unsigned int)(pin)) >> PORT_SHIFT)
00252 #define GPIO_PORT_BASE(pin)   ((GPIO_Type *)(PTA_BASE + GPIO_PORT(pin) * 0x40))
00253 #define GPIO_PINMASK(pin)     gpio_set(pin)
00254  
00255 IF_DIAG(
00256     extern uint64_t mainLoopIterCheckpt[];
00257     extern Timer mainLoopTimer;)
00258         
00259 class TSL14xx
00260 {
00261 public:
00262     // Set up the interface.  
00263     //
00264     //  nPixSensor = native number of pixels on sensor
00265     //  siPin = SI pin (GPIO, digital out)
00266     //  clockPin = CLK pin (GPIO, digital out)
00267     //  aoPin = AO pin (GPIO, analog in - must be ADC-capable)
00268     TSL14xx(int nPixSensor, PinName siPin, PinName clockPin, PinName aoPin)
00269         : adc_dma(DMAch_TSL_ADC), 
00270           clkUp_dma(DMAch_TSL_CLKUP), 
00271           clkDn_dma(DMAch_TSL_CLKDN),
00272           si(siPin), 
00273           clock(clockPin), 
00274           ao(aoPin, true, 0),  // continuous sampling, fast sampling mode
00275           nPixSensor(nPixSensor)
00276     {
00277         // Calibrate the ADC for best accuracy
00278         ao.calibrate();
00279         
00280         // start the sample timer with an arbitrary zero point of 'now'
00281         t.start();
00282         
00283         // start with no minimum integration time
00284         tIntMin = 0;
00285         
00286         // allocate our double pixel buffers
00287         pix1 = new uint8_t[nPixSensor*2];
00288         pix2 = pix1 + nPixSensor;
00289         
00290         // put the first DMA transfer into the first buffer (pix1)
00291         pixDMA = 0;
00292         
00293         // DMA owns both buffers until the first transfer completes
00294         clientOwnsStablePix = true;
00295 
00296         // remember the clock pin port base and pin mask for fast access
00297         clockPort = GPIO_PORT_BASE(clockPin);
00298         clockMask = GPIO_PINMASK(clockPin);
00299         
00300         // clear out power-on random data by clocking through all pixels twice
00301         clear();
00302         clear();
00303         
00304         // Set up the Clock Up DMA channel.  This channel takes the
00305         // clock high by writing the clock bit to the PSOR (set output) 
00306         // register for the clock pin.
00307         clkUp_dma.source(&clockMask, false, 32);
00308         clkUp_dma.destination(&clockPort->PSOR, false, 32);
00309 
00310         // Set up the Clock Down DMA channel.  This channel takes the
00311         // clock low by writing the clock bit to the PCOR (clear output)
00312         // register for the clock pin.
00313         clkDn_dma.source(&clockMask, false, 32);
00314         clkDn_dma.destination(&clockPort->PCOR, false, 32);
00315         
00316         // Set up the ADC transfer DMA channel.  This channel transfers
00317         // the current analog sampling result from the ADC output register
00318         // to our pixel array.
00319         ao.initDMA(&adc_dma);
00320 
00321         // Set up our chain of linked DMA channel:
00322         //
00323         //   ADC sample completion triggers Clock Up
00324         //   ...which triggers the ADC transfer
00325         //   ...which triggers Clock Down
00326         //
00327         // We operate the ADC in "continuous mode", meaning that it starts
00328         // a new sample immediately after the last one completes.  This is
00329         // what keeps the cycle going after the Clock Down, since the Clock
00330         // Down transfer itself doesn't trigger another DMA operation.
00331         clkUp_dma.trigger(Trigger_ADC0);
00332         clkUp_dma.link(adc_dma);
00333         adc_dma.link(clkDn_dma, false);
00334         
00335         // Set the trigger on the downstream links to NONE - these are
00336         // triggered by their upstream links, so they don't need separate
00337         // peripheral or software triggers.
00338         adc_dma.trigger(Trigger_NONE);
00339         clkDn_dma.trigger(Trigger_NONE);
00340         
00341         // Register an interrupt callback so that we're notified when
00342         // the last transfer completes.
00343         clkDn_dma.attach(this, &TSL14xx::transferDone);
00344 
00345         // clear the timing statistics        
00346         totalTime = 0.0; 
00347         nRuns = 0;
00348         
00349         // start the first transfer
00350         startTransfer();
00351     }
00352     
00353     // Get the stable pixel array.  This is the image array from the
00354     // previous capture.  It remains valid until the next startCapture()
00355     // call, at which point this buffer will be reused for the new capture.
00356     void getPix(uint8_t * &pix, uint32_t &t)
00357     {
00358         // return the pixel array that ISN'T assigned to the DMA
00359         if (pixDMA)
00360         {
00361             // DMA owns pix2, so the stable array is pix1
00362             pix = pix1;
00363             t = t1;
00364         }
00365         else
00366         {
00367             // DMA owns pix1, so the stable array is pix2
00368             pix = pix2;
00369             t = t2;
00370         }
00371     }
00372     
00373     // Wait for the current DMA transfer to finish, and retrieve its
00374     // pixel array buffer.  This provides access to the latest image
00375     // without starting a new transfer.  These pixels are valid throughout
00376     // the next transfer (started via startCapture()) and remain valid 
00377     // until the next transfer after that.
00378     void waitPix(uint8_t * &pix, uint32_t &t)
00379     {
00380         // wait for stable buffer ownership to transfer to the client
00381         wait();
00382         
00383         // Return the pixel array that IS assigned to DMA, since this
00384         // is the latest buffer filled.  This buffer is stable, even
00385         // though it's assigned to DMA, because the last transfer is
00386         // already finished and thus DMA is no longer accessing the
00387         // buffer.
00388         if (pixDMA)
00389         {
00390             // DMA owns pix2
00391             pix = pix2;
00392             t = t2;
00393         }
00394         else
00395         {
00396             // DMA owns pix1
00397             pix = pix1;
00398             t = t1;
00399         }
00400     }
00401     
00402     // Set the requested minimum integration time.  If this is less than the
00403     // sensor's physical minimum time, the physical minimum applies.
00404     virtual void setMinIntTime(uint32_t us)
00405     {
00406         tIntMin = us;
00407     }
00408     
00409     // Wait for the stable buffer ownership to transfer to the client
00410     void wait() { while (!clientOwnsStablePix) ; }
00411     
00412     // Is a buffer available?
00413     bool ready() const { return clientOwnsStablePix; }
00414     
00415     // Release the client DMA buffer.  The client must call this when it's
00416     // done with the current image frame to release the frame back to the
00417     // DMA subsystem, so that it can hand us the next frame.
00418     void releasePix() { clientOwnsStablePix = false; }
00419         
00420     // get the timing statistics - sum of scan time for all scans so far 
00421     // in microseconds, and total number of scans so far
00422     void getTimingStats(uint64_t &totalTime, uint32_t &nRuns) const
00423     {
00424         totalTime = this->totalTime;
00425         nRuns = this->nRuns;
00426     }
00427     
00428     // get the average scan time in microseconds
00429     uint32_t getAvgScanTime() const
00430     {
00431         return uint32_t(totalTime / nRuns);
00432     }
00433     
00434 private:
00435     // Start a new transfer.  We call this at the end of each integration
00436     // cycle, in interrupt mode.  This can be called directly by the interrupt
00437     // handler invoked when the DMA transfer completes, or by a timeout.  In
00438     // either case, we're in interrupt mode.
00439     void startTransfer()
00440     {
00441         // If we own the stable buffer, swap buffers: hand ownership of the
00442         // old DMA buffer to the client, and take control of the old client
00443         // buffer (which the client must be done with if we own it) as our
00444         // new DMA buffer.
00445         //
00446         // If the client owns the stable buffer, we can't swap buffers,
00447         // because the client is still working on the stable one.  So we
00448         // must start the new transfer using the existing DMA buffer.
00449         if (!clientOwnsStablePix)
00450         {
00451             // swap buffers
00452             pixDMA ^= 1;
00453             
00454             // release the prior DMA buffer to the client
00455             clientOwnsStablePix = true;
00456         }
00457         
00458         // Set up the active pixel array as the destination buffer for 
00459         // the ADC DMA channel. 
00460         adc_dma.destination(pixDMA ? pix2 : pix1, true);
00461 
00462         // start the DMA transfers
00463         clkDn_dma.start(nPixSensor*4, true);
00464         adc_dma.start(nPixSensor, true);
00465         clkUp_dma.start(nPixSensor*4, true);
00466             
00467         // note the start time of this transfer
00468         t0 = t.read_us();
00469         
00470         // start the next integration cycle by pulsing SI and one clock
00471         si = 1;
00472         clock = 1;
00473         si = 0;
00474         clock = 0;
00475         
00476         // Set the timestamp for the current active buffer.  The SI pulse
00477         // we just did performed the HOLD operation, which takes a snapshot
00478         // of the photo receptors and stores it in the sensor's shift
00479         // register.  We noted the start of the current integration cycle 
00480         // in tInt when we started it during the previous scan.  The image 
00481         // we're about to transfer therefore represents the light collected
00482         // between tInt and right now (actually, the SI pulse above, but 
00483         // close enough).  The image covers a time range rather than a
00484         // single point in time, but we still have to give it a single
00485         // timestamp.  Use the midpoint of the integration period.
00486         uint32_t tmid = (t0 + tInt) >> 1;
00487         if (pixDMA)
00488             t2 = tmid;
00489         else
00490             t1 = tmid;
00491 
00492         // Start the ADC sampler.  The ADC will read samples continuously
00493         // until we tell it to stop.  Each sample completion will trigger 
00494         // our linked DMA channel, which will store the next sample in our
00495         // pixel array and pulse the CCD serial data clock to load the next
00496         // pixel onto the analog sampler pin.  This will all happen without
00497         // any CPU involvement, so we can continue with other work.
00498         ao.start();
00499         
00500         // The new integration cycle starts with the 19th clock pulse
00501         // after the SI pulse.  We offload all of the transfer work (including
00502         // the clock pulse generation) to the DMA controller, which doesn't
00503         // notify when that 19th pulse occurs, so we have to approximate.
00504         // Based on empirical measurements, each pixel transfer in our DMA
00505         // setup takes about 2us, so clocking 19 pixels takes about 38us.
00506         // In addition, the ADC takes about 4us extra for the first read.
00507         tInt = t.read_us() + 19*2 + 4;
00508     }
00509     
00510     // End of transfer notification.  This is called as an interrupt
00511     // handler when the DMA transfer completes.
00512     void transferDone()
00513     {
00514         // stop the ADC sampler
00515         ao.stop();
00516             
00517         // clock out one extra pixel to leave the analog out pin on
00518         // the sensor in the high-Z state
00519         clock = 1;
00520         clock = 0;
00521         
00522         // add this sample to the timing statistics (for diagnostics and
00523         // performance measurement)
00524         uint32_t now = t.read_us();
00525         totalTime += uint32_t(now - t0);
00526         nRuns += 1;
00527         
00528         // note the ending time of the transfer
00529         tDone = now;
00530         
00531         // Figure the time remaining to reach the minimum requested 
00532         // integration time for the next cycle.  The sensor is currently
00533         // working on an integration cycle that started at tInt, and that
00534         // cycle will end when we start the next cycle.  We therefore want
00535         // to wait to start the next cycle until we've reached the desired
00536         // total integration time.
00537         uint32_t dt = now - tInt;
00538         
00539         // Figure the time to the start of the next transfer.  Wait for the
00540         // remainder of the current integration period if we haven't yet
00541         // reached the requested minimum, otherwise just start almost
00542         // immediately.  (Not *actually* immediately: we don't want to start 
00543         // the new transfer within this interrupt handler, because the DMA
00544         // IRQ doesn't reliably clear if we start a new transfer immediately.)
00545         uint32_t dtNext = dt < tIntMin ? tIntMin - dt : 1;
00546 
00547         // Schedule the next transfer
00548         integrationTimeout.attach_us(this, &TSL14xx::startTransfer, dtNext);
00549     }
00550 
00551     // Clear the sensor shift register.  Clocks in all of the pixels from
00552     // the sensor without bothering to read them on the ADC.  Pulses SI 
00553     // at the beginning of the operation, which starts a new integration 
00554     // cycle.
00555     void clear()
00556     {
00557         // get the clock toggle register
00558         volatile uint32_t *ptor = &clockPort->PTOR;
00559         
00560         // make sure any DMA run is completed
00561         wait();
00562         
00563         // clock in an SI pulse
00564         si = 1;
00565         *ptor = clockMask;
00566         clockPort->PSOR = clockMask;
00567         si = 0;
00568         *ptor = clockMask;
00569         
00570         // This starts a new integration period.  Or more precisely, the
00571         // 19th clock pulse will start the new integration period.  We're
00572         // going to blast the clock signal as fast as we can, at about
00573         // 100ns intervals (50ns up and 50ns down), so the 19th clock
00574         // will be about 2us from now.
00575         tInt = t.read_us() + 2;
00576         
00577         // clock out all pixels, plus an extra one to clock past the last
00578         // pixel and reset the last pixel's internal sampling switch in
00579         // the sensor
00580         for (int i = 0 ; i < nPixSensor + 1 ; ) 
00581         {
00582             // toggle the clock to take it high
00583             *ptor = clockMask;
00584             
00585             // increment our loop variable here to pad the timing, to
00586             // keep our pulse width long enough for the sensor
00587             ++i;
00588             
00589             // toggle the clock to take it low
00590             *ptor = clockMask;
00591         }
00592     }
00593         
00594     // DMA controller interfaces
00595     SimpleDMA adc_dma;        // DMA channel for reading the analog input
00596     SimpleDMA clkUp_dma;      // "Clock Up" channel
00597     SimpleDMA clkDn_dma;      // "Clock Down" channel
00598 
00599     // Sensor interface pins
00600     DigitalOut si;            // GPIO pin for sensor SI (serial data) 
00601     DigitalOut clock;         // GPIO pin for sensor SCLK (serial clock)
00602     GPIO_Type *clockPort;     // IOPORT base address for clock pin - cached for DMA writes
00603     uint32_t clockMask;       // IOPORT register bit mask for clock pin
00604     AltAnalogIn_8bit ao;           // GPIO pin for sensor AO (analog output)
00605     
00606     // number of pixels in the physical sensor array
00607     int nPixSensor;           // number of pixels in physical sensor array
00608 
00609     // pixel buffers - we keep two buffers so that we can transfer the
00610     // current sensor data into one buffer via DMA while we concurrently
00611     // process the last buffer
00612     uint8_t *pix1;            // pixel array 1
00613     uint8_t *pix2;            // pixel array 2
00614     
00615     // Timestamps of pix1 and pix2 arrays, in microseconds, in terms of the 
00616     // sample timer (this->t).
00617     uint32_t t1;
00618     uint32_t t2;
00619     
00620     // DMA target buffer.  This is the buffer for the next DMA transfer.
00621     // 0 means pix1, 1 means pix2.  The other buffer contains the stable 
00622     // data from the last transfer.
00623     uint8_t pixDMA;
00624     
00625     // Stable buffer ownership.  At any given time, the DMA subsystem owns
00626     // the buffer specified by pixDMA.  The other buffer - the "stable" buffer,
00627     // which contains the most recent completed frame, can be owned by EITHER
00628     // the client or by the DMA subsystem.  Each time a DMA transfer completes,
00629     // the DMA subsystem looks at the stable buffer owner flag to determine 
00630     // what to do:
00631     //
00632     // - If the DMA subsystem owns the stable buffer, it swaps buffers.  This
00633     //   makes the newly completed DMA buffer the new stable buffer, and makes
00634     //   the old stable buffer the new DMA buffer.  At this time, the DMA 
00635     //   subsystem also changes the stable buffer ownership to CLIENT.
00636     //
00637     // - If the CLIENT owns the stable buffer, the DMA subsystem can't swap
00638     //   buffers, because the client is still using the stable buffer.  It
00639     //   simply leaves things as they are.
00640     //
00641     // In either case, the DMA system starts a new transfer at this point.
00642     //
00643     // The client, meanwhile, is free to access the stable buffer when it has
00644     // ownership.  If the client *doesn't* have ownership, it must wait for
00645     // the ownership to be transferred, which can only be done by the DMA
00646     // subsystem on completing a transfer.
00647     //
00648     // When the client is done with the stable buffer, it transfers ownership
00649     // back to the DMA subsystem.
00650     //
00651     // Transfers of ownership from DMA to CLIENT are done only by DMA.
00652     // Transfers from CLIENT to DMA are done only by CLIENT.  So whoever has
00653     // ownership now is responsible for transferring ownership.
00654     //
00655     volatile bool clientOwnsStablePix;
00656     
00657     // End-of-integration timeout handler.  This lets us fire an interrupt
00658     // when the current integration cycle is done, so that we can start the
00659     // next cycle.
00660     Timeout integrationTimeout;
00661     
00662     // Requested minimum integration time, in micoseconds.  The client can use 
00663     // this to control the exposure level, by increasing it for a longer
00664     // exposure and thus more light-gathering in low-light conditions.  Note 
00665     // that the physical limit on the minimum integration time is roughly equal 
00666     // to the pixel file transfer time, because the integration cycle is
00667     // initiated and ended by transfer starts.  It's thus impossible to make
00668     // the integration time less than the time for one full pixel file 
00669     // transfer.
00670     uint32_t tIntMin;
00671     
00672     // timing statistics
00673     Timer t;                  // sample timer
00674     uint32_t t0;              // start time (us) of current sample
00675     uint32_t tInt;            // start time (us) of current integration period
00676     uint32_t tDone;           // end time of latest finished transfer
00677     uint64_t totalTime;       // total time consumed by all reads so far
00678     uint32_t nRuns;           // number of runs so far
00679 };
00680  
00681 #endif /* TSL14XX_H */