
Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array
Fork of Pinscape_Controller by
Revision 14:df700b22ca08, committed 2014-09-26
- Comitter:
- mjr
- Date:
- Fri Sep 26 20:51:02 2014 +0000
- Parent:
- 13:72dda449c3c0
- Child:
- 15:eb8aac252eba
- Commit message:
- Reduce button input latency by reducing debounce time and polling during CCD read cycle
Changed in this revision
--- a/TSL1410R/tsl1410r.h Sat Sep 13 23:47:32 2014 +0000 +++ b/TSL1410R/tsl1410r.h Fri Sep 26 20:51:02 2014 +0000 @@ -34,7 +34,11 @@ // 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 // the current pixels and start a fresh integration cycle. - void read(uint16_t *pix, int n); + void read(uint16_t *pix, int n) { read(pix, n, 0, 0, 0); } + + // 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); // Clock through all pixels to clear the array. Pulses SI at the // beginning of the operation, which starts a new integration cycle.
--- a/TSL1410R/tsl410r.cpp Sat Sep 13 23:47:32 2014 +0000 +++ b/TSL1410R/tsl410r.cpp Fri Sep 26 20:51:02 2014 +0000 @@ -24,7 +24,7 @@ } } -void TSL1410R::read(uint16_t *pix, int n) +void TSL1410R::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; @@ -34,22 +34,41 @@ // 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 the pixels - for (int src = 0, dst = 0 ; src < nPix ; ++src) + // read all of the pixels + for (int src = 0, dst = 0 ; src < nPix ; ) { - // read this pixel - pix[dst++] = ao.read_u16(); + // figure the end of this callback interval + int srcEnd = src + cbInterval; + if (srcEnd > nPix) + srcEnd = nPix; - // clock in the next pixel - clock = 1; - clock = 0; + // read one callback chunk of pixels + for ( ; src < srcEnd ; ++src) + { + // read this pixel + pix[dst++] = ao.read_u16(); - // clock skipped pixels - for (int i = 0 ; i < skip ; ++i, ++src) { + // clock in the next pixel clock = 1; clock = 0; + + // 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
--- a/main.cpp Sat Sep 13 23:47:32 2014 +0000 +++ b/main.cpp Fri Sep 26 20:51:02 2014 +0000 @@ -706,9 +706,9 @@ // start timing the next interval buttonTimer.reset(); - // AND together readings over 50ms + // AND together readings over 25ms int ms = 0; - for (int i = 1 ; i < countof(readings) && ms < 50 ; ++i) + for (int i = 1 ; i < countof(readings) && ms < 25 ; ++i) { // find the next prior reading, wrapping in the circular buffer int j = ri - i; @@ -1125,11 +1125,19 @@ // --------------------------------------------------------------------------- // -// Clear the I2C bus for the MMA8451!. This seems necessary some of the time +// Clear the I2C bus for the MMA8451Q. This seems necessary some of the time // for reasons that aren't clear to me. Doing a hard power cycle has the same // effect, but when we do a soft reset, the hardware sometimes seems to leave // the MMA's SDA line stuck low. Forcing a series of 9 clock pulses through -// the SCL line is supposed to clear this conidtion. +// the SCL line is supposed to clear this condition. I'm not convinced this +// actually works with the way this component is wired on the KL25Z, but it +// seems harmless, so we'll do it on reset in case it does some good. What +// we really seem to need is a way to power cycle the MMA8451Q if it ever +// gets stuck, but this is simply not possible in software on the KL25Z. +// +// If the accelerometer does get stuck, and a software reboot doesn't reset +// it, the only workaround is to manually power cycle the whole KL25Z by +// unplugging both of its USB connections. // void clear_i2c() { @@ -1146,6 +1154,21 @@ wait_us(20); } } + +// --------------------------------------------------------------------------- +// +// CCD read interval callback. When reading the CCD, we'll call this +// several times over the course of the read loop to refresh the button +// states. This allows us to debounce the buttons while the long CCD +// read cycle is taking place, so that we can reliably report button +// states after each CCD read cycle. (The read cycle takes about 30ms, +// which should be enough time to reliably debounce the buttons.) +// +void ccdReadCB(void *) +{ + // read the keyboard + readButtonsDebounced(); +} // --------------------------------------------------------------------------- // @@ -1496,7 +1519,7 @@ int znew = z; // read the array - ccd.read(pix, npix); + ccd.read(pix, npix, ccdReadCB, 0, 3); // get the average brightness at each end of the sensor long avg1 = (long(pix[0]) + long(pix[1]) + long(pix[2]) + long(pix[3]) + long(pix[4]))/5;