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
Revision 25:e22b88bd783a, committed 2015-09-01
- 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
--- 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();