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

TCD1103.h

00001 // Toshiba TCD1103 linear CCD image sensor, 1x1500 pixels.
00002 //
00003 // This sensor is conceptually similar to the TAOS TSL1410R (the original 
00004 // Pinscape sensor!).  Like the TSL1410R, it has a linear array of optical
00005 // sensor pixels that convert incident photons into electrical charge, an
00006 // internal shift register connected to the pixel file that acts as an 
00007 // electronic shutter, and a serial interface that clocks the pixels out
00008 // to the host in analog voltage level format.
00009 //
00010 // The big physical difference between this sensor and the old TAOS sensors
00011 // is the size.  The TAOS sensors were (by some miracle) approximately the
00012 // same size as the plunger travel range, so we were able to take "contact"
00013 // images without any optics, by placing the plunger close to the sensor,
00014 // back-lighting it, and essentially taking a picture of its shadow.  The
00015 // Toshiba sensor, in contrast, has a pixel window that's only 8mm long, so
00016 // the contact image approach won't work.  Instead, we have to use a lens
00017 // to focus a reduced image (about 1:10 scale) on the sensor.  That makes
00018 // the physical setup more complex, but it has the great advantage that we
00019 // get a focused image.  The shadow was always fuzzy in  the old contact 
00020 // image approach, which reduced the effective resolution when determining 
00021 // the plunger position.  With a focused image, we can get single-pixel 
00022 // resolution.  With this Toshiba sensor's 1500 pixels, that's about 500 
00023 // dpi, which beats every other sensor we've come up with.
00024 //
00025 // The electronic interface to this sensor is similar to the TAOS, but it
00026 // has enough differences that we can't share the same code base.
00027 //
00028 // As with the 1410R, we have to use DMA for the ADC transfers in order
00029 // to keep up with the high data rate without overloading the KL25Z CPU.
00030 // With the 1410R, we're able to use the ADC itself as the clock source,
00031 // by running the ADC in continous mode and using its "sample ready" signal
00032 // to trigger the DMA transfer.  We used this to generate the external clock
00033 // signal for the sensor by "linking" the ADC's DMA channel to another pair
00034 // of DMA channels that generated the clock up/down signal each time an ADC
00035 // sample completed.  This strategy won't work with the Toshiba sensor,
00036 // though, because the Toshiba sensor's timing sequence requires *two* clock
00037 // pulses per pixel.  I can't come up with a way to accomplish that with the
00038 // linked-DMA approach.  Instead, we'll have to generate a true clock signal
00039 // for the sensor, and drive the DMA conversions off of that clock.
00040 //
00041 // The obvious (and, as far as I can tell, only) way to generate the clock
00042 // signal with the KL25Z at the high frequency required is to use a TPM -
00043 // the KL25Z module that drives PWM outputs.  TPM channels are designed
00044 // precisely for this kind of work, so this is the right approach in terms of
00045 // suitability, but it has the downside that TPM units are an extremely scarce
00046 // resource on the KL25Z.  We only have three of them to work with.  Luckily,
00047 // the rest of the Pinscape software only requires two of them: one for the
00048 // IR transmitter (which uses a TPM channel to generate the 41-48 kHz carrier
00049 // wave used by nearly all consumer IR remotes), and one for the TLC5940
00050 // driver (which uses it to generate the grayscale clock signal).  Note that
00051 // we also use PWM channels for feedback device output ports, but those don't
00052 // have any dependency on the TPM period - they'll work with whatever period
00053 // the underlying TPM is set to use.  So the feedback output ports can all
00054 // happily use free channels on TPM units claimed by any of the dedicated
00055 // users (IR, TLC5940, and us).
00056 //
00057 // But what do we do about the 2:1 ratio between master clock pulses and ADC
00058 // samples?  The "right" way would be to allocate a second TPM unit to
00059 // generate a second clock signal at half the frequency of the master clock, 
00060 // and use that as the ADC trigger.  But as we just said, we only have three 
00061 // TPM units in the whole system, and two of them are already claimed for 
00062 // other uses, so we only have one unit available for our use here.
00063 //
00064 // Fortunately, we can make do with one TPM unit, by taking advantage of a 
00065 // feature/quirk of the KL25Z ADC.  The quirk lets us take ADC samples at
00066 // exactly half of the master clock rate, in perfect sync.  The trick is to
00067 // pick a combination of master clock rate and ADC sample mode such that the
00068 // ADC conversion time is *almost but not quite* twice as long as the master
00069 // clock rate.  With that combination of timings, we can trigger the ADC
00070 // from the TPM, and we'll get an ADC sample on exactly every other tick of
00071 // the master clock.  The reason this works is that the KL25Z ADC ignores
00072 // hardware triggers (the TPM trigger is a hardware trigger) that occur when
00073 // a conversion is already in progress.  So if the ADC sampling time is more
00074 // than one master clock period, the ADC will always be busy one clock tick
00075 // after a sample starts, so it'll ignore that first clock tick.  But as 
00076 // long as the sampling time is less than *two* master clock periods, the
00077 // ADC will always be ready again on the second tick.  So we'll get one ADC
00078 // sample for every two master clock ticks, exactly as we need.
00079 //
00080 // This is all possible because the ADC timing is deterministic, and runs on
00081 // the same clock as the TPM.  The KL25Z Subfamily Reference Manual explains
00082 // how to calculate the ADC conversion time for a given combination of mode
00083 // bits.  So we just have to pick an ADC mode, calculate its conversion time,
00084 // and then select a TPM period that's slightly more than 1/2 of the ADC
00085 // conversion time.
00086 //
00087 //
00088 // Pixel output signal
00089 //
00090 // The pixel output signal from this sensor is an analog voltage level.  It's
00091 // inverted from the brightness: higher brightness is represented by lower
00092 // voltage.  The dynamic range is only about 1V - dark pixels read at about 
00093 // 2V, and saturated pixels read at about 1V.  
00094 //
00095 //
00096 // Inverted logic signals
00097 //
00098 // The Toshiba data sheet recommends buffering the logic signal inputs from 
00099 // an MCU through a 74HC04 inverter, because the sensor's logic gates have
00100 // relatively high input capacitance that an MCU might not be able to drive 
00101 // fast enough directly to keep up with the sensor's timing requirements.  
00102 // SH in particular might be a problem because of its 150pF capacitance,
00103 // which implies about a 2us rise/fall time if driven directly by KL25Z
00104 // GPIOs, which is too slow.
00105 //
00106 // The software willo work with or without the logic inversion, in case anyone
00107 // wants to try implementing it with direct GPIO drive (not recommended) or 
00108 // with a non-inverting buffer in place of the 74HC04.  Simply instantiate the
00109 // class with the 'invertedLogicGates' template parameter set to false to use 
00110 // non-inverted logic.
00111 //
00112 //
00113 // How to connect to the KL25Z
00114 //
00115 // Follow the "typical drive circuit" presented in the Toshiba data sheet.
00116 // They leave some of the parts unspecified, so here are the specific values
00117 // we used for our reference implementation:
00118 //
00119 //   - 3.3V power supply
00120 //   - 74HC04N hex inverter for the logic gate inputs (fM, SH, ICG)
00121 //   - 0.1uF ceramic + 10uF electrolytic decoupling capacitors (GND to Vcc))
00122 //   - BC212A PNP transistor for the output drive (OS), with:
00123 //     - 150 ohm resistor on the base
00124 //     - 150 ohm resistor between collector and GND
00125 //     - 2.2K ohm resistor between emitter and Vcc
00126 //
00127 
00128 #include "config.h"
00129 #include "NewPwm.h"
00130 #include "AltAnalogIn.h"
00131 #include "SimpleDMA.h"
00132 #include "DMAChannels.h"
00133 
00134 
00135 template<bool invertedLogicGates> class TCD1103
00136 {
00137 public:
00138     TCD1103(PinName fmPin, PinName osPin, PinName icgPin, PinName shPin) :
00139        fm(fmPin, invertedLogicGates),
00140        os(osPin, false, 6, 1),    // single sample, 6-cycle long sampling mode, no averaging
00141        icg(icgPin), 
00142        sh(shPin),
00143        os_dma(DMAch_TDC_ADC)
00144     {
00145         // Idle conditions: SH low, ICG high.
00146         sh = logicLow;
00147         icg = logicHigh;
00148 
00149         // Set a zero minimum integration time by default.  Note that tIntMin
00150         // has no effect when it's less than the absolute minimum, which is
00151         // the pixel transfer time for one frame (around 3ms).  tIntMin only
00152         // kicks in when it goes above that absolute minimum, at which point
00153         // we'll wait for any additional time needed to reach tIntMin before
00154         // starting the next integration cycle.
00155         tIntMin = 0;
00156 
00157         // Calibrate the ADC for best accuracy
00158         os.calibrate();
00159         
00160         // ADC sample conversion time.  This must be calculated based on the
00161         // combination of parameters selected for the os() initializer above.
00162         // See the KL25 Sub-Family Reference Manual, section 28.4.4.5, for the
00163         // formula.  We operate in single-sample mode, so when you read the
00164         // Reference Manual tables, the sample time value to use is the
00165         // "First or Single" value.
00166         const float ADC_TIME = 2.1041667e-6f; // 6-cycle long sampling, no averaging
00167 
00168         // Set the TPM cycle time to satisfy our timing constraints:
00169         // 
00170         //   Tm + epsilon1 < A < 2*Tm - epsilon2
00171         //
00172         // where A is the ADC conversion time and Tm is the master clock
00173         // period, and the epsilons provide a margin of safety for any 
00174         // non-deterministic component to the timing of A and Tm.  The
00175         // epsilons could be zero if the timing of the ADC is perfectly
00176         // deterministic; this must be determined empirically.
00177         //
00178         // The most conservative solution would be to make epsilon as large
00179         // as possible, which means bisecting the time window by making
00180         // A = 1.5*T, or, equivalently, T = A/1.5 (the latter form being more 
00181         // useful because T is the free variable here, as we can only control
00182         // A to the extent that we can choose the ADC parameters).
00183         //
00184         // But we'd also like to make T as short as possible while maintaining
00185         // reliable operation.  Shorter T yields a higher frame rate, and we
00186         // want the frame rate to be as high as possible so that we can track
00187         // fast plunger motion accurately.  Empirically, we can get reliable
00188         // results by using half of the ADC time plus a small buffer time.
00189         //
00190         fm.getUnit()->period(masterClockPeriod = ADC_TIME/2 + 0.25e-6f);
00191         
00192         // Start the master clock running with a 50% duty cycle
00193         fm.write(0.5f);
00194 
00195         // Allocate our double pixel buffers.  
00196         pix1 = new uint8_t[nPixAlo * 2];
00197         pix2 = pix1 + nPixAlo;
00198         
00199         // put the first DMA transfer into the first buffer (pix1)
00200         pixDMA = 0;
00201         clientOwnsStablePix = false;
00202 
00203         // start the sample timer with an arbitrary epoch of "now"
00204         t.start();
00205 
00206         // Set up the ADC transfer DMA channel.  This channel transfers
00207         // the current analog sampling result from the ADC output register
00208         // to our pixel array.
00209         os.initDMA(&os_dma);
00210 
00211         // Register an interrupt callback so that we're notified when
00212         // the last ADC transfer completes.
00213         os_dma.attach(this, &TCD1103::transferDone);
00214         
00215         // Set up the ADC to trigger on the master clock's TPM channel
00216         os.setTriggerTPM(fm.getUnitNum());
00217         
00218         // clear the timing statistics        
00219         totalXferTime = 0.0; 
00220         maxXferTime = 0;
00221         minXferTime = 0xffffffff;
00222         nRuns = 0;
00223 
00224         // start the first transfer
00225         startTransfer();
00226     }
00227         
00228     // logic gate levels, based on whether or not the logic gate connections
00229     // in the hardware are buffered through inverters
00230     static const int logicLow = invertedLogicGates ? 1 : 0;
00231     static const bool logicHigh = invertedLogicGates ? 0 : 1;
00232     
00233     // ready to read
00234     bool ready() { return clientOwnsStablePix; }
00235         
00236     // Get the stable pixel array.  This is the image array from the
00237     // previous capture.  It remains valid until the next startCapture()
00238     // call, at which point this buffer will be reused for the new capture.
00239     void getPix(uint8_t * &pix, uint32_t &t)
00240     {
00241         // Return the pixel array that ISN'T assigned to the DMA.
00242         if (pixDMA)
00243         {
00244             // DMA owns pix2, so the stable array is pix1
00245             pix = pix1;
00246             t = t1;
00247         }
00248         else
00249         {
00250             // DMA owns pix1, so the stable array is pix2
00251             pix = pix2;
00252             t = t2;
00253         }
00254     }
00255     
00256     // release the client's pixel buffer
00257     void releasePix() { clientOwnsStablePix = false; }
00258     
00259     // figure the average scan time from the running totals
00260     uint32_t getAvgScanTime() { return static_cast<uint32_t>(totalXferTime / nRuns);}
00261 
00262     // Set the requested minimum integration time.  If this is less than the
00263     // sensor's physical minimum time, the physical minimum applies.
00264     virtual void setMinIntTime(uint32_t us)
00265     {
00266         tIntMin = us;
00267     }
00268     
00269 protected:
00270     // Start an image capture from the sensor.  Waits the previous
00271     // capture to finish if it's still running, then starts a new one
00272     // and returns immediately.  The new capture proceeds asynchronously 
00273     // via DMA hardware transfer, so the client can continue with other 
00274     // processing during the capture.
00275     void startTransfer()
00276     {
00277         // if we own the stable buffer, swap buffers
00278         if (!clientOwnsStablePix)
00279         {
00280             // swap buffers
00281             pixDMA ^= 1;
00282             
00283             // release the prior DMA buffer to the client
00284             clientOwnsStablePix = true;
00285         }
00286         
00287         // figure our destination buffer
00288         uint8_t *dst = pixDMA ? pix2 : pix1;
00289         
00290         // Set up the active pixel array as the destination buffer for 
00291         // the ADC DMA channel. 
00292         os_dma.destination(dst, true);
00293         
00294         // Start the read cycle by sending the ICG/SH pulse sequence
00295         uint32_t tNewInt = gen_SH_ICG_pulse(true);
00296 
00297         // Set the timestamp for the current active buffer.  The ICG/SH
00298         // gymnastics we just did transferred the CCD pixels into the sensor's
00299         // internal shift register and reset the pixels, starting a new
00300         // integration cycle.  So the pixels we just shifted started
00301         // integrating the *last* time we did that, which we recorded as
00302         // tInt at the time.  The image we're about to transfer therefore 
00303         // represents the light collected between tInt and the SH pulse we
00304         // just did.  The image covers a time range rather than a single 
00305         // point in time, but we still have to give it a single timestamp. 
00306         // Use the midpoint of the integration period.
00307         uint32_t tmid = (tNewInt + tInt) >> 1;
00308         if (pixDMA)
00309             t2 = tmid;
00310         else
00311             t1 = tmid;
00312 
00313         // Record the start time of the currently active integration period
00314         tInt = tNewInt;
00315     }
00316     
00317     // End of transfer notification.  This runs as an interrupt handler when
00318     // the DMA transfer completes.
00319     void transferDone()
00320     {
00321         // stop the ADC triggering
00322         os.stop();
00323 
00324         // add this sample to the timing statistics (for diagnostics and
00325         // performance measurement)
00326         uint32_t now = t.read_us();
00327         uint32_t dt = dtPixXfer = static_cast<uint32_t>(now - tXfer);
00328         totalXferTime += dt;
00329         nRuns += 1;
00330         
00331         // collect debug statistics
00332         if (dt < minXferTime) minXferTime = dt;
00333         if (dt > maxXferTime) maxXferTime = dt;
00334 
00335         // figure how long we've been integrating so far on this cycle 
00336         uint32_t dtInt = now - tInt;
00337         
00338         // Figure the time to the start of the next transfer.  Wait for the
00339         // remainder of the current integration period if we haven't yet
00340         // reached the requested minimum, otherwise just start almost
00341         // immediately.  (Not *actually* immediately: we don't want to start 
00342         // the new transfer within this interrupt handler, because the DMA
00343         // IRQ doesn't reliably clear if we start a new transfer immediately.)
00344         uint32_t dtNext = dtInt < tIntMin ? tIntMin - dtInt : 1;
00345         
00346         // Schedule the next transfer
00347         integrationTimeout.attach_us(this, &TCD1103::startTransfer, dtNext);
00348     }
00349 
00350     // Generate an SH/ICG pulse.  This transfers the pixel data from the live
00351     // sensor photoreceptors into the sensor's internal shift register, clears
00352     // the live pixels, and starts a new integration cycle.
00353     //
00354     // If start_dma_xfer is true, we'll start the DMA transfer for the ADC
00355     // pixel data.  We handle this here because the sensor starts clocking
00356     // out pixels precisely at the end of the ICG pulse, so we have to be
00357     // be very careful about the timing.
00358     //
00359     // Returns the timestamp (relative to our image timer 't') of the end
00360     // of the SH pulse, which is the moment the new integration cycle starts.
00361     //
00362     // Note that we send these pulses synchronously - that is, this routine
00363     // blocks until the pulses have been sent.  The overall sequence takes 
00364     // about 2.5us to 3us, so it's not a significant interruption of the 
00365     // main loop.
00366     //
00367     uint32_t gen_SH_ICG_pulse(bool start_dma_xfer)
00368     {
00369         // Make sure the ADC is stopped
00370         os.stop();
00371 
00372         // If desired, prepare to start the DMA transfer for the ADC data.
00373         // (Set up a dummy location to write in lieu of the DMA register if
00374         // DMA initiation isn't required, so that we don't have to take the
00375         // time for a conditional when we're ready to start the DMA transfer.
00376         // The timing there will be extremely tight, and we can't afford the
00377         // extra instructions to test a condition.)
00378         uint8_t dma_chcfg_dummy = 0;
00379         volatile uint8_t *dma_chcfg = start_dma_xfer ? os_dma.prepare(nPixSensor, true) : &dma_chcfg_dummy;
00380         
00381         // The basic idea is to take ICG low, and while holding ICG low,
00382         // pulse SH.  The coincidence of the two pulses transfers the charge
00383         // from the live pixels into the shift register, which effectively
00384         // discharges the live pixels and thereby starts a new integration
00385         // cycle.
00386         //
00387         // The timing of the pulse sequence is rather tightly constrained 
00388         // per the data sheet, so we have to take some care in executing it:
00389         //
00390         //   ICG ->  LOW
00391         //   100-1000 ns delay   (*)
00392         //   SH -> HIGH
00393         //   >1000ns delay
00394         //   SH -> LOW
00395         //   >1000ns delay
00396         //   ICG -> high         (**)
00397         //
00398         // There are two steps here that are tricky:
00399         //
00400         // (*) is a narrow window that we can't achieve with an mbed 
00401         // microsecond timer.  Instead, we'll do a couple of extra writes 
00402         // to the ICG register, which take about 60ns each.
00403         //
00404         // (**) has the rather severe constraint that the transition must 
00405         // occur AND complete while the master clock is high.  Other people 
00406         // working with similar Toshiba chips in MCU projects have suggested
00407         // that this constraint can safely be ignored, so maybe the data
00408         // sheet's insistence about it is obsolete advice from past Toshiba
00409         // sensors that the doc writers carried forward by copy-and-paste.
00410         // Toshiba has been making these sorts of chips for a very long time,
00411         // and the data sheets for many of them are obvious copy-and-paste
00412         // jobs.  But let's take the data sheet at its word and assume that 
00413         // this is important for proper operation.  Our best hope of 
00414         // satisfying this constraint is to synchronize the start of the
00415         // ICG->high transition with the start of a TPM cycle on the master
00416         // clock.  That guarantees that the ICG transition starts when the
00417         // clock signal is high (as each TPM cycle starts out high), and
00418         // gives us the longest possible runway for the transition to
00419         // complete while the clock is still high, as we get the full
00420         // length of the high part of the cycle to work with.  To quantify,
00421         // it gives us about 600ns.  The register write takes about 60ns, 
00422         // and waitEndCycle() adds several instructions of overhead, perhaps
00423         // 200ns, so we get around 300ns for the transition to finish.  That
00424         // should be a gracious plenty assuming that the hardware is set up 
00425         // with an inverter to buffer the clock signals.  The inverter should
00426         // be able to pull up the 35pF on ICG in a "typical" 30ns (rise time
00427         // plus propagation delay, per the 74HC04 data sheet) and max 150ns.
00428         // This seems to be one place where the inverter might really be
00429         // necessary to meet the timing requirements, as the KL25Z GPIO
00430         // might need more like 2us to pull that load up.
00431         //
00432         // There's an additional constraint on the timing at the end of the
00433         // ICG pulse.  The sensor starts clocking out pixels on the rising
00434         // edge of the ICG pulse.  So we need the ICG pulse end to align
00435         // with the start of an ADC cycle.  If we get that wrong, all of our
00436         // ADC samples will be off by half a clock, so every sample will be
00437         // the average of two adjacent pixels instead of one pixel.  That
00438         // would have the effect of shifting the image by half a pixel,
00439         // which could make our edge detection jitter by one pixel from one
00440         // frame to the next.  So we definitely want to avoid this.
00441         //
00442         // The end of the SH pulse triggers the start of a new integration 
00443         // cycle, so note the time of that pulse for image timestamping 
00444         // purposes.  That will be the start time of the NEXT image we 
00445         // transfer after we shift out the current sensor pixels, which 
00446         // represent the pixels from the last time we pulsed SH.
00447         //
00448         icg = logicLow;
00449         icg = logicLow;  // for timing, adds about 150ns > min 100ns
00450 
00451         sh = logicHigh;  // take SH high
00452         
00453         wait_us(1);      // >1000ns delay
00454         sh = logicHigh;  // a little more padding to be sure we're over the minimum
00455         
00456         sh = logicLow;   // take SH low
00457         
00458         uint32_t t_sh = t.read_us();  // this is the start time of the NEXT integration
00459         
00460         wait_us(3);      // >1000ns delay, 5000ns typical; 3us should get us most
00461                          // of the way there, considering that we have some more
00462                          // work to do before we end the ICG pulse
00463         
00464         // Now the tricky part!  We have to end the ICG pulse (take ICG high)
00465         // at the start of a master clock cycle, AND at the start of an ADC 
00466         // sampling cycle.  The sensor will start clocking out pixels the
00467         // instance ICG goes high, so we have to align our ADC cycle so that
00468         // we start a sample at almost exactly the same time we take ICG
00469         // high.
00470         //
00471         // Now, every ADC sampling cycle always starts at a rising edge of 
00472         // the master clock, since the master clock is the ADC trigger.  BUT,
00473         // the converse is NOT true: every rising edge of the master clock
00474         // is NOT an ADC sample start.  Recall that we've contrived the timing
00475         // so that every OTHER master clock rising edge starts an ADC sample.
00476         // 
00477         // So how do we detect which part of the clock cycle we're in?  We
00478         // could conceivably use the COCO bit in the ADC status register to
00479         // detect the little window between the end of one sample and the
00480         // start of the next.  Unfortunately, this doesn't work: the COCO
00481         // bit is never actually set for the duration of even a single CPU
00482         // instruction in our setup, no matter how loose we make the timing
00483         // between the ADC and the fM cycle.  I think the reason is the DMA
00484         // setup: the COCO bit triggers the DMA, and the DMA controller
00485         // reads the ADC result register (the DMA source in our setup),
00486         // which has the side effect of clearing COCO.  I've experimented
00487         // with this using different timing parameters, and the result is
00488         // always the same: the CPU *never* sees the COCO bit set.  The DMA
00489         // trigger timing is evidently deterministic such that the DMA unit
00490         // invariably gets its shot at reading ADC0->R before the CPU does.
00491         //
00492         // The COCO approach would be a little iffy anyway, since we want the
00493         // ADC idle time to be as short as possible, which wouldn't give us
00494         // much time to do all we have to do in the COCO period, even if
00495         // there were one.  What we can do instead is seize control of the
00496         // ADC cycle timing: rather than trying to detect when the cycle
00497         // ends, we can specify when it begins.  We can do this by canceling
00498         // the TPM->ADC trigger and aborting any conversion in progress, then
00499         // reprogramming the TPM->ADC trigger at our leisure.  What we *can*
00500         // detect reliably is the start of a TPM cycle.  So here's our
00501         // strategy:
00502         //
00503         //   - Turn off the TPM->ADC trigger and abort the current conversion
00504         //   - Wait until a new TPM cycle starts
00505         //   - Reset the TPM->ADC trigger.  The first new conversion will
00506         //     start on the next TPM cycle, so we have the remainder of
00507         //     the current TPM cycle to make this happen (about 1us, enough
00508         //     for 16 CPU instructions - plenty for this step)
00509         //   - Wait for the new TPM cycle
00510         //   - End the ICG pulse
00511         //
00512         
00513         // Enable the DMA controller for the new transfer from the ADC.
00514         // The sensor will start clocking out new samples at the ICG rising
00515         // edge, so the next ADC sample to complete will represent the first
00516         // pixel in the new frame.  So we need the DMA ready to go at the
00517         // very next sample.  Recall that the DMA is triggered by ADC
00518         // completion, and ADC is stopped right now, so enabling the DMA 
00519         // won't have any immediate effect - it just spools it up so that
00520         // it's ready to move samples as soon as we resume the ADC.
00521         *dma_chcfg |= DMAMUX_CHCFG_ENBL_MASK;
00522         
00523         // wait for the start of a new master clock cycle
00524         fm.waitEndCycle();
00525         
00526         // Wait one more cycle to be sure the DMA is ready.  Empirically,
00527         // this extra wait is actually required; evidently DMA startup has
00528         // some non-deterministic timing element or perhaps an asynchronous
00529         // external dependency.  In any case, *without* this extra wait,
00530         // the DMA transfer sporadically (about 20% probability) misses the
00531         // very first pixel that the sensor clocks out, so the entire image
00532         // is shifted "left" by one pixel.  That makes the position sensing
00533         // jitter by a pixel from one frame to the next according to whether
00534         // or not we had that one-pixel delay in the DMA startup.  Happily,
00535         // padding the timing by an fM cycle seems to make the DMA startup
00536         // perfectly reliable.
00537         fm.waitEndCycle();
00538         
00539         // Okay, a master clock cycle just started, so we have about 1us 
00540         // (about 16 CPU instructions) before the next one begins.  Resume 
00541         // ADC sampling.  The first new sample will start with the next
00542         // TPM cycle 1us from now.  This step itself takes about 3 machine
00543         // instructions for 180ns, so we have about 820ns left to go.
00544         os.resume();
00545         
00546         // Eerything is queued up!  We just have to fire the starting gun
00547         // on the sensor at the right moment.  And that right moment is the 
00548         // start of the next TPM cycle.  Wait for it...
00549         fm.waitEndCycle();
00550         
00551         // And go!
00552         icg = logicHigh;
00553         
00554         // note the start time of the transfer
00555         tXfer = t.read_us();
00556         
00557         // return the timestamp of the end of the SH pulse - this is the start
00558         // of the new integration period that we just initiated
00559         return t_sh;
00560     }
00561 
00562     // master clock
00563     NewPwmOut fm;
00564     
00565     // analog input for reading the pixel voltage level
00566     AltAnalogIn_8bit os;
00567     
00568     // Integration Clear Gate output
00569     DigitalOut icg;
00570     
00571     // Shift Gate output
00572     DigitalOut sh;
00573     
00574     // DMA channel for the analog input
00575     SimpleDMA os_dma;
00576     
00577     // Master clock period, in seconds, calculated based on the ADC timing
00578     float masterClockPeriod;
00579     
00580     // Number of pixels.  The TCD1103 has 1500 image pixels, plus 32 dummy
00581     // pixels at the front end (before the first image pixel) and another 14
00582     // dummy pixels at the back end.  The sensor always transfers the full
00583     // file on each read cycle, including the dummies, so we have to make
00584     // room for the dummy pixels during each read.
00585     static const int nPixSensor = 1546;
00586     
00587     // Figure the number of pixels to allocate per pixel buffer.  Round
00588     // up to the next 4-byte boundary, so that the buffers are both DWORD-
00589     // aligned.  (This allows using DWORD pointers into the buffer to 
00590     // operate on buffer pixels four at a time, such as in the negative 
00591     // image inversion code in the generic PlungerSensorImage base class.)
00592     static const int nPixAlo = (nPixSensor + 3) & ~3;
00593     
00594     // pixel buffers - we keep two buffers so that we can transfer the
00595     // current sensor data into one buffer via DMA while we concurrently
00596     // process the last buffer
00597     uint8_t *pix1;            // pixel array 1
00598     uint8_t *pix2;            // pixel array 2
00599     
00600     // Timestamps of pix1 and pix2 arrays, in microseconds, in terms of the 
00601     // sample timer (this->t).
00602     uint32_t t1;
00603     uint32_t t2;
00604     
00605     // DMA target buffer.  This is the buffer for the next DMA transfer.
00606     // 0 means pix1, 1 means pix2.  The other buffer contains the stable 
00607     // data from the last transfer.
00608     uint8_t pixDMA;
00609     
00610     // Stable buffer ownership.  At any given time, the DMA subsystem owns
00611     // the buffer specified by pixDMA.  The other buffer - the "stable" buffer,
00612     // which contains the most recent completed frame, can be owned by EITHER
00613     // the client or by the DMA subsystem.  Each time a DMA transfer completes,
00614     // the DMA subsystem looks at the stable buffer owner flag to determine 
00615     // what to do:
00616     //
00617     // - If the DMA subsystem owns the stable buffer, it swaps buffers.  This
00618     //   makes the newly completed DMA buffer the new stable buffer, and makes
00619     //   the old stable buffer the new DMA buffer.  At this time, the DMA 
00620     //   subsystem also changes the stable buffer ownership to CLIENT.
00621     //
00622     // - If the CLIENT owns the stable buffer, the DMA subsystem can't swap
00623     //   buffers, because the client is still using the stable buffer.  It
00624     //   simply leaves things as they are.
00625     //
00626     // In either case, the DMA system starts a new transfer at this point.
00627     //
00628     // The client, meanwhile, is free to access the stable buffer when it has
00629     // ownership.  If the client *doesn't* have ownership, it must wait for
00630     // the ownership to be transferred, which can only be done by the DMA
00631     // subsystem on completing a transfer.
00632     //
00633     // When the client is done with the stable buffer, it transfers ownership
00634     // back to the DMA subsystem.
00635     //
00636     // Transfers of ownership from DMA to CLIENT are done only by DMA.
00637     // Transfers from CLIENT to DMA are done only by CLIENT.  So whoever has
00638     // ownership now is responsible for transferring ownership.
00639     //
00640     volatile bool clientOwnsStablePix;
00641     
00642     // Minimum requested integration time, in microseconds
00643     uint32_t tIntMin;
00644     
00645     // Timeout for generating an interrupt at the end of the integration period
00646     Timeout integrationTimeout;
00647         
00648     // timing statistics
00649     Timer t;                  // sample timer
00650     uint32_t tInt;            // start time (us) of current integration period
00651     uint32_t tXfer;           // start time (us) of current pixel transfer
00652     uint32_t dtPixXfer;       // pixel transfer time of last frame
00653     uint64_t totalXferTime;   // total time consumed by all reads so far
00654     uint32_t nRuns;           // number of runs so far
00655     
00656     // debugging - min/max transfer time statistics
00657     uint32_t minXferTime;
00658     uint32_t maxXferTime;
00659 };