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

Committer:
mjr
Date:
Mon Feb 15 23:03:55 2016 +0000
Revision:
68:edfecf67a931
Parent:
41:cbd237fe5021
Finalize USB library updates to fix compatibility problems introduced in USBHAL_KL25Z overhaul.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 17:ab3cec0c8bf4 1 // CCD plunger sensor
mjr 17:ab3cec0c8bf4 2 //
mjr 17:ab3cec0c8bf4 3 // This file implements our generic plunger sensor interface for the
mjr 17:ab3cec0c8bf4 4 // TAOS TSL1410R CCD array sensor.
mjr 17:ab3cec0c8bf4 5
mjr 17:ab3cec0c8bf4 6
mjr 17:ab3cec0c8bf4 7
mjr 25:e22b88bd783a 8 // Number of pixels we read from the CCD on each frame. Use the
mjr 25:e22b88bd783a 9 // sample size from config.h.
mjr 25:e22b88bd783a 10 const int npix = CCD_NPIXELS_SAMPLED;
mjr 17:ab3cec0c8bf4 11
mjr 25:e22b88bd783a 12 // PlungerSensor interface implementation for the CCD
mjr 17:ab3cec0c8bf4 13 class PlungerSensor
mjr 17:ab3cec0c8bf4 14 {
mjr 17:ab3cec0c8bf4 15 public:
mjr 17:ab3cec0c8bf4 16 PlungerSensor() : ccd(CCD_SO_PIN)
mjr 17:ab3cec0c8bf4 17 {
mjr 17:ab3cec0c8bf4 18 }
mjr 17:ab3cec0c8bf4 19
mjr 17:ab3cec0c8bf4 20 // initialize
mjr 17:ab3cec0c8bf4 21 void init()
mjr 17:ab3cec0c8bf4 22 {
mjr 17:ab3cec0c8bf4 23 // flush any random power-on values from the CCD's integration
mjr 17:ab3cec0c8bf4 24 // capacitors, and start the first integration cycle
mjr 17:ab3cec0c8bf4 25 ccd.clear();
mjr 17:ab3cec0c8bf4 26 }
mjr 17:ab3cec0c8bf4 27
mjr 17:ab3cec0c8bf4 28 // Perform a low-res scan of the sensor.
mjr 17:ab3cec0c8bf4 29 int lowResScan()
mjr 17:ab3cec0c8bf4 30 {
mjr 17:ab3cec0c8bf4 31 // read the pixels at low resolution
mjr 17:ab3cec0c8bf4 32 const int nlpix = 32;
mjr 17:ab3cec0c8bf4 33 uint16_t pix[nlpix];
mjr 17:ab3cec0c8bf4 34 ccd.read(pix, nlpix);
mjr 17:ab3cec0c8bf4 35
mjr 17:ab3cec0c8bf4 36 // determine which end is brighter
mjr 17:ab3cec0c8bf4 37 uint16_t p1 = pix[0];
mjr 17:ab3cec0c8bf4 38 uint16_t p2 = pix[nlpix-1];
mjr 41:cbd237fe5021 39 int si = 0, di = 1;
mjr 17:ab3cec0c8bf4 40 if (p1 < p2)
mjr 41:cbd237fe5021 41 si = nlpix - 1, di = -1;
mjr 17:ab3cec0c8bf4 42
mjr 17:ab3cec0c8bf4 43 // figure the shadow edge threshold - just use the midpoint
mjr 17:ab3cec0c8bf4 44 // of the levels at the bright and dark ends
mjr 17:ab3cec0c8bf4 45 uint16_t shadow = uint16_t((long(p1) + long(p2))/2);
mjr 17:ab3cec0c8bf4 46
mjr 17:ab3cec0c8bf4 47 // find the current tip position
mjr 17:ab3cec0c8bf4 48 for (int n = 0 ; n < nlpix ; ++n, si += di)
mjr 17:ab3cec0c8bf4 49 {
mjr 17:ab3cec0c8bf4 50 // check to see if we found the shadow
mjr 17:ab3cec0c8bf4 51 if (pix[si] <= shadow)
mjr 17:ab3cec0c8bf4 52 {
mjr 17:ab3cec0c8bf4 53 // got it - normalize it to normal 'npix' resolution and
mjr 17:ab3cec0c8bf4 54 // return the result
mjr 17:ab3cec0c8bf4 55 return n*npix/nlpix;
mjr 17:ab3cec0c8bf4 56 }
mjr 17:ab3cec0c8bf4 57 }
mjr 17:ab3cec0c8bf4 58
mjr 17:ab3cec0c8bf4 59 // didn't find a shadow - assume the whole array is in shadow (so
mjr 17:ab3cec0c8bf4 60 // the edge is at the zero pixel point)
mjr 17:ab3cec0c8bf4 61 return 0;
mjr 17:ab3cec0c8bf4 62 }
mjr 17:ab3cec0c8bf4 63
mjr 17:ab3cec0c8bf4 64 // Perform a high-res scan of the sensor.
mjr 17:ab3cec0c8bf4 65 bool highResScan(int &pos)
mjr 17:ab3cec0c8bf4 66 {
mjr 17:ab3cec0c8bf4 67 // read the array
mjr 18:5e890ebd0023 68 ccd.read(pix, npix);
mjr 17:ab3cec0c8bf4 69
mjr 18:5e890ebd0023 70 // get the brightness at each end of the sensor
mjr 18:5e890ebd0023 71 long b1 = pix[0];
mjr 18:5e890ebd0023 72 long b2 = pix[npix-1];
mjr 17:ab3cec0c8bf4 73
mjr 17:ab3cec0c8bf4 74 // Work from the bright end to the dark end. VP interprets the
mjr 17:ab3cec0c8bf4 75 // Z axis value as the amount the plunger is pulled: zero is the
mjr 17:ab3cec0c8bf4 76 // rest position, and the axis maximum is fully pulled. So we
mjr 17:ab3cec0c8bf4 77 // essentially want to report how much of the sensor is lit,
mjr 17:ab3cec0c8bf4 78 // since this increases as the plunger is pulled back.
mjr 18:5e890ebd0023 79 int si = 0, di = 1;
mjr 18:5e890ebd0023 80 long hi = b1;
mjr 18:5e890ebd0023 81 if (b1 < b2)
mjr 18:5e890ebd0023 82 si = npix - 1, di = -1, hi = b2;
mjr 17:ab3cec0c8bf4 83
mjr 17:ab3cec0c8bf4 84 // Figure the shadow threshold. In practice, the portion of the
mjr 17:ab3cec0c8bf4 85 // sensor that's not in shadow has all pixels consistently near
mjr 17:ab3cec0c8bf4 86 // saturation; the first drop in brightness is pretty reliably the
mjr 17:ab3cec0c8bf4 87 // start of the shadow. So set the threshold level to be closer
mjr 17:ab3cec0c8bf4 88 // to the bright end's brightness level, so that we detect the leading
mjr 17:ab3cec0c8bf4 89 // edge if the shadow isn't perfectly sharp. Use the point 1/3 of
mjr 17:ab3cec0c8bf4 90 // the way down from the high top the low side, so:
mjr 17:ab3cec0c8bf4 91 //
mjr 17:ab3cec0c8bf4 92 // threshold = lo + (hi - lo)*2/3
mjr 17:ab3cec0c8bf4 93 // = lo + hi*2/3 - lo*2/3
mjr 17:ab3cec0c8bf4 94 // = lo - lo*2/3 + hi*2/3
mjr 17:ab3cec0c8bf4 95 // = lo*1/3 + hi*2/3
mjr 17:ab3cec0c8bf4 96 // = (lo + hi*2)/3
mjr 17:ab3cec0c8bf4 97 //
mjr 18:5e890ebd0023 98 // Now, 'lo' is always one of b1 or b2, and 'hi' is the other
mjr 18:5e890ebd0023 99 // one, so we can rewrite this as:
mjr 18:5e890ebd0023 100 long midpt = (b1 + b2 + hi)/3;
mjr 17:ab3cec0c8bf4 101
mjr 17:ab3cec0c8bf4 102 // If we have enough contrast, proceed with the scan.
mjr 17:ab3cec0c8bf4 103 //
mjr 17:ab3cec0c8bf4 104 // If the bright end and dark end don't differ by enough, skip this
mjr 17:ab3cec0c8bf4 105 // reading entirely. Either we have an overexposed or underexposed frame,
mjr 17:ab3cec0c8bf4 106 // or the sensor is misaligned and is either fully in or out of shadow
mjr 17:ab3cec0c8bf4 107 // (it's supposed to be mounted such that the edge of the shadow always
mjr 17:ab3cec0c8bf4 108 // falls within the sensor, for any possible plunger position).
mjr 18:5e890ebd0023 109 if (labs(b1 - b2) > 0x1000)
mjr 17:ab3cec0c8bf4 110 {
mjr 17:ab3cec0c8bf4 111 uint16_t *pixp = pix + si;
mjr 18:5e890ebd0023 112 for (int n = 0 ; n < npix ; ++n, pixp += di)
mjr 17:ab3cec0c8bf4 113 {
mjr 17:ab3cec0c8bf4 114 // if we've crossed the midpoint, report this position
mjr 18:5e890ebd0023 115 if (long(*pixp) < midpt)
mjr 17:ab3cec0c8bf4 116 {
mjr 17:ab3cec0c8bf4 117 // note the new position
mjr 17:ab3cec0c8bf4 118 pos = n;
mjr 17:ab3cec0c8bf4 119 return true;
mjr 17:ab3cec0c8bf4 120 }
mjr 17:ab3cec0c8bf4 121 }
mjr 17:ab3cec0c8bf4 122 }
mjr 17:ab3cec0c8bf4 123
mjr 17:ab3cec0c8bf4 124 // we didn't find a shadow - return no reading
mjr 17:ab3cec0c8bf4 125 return false;
mjr 17:ab3cec0c8bf4 126 }
mjr 17:ab3cec0c8bf4 127
mjr 17:ab3cec0c8bf4 128 // send an exposure report to the joystick interface
mjr 17:ab3cec0c8bf4 129 void sendExposureReport(USBJoystick &js)
mjr 17:ab3cec0c8bf4 130 {
mjr 17:ab3cec0c8bf4 131 // send reports for all pixels
mjr 17:ab3cec0c8bf4 132 int idx = 0;
mjr 17:ab3cec0c8bf4 133 while (idx < npix)
mjr 18:5e890ebd0023 134 {
mjr 17:ab3cec0c8bf4 135 js.updateExposure(idx, npix, pix);
mjr 18:5e890ebd0023 136 wait_ms(1);
mjr 18:5e890ebd0023 137 }
mjr 17:ab3cec0c8bf4 138
mjr 17:ab3cec0c8bf4 139 // The pixel dump requires many USB reports, since each report
mjr 17:ab3cec0c8bf4 140 // can only send a few pixel values. An integration cycle has
mjr 17:ab3cec0c8bf4 141 // been running all this time, since each read starts a new
mjr 17:ab3cec0c8bf4 142 // cycle. Our timing is longer than usual on this round, so
mjr 17:ab3cec0c8bf4 143 // the integration won't be comparable to a normal cycle. Throw
mjr 17:ab3cec0c8bf4 144 // this one away by doing a read now, and throwing it away - that
mjr 17:ab3cec0c8bf4 145 // will get the timing of the *next* cycle roughly back to normal.
mjr 17:ab3cec0c8bf4 146 ccd.read(pix, npix);
mjr 17:ab3cec0c8bf4 147 }
mjr 17:ab3cec0c8bf4 148
mjr 17:ab3cec0c8bf4 149 private:
mjr 17:ab3cec0c8bf4 150 // pixel buffer
mjr 17:ab3cec0c8bf4 151 uint16_t pix[npix];
mjr 17:ab3cec0c8bf4 152
mjr 17:ab3cec0c8bf4 153 // the low-level interface to the CCD hardware
mjr 17:ab3cec0c8bf4 154 TSL1410R<CCD_SI_PIN, CCD_CLOCK_PIN> ccd;
mjr 17:ab3cec0c8bf4 155 };