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

Files at this revision

API Documentation at this revision

Comitter:
mjr
Date:
Tue Sep 01 04:27:15 2015 +0000
Parent:
24:e902bc7cdc1e
Child:
26:cb71c4af2912
Commit message:
Centralized the CCD pixel count setting to a single config.h option; added an option to config.h to select the board's mounting orientation for the accelerometer

Changed in this revision

TSL1410R/tsl1410r.h Show annotated file Show diff for this revision Revisions of this file
USBJoystick/USBJoystick.cpp Show annotated file Show diff for this revision Revisions of this file
ccdSensor.h Show annotated file Show diff for this revision Revisions of this file
config.h 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	Wed Jun 03 18:52:22 2015 +0000
+++ b/TSL1410R/tsl1410r.h	Tue Sep 01 04:27:15 2015 +0000
@@ -5,6 +5,7 @@
  */
  
  #include "mbed.h"
+ #include "config.h"
  #include "FastIO.h"
  #include "FastAnalogIn.h"
  
@@ -119,7 +120,7 @@
     }
 
     // number of pixels in the array
-    static const int nPix = 1280;
+    static const int nPix = CCD_NPIXELS;
     
     
 private:
--- a/USBJoystick/USBJoystick.cpp	Wed Jun 03 18:52:22 2015 +0000
+++ b/USBJoystick/USBJoystick.cpp	Tue Sep 01 04:27:15 2015 +0000
@@ -71,10 +71,20 @@
     // low 11 bits are the current pixel index.
     uint16_t s = idx | 0x8000;
     put(0, s);
+    
+    // start at the second byte
+    int ofs = 2;
+    
+    // in the first report, add the total pixel count as the next two bytes
+    if (idx == 0)
+    {
+        put(ofs, npix);
+        ofs += 2;
+    }
         
     // now fill out the remaining words with exposure values
     report.length = reportLen;
