
Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array
Fork of Pinscape_Controller by
Revision 10:976666ffa4ef, committed 2014-08-23
- Comitter:
- mjr
- Date:
- Sat Aug 23 01:24:36 2014 +0000
- Parent:
- 9:fd65b0a94720
- Child:
- 11:bd9da7088e6e
- Commit message:
- Add raw pixel dump support for use by the Windows config tool
Changed in this revision
--- a/USBDevice.lib Mon Aug 18 21:46:10 2014 +0000 +++ b/USBDevice.lib Sat Aug 23 01:24:36 2014 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mjr/code/USBDevice/#81f57ea86f8f +http://mbed.org/users/mjr/code/USBDevice/#a8eb758f4074
--- a/USBJoystick/USBJoystick.cpp Mon Aug 18 21:46:10 2014 +0000 +++ b/USBJoystick/USBJoystick.cpp Sat Aug 23 01:24:36 2014 +0000 @@ -26,7 +26,7 @@ _y = y; _z = z; _buttons = buttons; - _status = (uint8_t)status; + _status = status; // send the report return update(); @@ -37,15 +37,38 @@ // Fill the report according to the Joystick Descriptor #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff) - put(0, _buttons); - put(2, _x); - put(4, _y); - put(6, _z); - report.data[8] = _status; - report.length = 9; + put(0, _status); + put(2, 0); // second byte of status isn't used in normal reports + put(4, _buttons); + put(6, _x); + put(8, _y); + put(10, _z); + report.length = 12; // send the report - return sendNB(&report); + return sendTO(&report, 100); +} + +bool USBJoystick::updateExposure(int &idx, int npix, const uint16_t *pix) +{ + HID_REPORT report; + + // Set the special status bits to indicate it's an exposure report. + // The high 5 bits of the status word are set to 10000, and the + // low 11 bits are the current pixel index. + uint16_t s = idx | 0x8000; + put(0, s); + + // now fill out the remaining words with exposure values + report.length = 12; + for (int ofs = 2 ; ofs + 1 < report.length ; ofs += 2) + { + uint16_t p = (idx < npix ? pix[idx++] : 0); + put(ofs, p); + } + + // send the report + return send(&report); } bool USBJoystick::move(int16_t x, int16_t y) { @@ -106,6 +129,15 @@ // COLLECTION(1), 0x00, // Physical // input report (device to host) + + USAGE_PAGE(1), 0x06, // generic device controls - for config status + USAGE(1), 0x00, // undefined device control + LOGICAL_MINIMUM(1), 0x00, // 8-bit values + LOGICAL_MAXIMUM(1), 0xFF, + REPORT_SIZE(1), 0x08, // 8 bits per report + REPORT_COUNT(1), 0x04, // 4 reports (4 bytes) + INPUT(1), 0x02, // Data, Variable, Absolute + USAGE_PAGE(1), 0x09, // Buttons USAGE_MINIMUM(1), 0x01, // { buttons } USAGE_MAXIMUM(1), 0x10, // { 1-16 } @@ -127,14 +159,6 @@ REPORT_COUNT(1), 0x03, // 3 reports (X, Y, Z) INPUT(1), 0x02, // Data, Variable, Absolute - USAGE_PAGE(1), 0x06, // generic device controls - for config status - USAGE(1), 0x00, // undefined device control - LOGICAL_MINIMUM(1), 0x00, // 1-bit flags - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, // 1 bit per report - REPORT_COUNT(1), 0x08, // 8 reports (8 bits) - INPUT(1), 0x02, // Data, Variable, Absolute - // output report (host to device) REPORT_SIZE(1), 0x08, // 8 bits per report REPORT_COUNT(1), 0x08, // output report count (LEDWiz messages)
--- a/USBJoystick/USBJoystick.h Mon Aug 18 21:46:10 2014 +0000 +++ b/USBJoystick/USBJoystick.h Sat Aug 23 01:24:36 2014 +0000 @@ -107,6 +107,18 @@ * @returns true if there is no error, false otherwise */ bool update(int16_t x, int16_t y, int16_t z, uint16_t buttons, uint16_t status); + + /** + * Write an exposure report. We'll fill out a report with as many pixels as + * will fit in the packet, send the report, and update the index to the next + * pixel to send. The caller should call this repeatedly to send reports for + * all pixels. + * + * @param idx current index in pixel array, updated to point to next pixel to send + * @param npix number of pixels in the overall array + * @param pix pixel array + */ + bool updateExposure(int &idx, int npix, const uint16_t *pix); /** * Write a state of the mouse @@ -156,7 +168,7 @@ int16_t _y; int16_t _z; uint16_t _buttons; - uint8_t _status; + uint16_t _status; void _init(); };
--- a/main.cpp Mon Aug 18 21:46:10 2014 +0000 +++ b/main.cpp Sat Aug 23 01:24:36 2014 +0000 @@ -181,6 +181,31 @@ // byte 0 = 65 (0x41) // byte 1 = 2 (0x02) // +// Exposure reports: the host can request a report of the full set of pixel +// values for the next frame by sending this special packet: +// +// length = 8 bytes +// byte 0 = 65 (0x41) +// byte 1 = 3 (0x03) +// +// We'll respond with a series of special reports giving the exposure status. +// Each report has the following structure: +// +// bytes 0:1 = 11-bit index, with high 5 bits set to 10000. For +// example, 0x04 0x80 indicates index 4. This is the +// starting pixel number in the report. The first report +// will be 0x00 0x80 to indicate pixel #0. +// bytes 2:3 = 16-bit unsigned int brightness level of pixel at index +// bytes 4:5 = brightness of pixel at index+1 +// etc for the rest of the packet +// +// This still has the form of a joystick packet at the USB level, but +// can be differentiated by the host via the status bits. It would have +// been cleaner to use a different Report ID at the USB level, but this +// would have necessitated a different container structure in the report +// descriptor, which would have broken LedWiz compatibility. Given that +// constraint, we have to re-use the joystick report type, making for +// this somewhat kludgey approach. #include "mbed.h" #include "math.h" @@ -983,6 +1008,9 @@ // of these bits: // 0x01 -> plunger sensor enabled uint16_t statusFlags = (cfg.d.ccdEnabled ? 0x01 : 0x00); + + // flag: send a pixel dump after the next read + bool reportPix = false; // we're all set up - now just loop, processing sensor reports and // host requests @@ -1064,6 +1092,17 @@ calBtnTimer.reset(); cfg.resetPlunger(); } + else if (data[1] == 3) + { + // 3 = pixel dump + // (No parameters) + reportPix = true; + + // show purple until we finish sending the report + ledR = 0; + ledB = 0; + ledG = 1; + } } else { @@ -1193,6 +1232,7 @@ } // read the plunger sensor, if it's enabled + uint16_t pix[npix]; if (cfg.d.ccdEnabled) { // start with the previous reading, in case we don't have a @@ -1200,7 +1240,6 @@ int znew = z; // read the array - uint16_t pix[npix]; ccd.read(pix, npix); // get the average brightness at each end of the sensor @@ -1338,14 +1377,6 @@ int fireTol = z/3 > JOYMAX/6 ? z/3 : JOYMAX/6; static const int firePattern[] = { -JOYMAX/12, -JOYMAX/12, -JOYMAX/12, - 0, 0, 0, - JOYMAX/16, JOYMAX/16, JOYMAX/16, - 0, 0, 0, - -JOYMAX/20, -JOYMAX/20, -JOYMAX/20, - 0, 0, 0, - JOYMAX/24, JOYMAX/24, JOYMAX/24, - 0, 0, 0, - -JOYMAX/30, -JOYMAX/30, -JOYMAX/30 }; if (firing != 0) { @@ -1442,6 +1473,27 @@ // joystick and Y Axis = Y on the joystick. js.update(y, x, z, 0, statusFlags); + // If we're in pixel dump mode, report all pixel exposure values + if (reportPix) + { + // we have satisfied this request + reportPix = false; + + // send reports for all pixels + int idx = 0; + while (idx < npix) + js.updateExposure(idx, npix, pix); + + // The pixel dump requires many USB reports, since each report + // can only send a few pixel values. An integration cycle has + // been running all this time, since each read starts a new + // cycle. Our timing is longer than usual on this round, so + // the integration won't be comparable to a normal cycle. Throw + // this one away by doing a read now, and throwing it away - that + // will get the timing of the *next* cycle roughly back to normal. + ccd.read(pix, npix); + } + #ifdef DEBUG_PRINTF if (x != 0 || y != 0) printf("%d,%d\r\n", x, y);