An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.
Dependencies: mbed FastIO FastPWM USBDevice
Fork of Pinscape_Controller by
USBJoystick.h
00001 /* USBJoystick.h */ 00002 /* USB device example: Joystick*/ 00003 /* Copyright (c) 2011 ARM Limited. All rights reserved. */ 00004 /* Modified Mouse code for Joystick - WH 2012 */ 00005 00006 #ifndef USBJOYSTICK_H 00007 #define USBJOYSTICK_H 00008 00009 #include "USBHID.h" 00010 #include "circbuf.h" 00011 00012 // Bufferd incoming LedWiz message structure 00013 struct LedWizMsg 00014 { 00015 uint8_t data[8]; 00016 }; 00017 00018 // interface IDs 00019 const uint8_t IFC_ID_JS = 0; // joystick + LedWiz interface 00020 const uint8_t IFC_ID_KB = 1; // keyboard interface 00021 00022 // keyboard interface report IDs 00023 const uint8_t REPORT_ID_KB = 1; 00024 const uint8_t REPORT_ID_MEDIA = 2; 00025 00026 /* Common usage */ 00027 enum JOY_BUTTON { 00028 JOY_B0 = 0x0001, 00029 JOY_B1 = 0x0002, 00030 JOY_B2 = 0x0004, 00031 JOY_B3 = 0x0008, 00032 JOY_B4 = 0x0010, 00033 JOY_B5 = 0x0020, 00034 JOY_B6 = 0x0040, 00035 JOY_B7 = 0x0080, 00036 JOY_B8 = 0x0100, 00037 JOY_B9 = 0x0200, 00038 JOY_B10 = 0x0400, 00039 JOY_B11 = 0x0800, 00040 JOY_B12 = 0x1000, 00041 JOY_B13 = 0x2000, 00042 JOY_B14 = 0x4000, 00043 JOY_B15 = 0x8000 00044 }; 00045 00046 /** 00047 * 00048 * USBJoystick example 00049 * @code 00050 * #include "mbed.h" 00051 * #include "USBJoystick.h" 00052 * 00053 * USBJoystick joystick; 00054 * 00055 * int main(void) 00056 * { 00057 * while (1) 00058 * { 00059 * joystick.move(20, 0); 00060 * wait(0.5); 00061 * } 00062 * } 00063 * 00064 * @endcode 00065 * 00066 * 00067 * @code 00068 * #include "mbed.h" 00069 * #include "USBJoystick.h" 00070 * #include <math.h> 00071 * 00072 * USBJoystick joystick; 00073 * 00074 * int main(void) 00075 * { 00076 * while (1) { 00077 * // Basic Joystick 00078 * joystick.update(tx, y, z, buttonBits); 00079 * wait(0.001); 00080 * } 00081 * } 00082 * @endcode 00083 */ 00084 00085 00086 class USBJoystick: public USBHID 00087 { 00088 public: 00089 // Length of our joystick reports. Important: This must be kept in sync 00090 // with the actual joystick report format sent in update(). 00091 static const int reportLen = 14; 00092 00093 // Joystick axis report format 00094 static const int AXIS_FORMAT_XYZ = 0; // nudge on X/Y, plunger on Z 00095 static const int AXIS_FORMAT_RXRYRZ = 1; // nudge on Rx/Ry, plunger on Rz 00096 00097 /** 00098 * Constructor 00099 * 00100 * @param vendor_id Your vendor_id (default: 0x1234) 00101 * @param product_id Your product_id (default: 0x0002) 00102 * @param product_release Your product_release (default: 0x0001) 00103 * @param waitforConnect don't return until the connection is established 00104 * @param enableJoystick enable the joystick interface (if false, uses the OUT-only LedWiz-style interface) 00105 * @param axisFormat an AXIS_FORMAT_xxx value specifying the joystick axis report format 00106 * @param useKB enable the USB keyboard reporting interface 00107 */ 00108 USBJoystick(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, 00109 int waitForConnect, bool enableJoystick, int axisFormat, bool useKB) 00110 : USBHID(16, 64, vendor_id, product_id, product_release, false) 00111 { 00112 _init(); 00113 this->useKB = useKB; 00114 this->enableJoystick = enableJoystick; 00115 this->axisFormat = axisFormat; 00116 connect(waitForConnect); 00117 }; 00118 00119 /* read a report from the LedWiz buffer */ 00120 bool readLedWizMsg(LedWizMsg &msg) 00121 { 00122 return lwbuf.read(msg); 00123 } 00124 00125 /* get the idle time settings, in milliseconds */ 00126 uint32_t getKbIdle() const { return kbIdleTime * 4UL; } 00127 uint32_t getMediaIdle() const { return mediaIdleTime * 4UL; } 00128 00129 00130 /** 00131 * Send a keyboard report. The argument gives the key state, in the standard 00132 * 6KRO USB keyboard report format: byte 0 is the modifier key bit mask, byte 1 00133 * is reserved (must be 0), and bytes 2-6 are the currently pressed keys, as 00134 * USB key codes. 00135 */ 00136 bool kbUpdate(uint8_t data[8]); 00137 00138 /** 00139 * Send a media key update. The argument gives the bit mask of media keys 00140 * currently pressed. See the HID report descriptor for the order of bits. 00141 */ 00142 bool mediaUpdate(uint8_t data); 00143 00144 /** 00145 * Update the joystick status 00146 * 00147 * @param x x-axis position 00148 * @param y y-axis position 00149 * @param z z-axis position 00150 * @param buttons buttons state, as a bit mask (combination with '|' of JOY_Bn values) 00151 * @returns true if there is no error, false otherwise 00152 */ 00153 bool update(int16_t x, int16_t y, int16_t z, uint32_t buttons, uint16_t status); 00154 00155 /** 00156 * Update just the status 00157 */ 00158 bool updateStatus(uint32_t stat); 00159 00160 /** 00161 * Write the plunger status report header. 00162 * 00163 * Note that we automatically add the "calibration mode" bit to the flags, 00164 * so the caller doesn't have to include this. The caller only has to 00165 * include the sensor-specific flags. 00166 * 00167 * @param npix number of pixels in the sensor (0 for non-imaging sensors) 00168 * @param pos the decoded plunger position, or -1 if none detected 00169 * @param flags (see USBProtocol.h, message type 2A, "byte 7" bit flags) 00170 * @param avgScanTime average sensor scan time in microseconds 00171 * @param processingTime time in microseconds to process the current frame 00172 */ 00173 bool sendPlungerStatus(int npix, int pos, int flags, 00174 uint32_t avgScanTime, uint32_t processingTime); 00175 00176 /** 00177 * Send a secondary plunger status report header. 00178 * 00179 * @param nativeScale upper bound of the sensor's native reading scale 00180 * @param jitterLo low end of jitter filter window (in sensor native scale units) 00181 * @param jitterHi high end of jitter filter window 00182 * @param rawPos raw position reading, before applying jitter filter 00183 * @param axcTime auto-exposure time in microseconds 00184 */ 00185 bool sendPlungerStatus2( 00186 int nativeScale, int jitterLo, int jitterHi, int rawPos, int axcTime); 00187 00188 /** 00189 * Send a barcode plunger status report header. 00190 * 00191 * @param nbits number of bits in bar code 00192 * @param codetype bar code type (1=Gray code/Manchester bit coding) 00193 * @param pixofs pixel offset of first bit 00194 * @param raw raw bar code bits 00195 * @param mask mask of successfully read bar code bits 00196 */ 00197 bool sendPlungerStatusBarcode( 00198 int nbits, int codetype, int startOfs, int pixPerBit, int raw, int mask); 00199 00200 /** 00201 * Send a quadrature sensor status report header. 00202 * 00203 * @param chA channel "A" reading 00204 * @param chB channel "B" reading 00205 */ 00206 bool sendPlungerStatusQuadrature(int chA, int chB); 00207 00208 /** 00209 * Send a VCNL4010 sensor extra status report 00210 * 00211 * @param proxCount raw proximity count reading from the sensor 00212 */ 00213 bool sendPlungerStatusVCNL4010(int filteredProxCount, int rawProxCount); 00214 00215 /** 00216 * Write an exposure report. We'll fill out a report with as many pixels as 00217 * will fit in the packet, send the report, and update the index to the next 00218 * pixel to send. The caller should call this repeatedly to send reports for 00219 * all pixels. 00220 * 00221 * @param idx current index in pixel array, updated to point to next pixel to send 00222 * @param npix number of pixels in the overall array 00223 * @param pix pixel array 00224 */ 00225 bool sendPlungerPix(int &idx, int npix, const uint8_t *pix); 00226 00227 /** 00228 * Write a configuration report. 00229 * 00230 * @param numOutputs the number of configured output channels 00231 * @param unitNo the device unit number 00232 * @param plungerZero plunger zero calibration point 00233 * @param plungerMax plunger max calibration point 00234 * @param plungerRlsTime measured plunger release time, in milliseconds 00235 * @param configured true if a configuration has been saved to flash from the host 00236 * @param sbxpbx true if this firmware version supports SBX/PBX protocol extensions 00237 * @param newAccelFeatures true if this firmware version supports the new accelerometer 00238 * features (adjustable dynamic range, adjustable auto-centering mode time, 00239 * auto-centering mode on/off) 00240 * @param flashStatusFeature true if this firmware version supports the flash write 00241 * success flags in the status bits 00242 * @param reportTimingFeatures true if this firmware version supports configurable 00243 * joystick report timing 00244 * @param chimeLogicFeature true if this firmware version supports Chime Logic 00245 * @param freeHeapBytes number of free bytes in the malloc heap 00246 */ 00247 bool reportConfig(int numOutputs, int unitNo, 00248 int plungerZero, int plungerMax, int plunterRlsTime, 00249 bool configured, bool sbxpbx, bool newAccelFeatures, 00250 bool flashStatusFeature, bool reportTimingFeatures, 00251 bool chimeLogicFeature, size_t freeHeapBytes); 00252 00253 /** 00254 * Write a configuration variable query report. 00255 * 00256 * @param data the 7-byte data variable buffer, starting with the variable ID byte 00257 */ 00258 bool reportConfigVar(const uint8_t *data); 00259 00260 /** 00261 * Write a device ID report. 00262 */ 00263 bool reportID(int index); 00264 00265 /** 00266 * Write a build data report 00267 * 00268 * @param date build date plus time, in __DATE__ " " __TIME__ macro format ("Mon dd, yyyy hh:mm:ss") 00269 */ 00270 bool reportBuildInfo(const char *date); 00271 00272 /** 00273 * Write a physical button status report. 00274 * 00275 * @param numButtons the number of buttons 00276 * @param state the button states, 1 bit per button, 8 buttons per byte, 00277 * starting with button 0 in the low-order bit (0x01) of the 00278 * first byte 00279 */ 00280 bool reportButtonStatus(int numButtons, const uint8_t *state); 00281 00282 /** 00283 * Write an IR raw sensor input report. This reports a set of raw 00284 * timing reports for input read from the IR sensor, for learning 00285 * remote purposes. 00286 * 00287 * @param n number of items to report, up to maxRawIR 00288 * @param data items to report; each is a timing reading, in 2us 00289 * increments, with the low bit in each report set to 0 for 00290 * a "space" (IR off) or 1 for a "mark" (IR on) 00291 */ 00292 bool reportRawIR(int n, const uint16_t *data); 00293 00294 /** 00295 * Maximum number of raw IR readings that can be sent in one report 00296 * via reportRawIR(). 00297 */ 00298 static const int maxRawIR = (reportLen - 3)/2; 00299 00300 /** 00301 * Write an IR input report. This reports a decoded command read in 00302 * learning mode to the host. 00303 * 00304 * @param pro protocol ID (see IRProtocolID.h) 00305 * @param flags bit flags: 0x02 = protocol uses dittos 00306 * @param code decoded command code 00307 */ 00308 bool reportIRCode(uint8_t pro, uint8_t flags, uint64_t code); 00309 00310 /** 00311 * Send a joystick report to the host 00312 * 00313 * @returns true if there is no error, false otherwise 00314 */ 00315 bool update(); 00316 00317 /** 00318 * Move the cursor to (x, y) 00319 * 00320 * @param x x-axis position 00321 * @param y y-axis position 00322 * @returns true if there is no error, false otherwise 00323 */ 00324 bool move(int16_t x, int16_t y); 00325 00326 /** 00327 * Set the z position 00328 * 00329 * @param z z-axis osition 00330 */ 00331 bool setZ(int16_t z); 00332 00333 /** 00334 * Press one or several buttons 00335 * 00336 * @param buttons button state, as a bitwise combination of JOY_Bn values 00337 * @returns true if there is no error, false otherwise 00338 */ 00339 bool buttons(uint32_t buttons); 00340 00341 /* USB descriptor overrides */ 00342 virtual const uint8_t *configurationDesc(); 00343 virtual const uint8_t *reportDesc(int idx, uint16_t &len); 00344 00345 /* USB descriptor string overrides */ 00346 virtual const uint8_t *stringImanufacturerDesc(); 00347 virtual const uint8_t *stringIserialDesc(); 00348 virtual const uint8_t *stringIproductDesc(); 00349 00350 /* set/get idle time */ 00351 virtual void setIdleTime(int ifc, int rptid, int t) 00352 { 00353 // Remember the new value if operating on the keyboard. Remember 00354 // separate keyboard and media control idle times, in case the 00355 // host wants separate report rates. 00356 if (ifc == IFC_ID_KB) 00357 { 00358 if (rptid == REPORT_ID_KB) 00359 kbIdleTime = t; 00360 else if (rptid == REPORT_ID_MEDIA) 00361 mediaIdleTime = t; 00362 } 00363 } 00364 virtual uint8_t getIdleTime(int ifc, int rptid) 00365 { 00366 // Return the kb idle time if the kb interface is the one requested. 00367 if (ifc == IFC_ID_KB) 00368 { 00369 if (rptid == REPORT_ID_KB) 00370 return kbIdleTime; 00371 if (rptid == REPORT_ID_MEDIA) 00372 return mediaIdleTime; 00373 } 00374 00375 // we don't use idle times for other interfaces or report types 00376 return 0; 00377 } 00378 00379 /* callback overrides */ 00380 virtual bool USBCallback_setConfiguration(uint8_t configuration); 00381 virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate) 00382 { return interface == 0 || interface == 1; } 00383 00384 virtual bool EP1_OUT_callback(); 00385 virtual bool EP4_OUT_callback(); 00386 00387 private: 00388 00389 // Incoming LedWiz message buffer. Each LedWiz message is exactly 8 bytes. 00390 CircBuf<LedWizMsg, 16> lwbuf; 00391 00392 // enable the joystick interface 00393 bool enableJoystick; 00394 00395 // joystick axis reporting format 00396 bool axisFormat; 00397 00398 // enable the keyboard interface for button inputs 00399 bool useKB; 00400 00401 // keyboard maximum idle time between reports 00402 uint8_t kbIdleTime; 00403 00404 // media maximum idle time between reports 00405 uint8_t mediaIdleTime; 00406 00407 // current X, Y, Z axis values 00408 int16_t _x; 00409 int16_t _y; 00410 int16_t _z; 00411 00412 // joystick button status bits 00413 uint16_t _buttonsLo; 00414 uint16_t _buttonsHi; 00415 00416 // special status flag bits 00417 uint16_t _status; 00418 00419 void _init(); 00420 }; 00421 00422 #endif
Generated on Wed Jul 13 2022 03:30:11 by 1.7.2