-    for (int ofs = 2 ; ofs + 1 < report.length ; ofs += 2)
+    for ( ; ofs + 1 < report.length ; ofs += 2)
     {
         uint16_t p = (idx < npix ? pix[idx++] : 0);
         put(ofs, p);
--- a/ccdSensor.h	Wed Jun 03 18:52:22 2015 +0000
+++ b/ccdSensor.h	Tue Sep 01 04:27:15 2015 +0000
@@ -5,37 +5,11 @@
 
 
 
-// Number of pixels we read from the CCD on each frame.  This can be
-// less than the actual sensor size if desired; if so, we'll read every
-// nth pixel.  E.g., with a 1280-pixel physical sensor, if npix is 320,
-// we'll read every 4th pixel.  Reading a pixel is fairly time-consuming,
-// because it requires waiting for the pixel's electric charge to
-// stabilize on the CCD output, for the charge to transfer to the KL25Z 
-// input, and then for the KL25Z analog voltage sampler to get a stable
-// reading.  This all takes about 15us per pixel, which adds up to
-// a relatively long time in such a large array.  However, we can skip
-// a pixel without waiting for all of that charge stabilization time,
-// so we can get higher frame rates by only sampling a subset of the
-// pixels.  The array is so dense (400dpi) that we can still get
-// excellent resolution by reading a fraction of the total pixels.
-//
-// Empirically, 160 pixels seems to be the point of diminishing returns
-// for resolution - going higher will only improve the apparent smoothness
-// slightly, if at all.  160 pixels gives us 50dpi on the sensor, which 
-// is roughly the same as the physical pixel pitch of a typical cabinet 
-// playfield monitor.  (1080p HDTV displayed 1920x1080 pixels, and a 40" 
-// TV is about 35" wide, so the dot pitch is about 55dpi across the width 
-// of the TV.  If on-screen plunger is displayed at roughly the true
-// physical size, it's about 3" on the screen, or about 165 pixels.  So at
-// 160 pixels on the sensor, one pixel on the sensor translates to almost
-// exactly one on-screen pixel on the TV, which makes the animated motion 
-// on-screen about as smooth as it can be.  Looked at another way, 50dpi
-// means that we're measuring the physical shooter rod position in about
-// half-millimeter increments, which is probably better than I can 
-// discern by feel or sight.
-const int npix = 160;
+// Number of pixels we read from the CCD on each frame.  Use the
+// sample size from config.h.
+const int npix = CCD_NPIXELS_SAMPLED;
 
-
+// PlungerSensor interface implementation for the CCD
 class PlungerSensor
 {
 public:
--- a/config.h	Wed Jun 03 18:52:22 2015 +0000
+++ b/config.h	Tue Sep 01 04:27:15 2015 +0000
@@ -5,6 +5,8 @@
 // button at the top of the window.  That will generate a customized .bin
 // file that you can download onto your KL25Z board.
 
+#ifndef CONFIG_H
+#define CONFIG_H
 
 // --------------------------------------------------------------------------
 //
@@ -32,6 +34,27 @@
 #define ENABLE_JOYSTICK
 
 
+// Accelerometer orientation.  The accelerometer feature lets Visual Pinball 
+// (and other pinball software) sense nudges to the cabinet, and simulate 
+// the effect on the ball's trajectory during play.  We report the direction
+// of the accelerometer readings as well as the strength, so it's important
+// for VP and the KL25Z to agree on the physical orientation of the
+// accelerometer relative to the cabinet.  The accelerometer on the KL25Z
+// is always mounted the same way on the board, but we still have to know
+// which way you mount the board in your cabinet.  We assume as default
+// orientation where the KL25Z is mounted flat on the bottom of your
+// cabinet with the USB ports pointing forward, toward the coin door.  If
+// it's more convenient for you to mount the board in a different direction,
+// you simply need to select the matching direction here.  Comment out the
+// ORIENTATION_PORTS_AT_FRONT line and un-comment the line that matches
+// your board's orientation.
+
+#define ORIENTATION_PORTS_AT_FRONT      // USB ports pointing toward front of cabinet
+// #define ORIENTATION_PORTS_AT_LEFT    // USB ports pointing toward left side of cab
+// #define ORIENTATION_PORTS_AT_RIGHT   // USB ports pointing toward right side of cab
+// #define ORIENTATION_PORTS_AT_REAR    // USB ports pointing toward back of cabinet
+
+
 // --------------------------------------------------------------------------
 // 
 // LedWiz default unit number.
@@ -89,6 +112,50 @@
 
 #define ENABLE_CCD_SENSOR
 
+// Physical pixel count for your sensor.  This software has been tested with
+// TAOS TSL1410R (1280 pixels) and TSL1412R (1536 pixels) sensors.  It might
+// work with other similar sensors as well, but you'll probably have to make
+// some changes to the software interface to the sensor if you're using any
+// sensor outside of the TAOS TSL14xxR series.
+//
+// If you're not using a CCD sensor, you can ignore this.
+const int CCD_NPIXELS = 1280;
+
+// Number of pixels from the CCD to sample on each high-res scan.  We don't
+// sample every pixel from the sensor on each scan, because (a) we don't
+// have to, and (b) we don't want to.  We don't have to sample all of the
+// pixels because these sensors have much finer resolution than we need to
+// get good results.  On a typical pinball cabinet setup with a 1920x1080
+// HD TV display, the on-screen plunger travel distance is about 165 pixels,
+// so that's all the pixels we need to sample for pixel-accurate animation.
+// Even so, we still *could* sample at higher resolution, but we don't *want*
+// to sample more pixels than we have to,  because reading each pixel takes 
+// time.  The limiting factor for read speed is the sampling time for the ADC 
+// (analog to digital  converter); it needs about 20us per sample to get an 
+// accurate voltage reading.  We want to animate the on-screen plunger in 
+// real time, with minimal lag, so it's important that we complete each scan 
+// as quickly as possible.  The fewer pixels we sample, the faster we 
+// complete each scan.
+//
+// Happily, the time needed to read the approximately 165 pixels required
+// for pixel-accurate positioning on the display is short enough that we can
+// complete a scan within the cycle time for USB reports.  USB gives us a
+// whole separate timing factor; we can't go much *faster* with USB than
+// sending a new report about every 10ms.  The sensor timing is such that
+// we can read about 165 pixels in well under 10ms.  So that's really the
+// sweet spot for our scans.
+//
+// Note that we distribute the sampled pixels evenly across the full range
+// of the sensor's pixels.  That is, we read every nth pixel, and skip the
+// ones in between.  That means that the sample count here has to be an even
+// divisor of the physical pixel count.  Empirically, reading every 8th
+// pixel gives us good results on both the TSL1410R and TSL1412R, so you
+// shouldn't need to change this if you're using one of those sensors.  If
+// you're using a different sensor, you should be sure to adjust this so that 
+// it works out to an integer result with no remainder.
+//
+const int CCD_NPIXELS_SAMPLED = CCD_NPIXELS / 8;
+
 // The KL25Z pins that the CCD sensor is physically attached to:
 //
 //  CCD_SI_PIN = the SI (sensor data input) pin
@@ -231,6 +298,8 @@
 // push mode.
 const float LaunchBallPushDistance = .08;
 
+#endif // CONFIG_H
+
 
 #ifdef DECL_EXTERNS
 // --------------------------------------------------------------------------
@@ -409,17 +478,17 @@
     { PTC10, false },    // pin J1-13, LW port 20
     { PTC11, false },    // pin J1-15, LW port 21
     { PTE0, false },     // pin J2-18, LW port 22
-    { NC, false },       // Not used,  LW port 23
-    { NC, false },       // Not used,  LW port 24
-    { NC, false },       // Not used,  LW port 25
-    { NC, false },       // Not used,  LW port 26
-    { NC, false },       // Not used,  LW port 27
-    { NC, false },       // Not used,  LW port 28
-    { NC, false },       // Not used,  LW port 29
-    { NC, false },       // Not used,  LW port 30
-    { NC, false },       // Not used,  LW port 31
-    { NC, false }        // Not used,  LW port 32
+    { NC, false },       // Not connected,  LW port 23
+    { NC, false },       // Not connected,  LW port 24
+    { NC, false },       // Not connected,  LW port 25
+    { NC, false },       // Not connected,  LW port 26
+    { NC, false },       // Not connected,  LW port 27
+    { NC, false },       // Not connected,  LW port 28
+    { NC, false },       // Not connected,  LW port 29
+    { NC, false },       // Not connected,  LW port 30
+    { NC, false },       // Not connected,  LW port 31
+    { NC, false }        // Not connected,  LW port 32
 };
 
 
-#endif // DECL_EXTERNS
\ No newline at end of file
+#endif // DECL_EXTERNS
--- a/main.cpp	Wed Jun 03 18:52:22 2015 +0000
+++ b/main.cpp	Tue Sep 01 04:27:15 2015 +0000
@@ -258,6 +258,36 @@
 // Joystick axis report range - we report from -JOYMAX to +JOYMAX
 #define JOYMAX 4096
 
+// --------------------------------------------------------------------------
+//
+// Set up mappings for the joystick X and Y reports based on the mounting
+// orientation of the KL25Z in the cabinet.  Visual Pinball and other 
+// pinball software effectively use video coordinates to define the axes:
+// positive X is to the right of the table, negative Y to the left, positive
+// Y toward the front of the table, negative Y toward the back.  The KL25Z
+// accelerometer is mounted on the board with positive Y toward the USB
+// ports and positive X toward the right side of the board with the USB
+// ports pointing up.  It's a simple matter to remap the KL25Z coordinate
+// system to match VP's coordinate system for mounting orientations at
+// 90-degree increments...
+//
+#if defined(ORIENTATION_PORTS_AT_FRONT)
+# define JOY_X(x, y)   (y)
+# define JOY_Y(x, y)   (x)
+#elif defined(ORIENTATION_PORTS_AT_LEFT)
+# define JOY_X(x, y)   (-(x))
+# define JOY_Y(x, y)   (y)
+#elif defined(ORIENTATION_PORTS_AT_RIGHT)
+# define JOY_X(x, y)   (x)
+# define JOY_Y(x, y)   (-(y))
+#elif defined(ORIENTATION_PORTS_AT_REAR)
+# define JOY_X(x, y)   (-(y))
+# define JOY_Y(x, y)   (-(x))
+#else
+# error Please define one of the ORIENTATION_PORTS_AT_xxx macros to establish the accelerometer orientation in your cabinet
+#endif
+
+
 
 // --------------------------------------------------------------------------
 //
@@ -1813,14 +1843,11 @@
             // a traditional plunger.
             int zrep = (ZBLaunchBallPort != 0 && wizOn[ZBLaunchBallPort-1] ? 0 : z);
             
-            // Send the status report.  Note that the nominal x and y axes
-            // are reversed - this makes it more intuitive to set up in VP.
-            // If we mount the Freesale card flat on the floor of the cabinet
-            // with the USB connectors facing the front of the cabinet, this
-            // arrangement of our nominal axes aligns with VP's standard
-            // setting, so that we can configure VP with X Axis = X on the
-            // joystick and Y Axis = Y on the joystick.
-            js.update(y, x, zrep, buttons | simButtons, statusFlags);
+            // Send the status report.  Note that we have to map the X and Y
+            // axes from the accelerometer to match the Windows joystick axes.
+            // The mapping is determined according to the mounting direction
+            // set in config.h via the ORIENTATION_xxx macros.
+            js.update(JOY_X(x,y), JOY_Y(x,y), zrep, buttons | simButtons, statusFlags);
             
             // we've just started a new report interval, so reset the timer
             reportTimer.reset();