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 Mike R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBJoystick.h Source File

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