Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array

Dependencies:   USBDevice mbed

Fork of Pinscape_Controller by Mike R

Files at this revision

API Documentation at this revision

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

TSL1410R/tsl1410r.h Show annotated file Show diff for this revision Revisions of this file
TSL1410R/tsl410r.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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;