An input/output controller for virtual pinball machines, with plunger position tracking, accelerometer-based nudge sensing, button input encoding, and feedback device control.

Dependencies:   USBDevice mbed FastAnalogIn FastIO FastPWM SimpleDMA

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBJoystick.cpp Source File

USBJoystick.cpp

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 * Modified Mouse code for Joystick - WH 2012
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00005 * and associated documentation files (the "Software"), to deal in the Software without
00006 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00007 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00008 * Software is furnished to do so, subject to the following conditions:
00009 *
00010 * The above copyright notice and this permission notice shall be included in all copies or
00011 * substantial portions of the Software.
00012 *
00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00018 */
00019  
00020 #include "stdint.h"
00021 #include "USBJoystick.h"
00022 
00023 #include "config.h"  // Pinscape configuration
00024 
00025 // Length of our joystick reports.  Important: This must be kept in sync 
00026 // with the actual joystick report format sent in update().
00027 const int reportLen = 14;
00028 
00029 #ifdef ENABLE_JOYSTICK
00030 bool USBJoystick::update(int16_t x, int16_t y, int16_t z, uint32_t buttons, uint16_t status) 
00031 {
00032    _x = x;
00033    _y = y;
00034    _z = z;
00035    _buttonsLo = (uint16_t)(buttons & 0xffff);
00036    _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff);
00037    _status = status;
00038  
00039    // send the report
00040    return update();
00041 }
00042  
00043 bool USBJoystick::update() 
00044 {
00045    HID_REPORT report;
00046 
00047    // Fill the report according to the Joystick Descriptor
00048 #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff)
00049    put(0, _status);
00050    put(2, 0);  // second byte of status isn't used in normal reports
00051    put(4, _buttonsLo);
00052    put(6, _buttonsHi);
00053    put(8, _x);
00054    put(10, _y);
00055    put(12, _z);
00056    
00057    // important: keep reportLen in sync with the actual byte length of
00058    // the reports we build here
00059    report.length = reportLen;
00060  
00061    // send the report
00062    return sendTO(&report, 100);
00063 }
00064 
00065 bool USBJoystick::updateExposure(int &idx, int npix, const uint16_t *pix)
00066 {
00067     HID_REPORT report;
00068     
00069     // Set the special status bits to indicate it's an exposure report.
00070     // The high 5 bits of the status word are set to 10000, and the
00071     // low 11 bits are the current pixel index.
00072     uint16_t s = idx | 0x8000;
00073     put(0, s);
00074     
00075     // start at the second byte
00076     int ofs = 2;
00077     
00078     // in the first report, add the total pixel count as the next two bytes
00079     if (idx == 0)
00080     {
00081         put(ofs, npix);
00082         ofs += 2;
00083     }
00084         
00085     // now fill out the remaining words with exposure values
00086     report.length = reportLen;
00087     for ( ; ofs + 1 < report.length ; ofs += 2)
00088     {
00089         uint16_t p = (idx < npix ? pix[idx++] : 0);
00090         put(ofs, p);
00091     }
00092     
00093     // send the report
00094     return send(&report);
00095 }
00096 
00097 bool USBJoystick::reportConfig(int numOutputs, int unitNo)
00098 {
00099     HID_REPORT report;
00100 
00101     // initially fill the report with zeros
00102     memset(report.data, 0, sizeof(report.data));
00103     
00104     // Set the special status bits to indicate that it's a config report.
00105     uint16_t s = 0x8800;
00106     put(0, s);
00107     
00108     // write the number of configured outputs
00109     put(2, numOutputs);
00110     
00111     // write the unit number
00112     put(4, unitNo);
00113     
00114     // send the report
00115     report.length = reportLen;
00116     return send(&report);
00117 }
00118 
00119 bool USBJoystick::move(int16_t x, int16_t y) 
00120 {
00121      _x = x;
00122      _y = y;
00123      return update();
00124 }
00125 
00126 bool USBJoystick::setZ(int16_t z) 
00127 {
00128     _z = z;
00129     return update();
00130 }
00131  
00132 bool USBJoystick::buttons(uint32_t buttons) 
00133 {
00134      _buttonsLo = (uint16_t)(buttons & 0xffff);
00135      _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff);
00136      return update();
00137 }
00138 
00139 #else /* ENABLE_JOYSTICK */
00140 
00141 bool USBJoystick::updateStatus(uint32_t status)
00142 {
00143    HID_REPORT report;
00144 
00145    // Fill the report according to the Joystick Descriptor
00146 #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff)
00147    memset(report.data, 0, reportLen);
00148    put(0, status);
00149    report.length = reportLen;
00150  
00151    // send the report
00152    return sendTO(&report, 100);
00153 }
00154 
00155 #endif /* ENABLE_JOYSTICK */
00156  
00157  
00158 void USBJoystick::_init() {
00159  
00160    _x = 0;                       
00161    _y = 0;     
00162    _z = 0;
00163    _buttonsLo = 0x0000;
00164    _buttonsHi = 0x0000;
00165    _status = 0;
00166 }
00167  
00168  
00169 uint8_t * USBJoystick::reportDesc() 
00170 {    
00171 #ifdef ENABLE_JOYSTICK
00172     // Joystick reports are enabled.  Use the full joystick report
00173     // format.
00174     static uint8_t reportDescriptor[] = 
00175     {         
00176          USAGE_PAGE(1), 0x01,            // Generic desktop
00177          USAGE(1), 0x04,                 // Joystick
00178          COLLECTION(1), 0x01,            // Application
00179          
00180              // input report (device to host)
00181 
00182              USAGE_PAGE(1), 0x06,        // generic device controls - for config status
00183              USAGE(1), 0x00,             // undefined device control
00184              LOGICAL_MINIMUM(1), 0x00,   // 8-bit values
00185              LOGICAL_MAXIMUM(1), 0xFF,
00186              REPORT_SIZE(1), 0x08,       // 8 bits per report
00187              REPORT_COUNT(1), 0x04,      // 4 reports (4 bytes)
00188              INPUT(1), 0x02,             // Data, Variable, Absolute
00189 
00190              USAGE_PAGE(1), 0x09,        // Buttons
00191              USAGE_MINIMUM(1), 0x01,     // { buttons }
00192              USAGE_MAXIMUM(1), 0x20,     // {  1-32   }
00193              LOGICAL_MINIMUM(1), 0x00,   // 1-bit buttons - 0...
00194              LOGICAL_MAXIMUM(1), 0x01,   // ...to 1
00195              REPORT_SIZE(1), 0x01,       // 1 bit per report
00196              REPORT_COUNT(1), 0x20,      // 32 reports
00197              UNIT_EXPONENT(1), 0x00,     // Unit_Exponent (0)
00198              UNIT(1), 0x00,              // Unit (None)                                           
00199              INPUT(1), 0x02,             // Data, Variable, Absolute
00200            
00201              USAGE_PAGE(1), 0x01,        // Generic desktop
00202              USAGE(1), 0x30,             // X axis
00203              USAGE(1), 0x31,             // Y axis
00204              USAGE(1), 0x32,             // Z axis
00205              LOGICAL_MINIMUM(2), 0x00,0xF0,   // each value ranges -4096
00206              LOGICAL_MAXIMUM(2), 0x00,0x10,   // ...to +4096
00207              REPORT_SIZE(1), 0x10,       // 16 bits per report
00208              REPORT_COUNT(1), 0x03,      // 3 reports (X, Y, Z)
00209              INPUT(1), 0x02,             // Data, Variable, Absolute
00210              
00211              // output report (host to device)
00212              REPORT_SIZE(1), 0x08,       // 8 bits per report
00213              REPORT_COUNT(1), 0x08,      // output report count - 8-byte LedWiz format
00214              0x09, 0x01,                 // usage
00215              0x91, 0x01,                 // Output (array)
00216 
00217          END_COLLECTION(0)
00218 
00219       };
00220 #else /* defined(ENABLE_JOYSTICK) */
00221 
00222     // Joystick reports are disabled.  We still want to appear
00223     // as a USB device for the LedWiz output emulation, but we
00224     // don't want to appear as a joystick.
00225      
00226     static uint8_t reportDescriptor[] = 
00227     {         
00228          USAGE_PAGE(1), 0x01,            // Generic desktop
00229          USAGE(1), 0x00,                 // Undefined
00230 
00231          COLLECTION(1), 0x01,            // Application
00232          
00233              // input report (device to host)
00234              USAGE_PAGE(1), 0x06,        // generic device controls - for config status
00235              USAGE(1), 0x00,             // undefined device control
00236              LOGICAL_MINIMUM(1), 0x00,   // 8-bit values
00237              LOGICAL_MAXIMUM(1), 0xFF,
00238              REPORT_SIZE(1), 0x08,       // 8 bits per report
00239              REPORT_COUNT(1), reportLen, // standard report length (same as if we were in joystick mode)
00240              INPUT(1), 0x02,             // Data, Variable, Absolute
00241 
00242              // output report (host to device)
00243              REPORT_SIZE(1), 0x08,       // 8 bits per report
00244              REPORT_COUNT(1), 0x08,      // output report count (LEDWiz messages)
00245              0x09, 0x01,                 // usage
00246              0x91, 0x01,                 // Output (array)
00247 
00248          END_COLLECTION(0)
00249       };
00250  
00251 #endif /* defined(ENABLE_JOYSTICK) */
00252 
00253       reportLength = sizeof(reportDescriptor);
00254       return reportDescriptor;
00255 }
00256  
00257  uint8_t * USBJoystick::stringImanufacturerDesc() {
00258     static uint8_t stringImanufacturerDescriptor[] = {
00259         0x10,                                            /*bLength*/
00260         STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
00261         'm',0,'j',0,'r',0,'c',0,'o',0,'r',0,'p',0        /*bString iManufacturer - mjrcorp*/
00262     };
00263     return stringImanufacturerDescriptor;
00264 }
00265 
00266 uint8_t * USBJoystick::stringIserialDesc() {
00267     static uint8_t stringIserialDescriptor[] = {
00268         0x16,                                                           /*bLength*/
00269         STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
00270         '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,    /*bString iSerial - 0123456789*/
00271     };
00272     return stringIserialDescriptor;
00273 }
00274 
00275 uint8_t * USBJoystick::stringIproductDesc() {
00276     static uint8_t stringIproductDescriptor[] = {
00277         0x28,                                                       /*bLength*/
00278         STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
00279         'P',0,'i',0,'n',0,'s',0,'c',0,'a',0,'p',0,'e',0,
00280         ' ',0,'C',0,'o',0,'n',0,'t',0,'r',0,'o',0,'l',0,
00281         'l',0,'e',0,'r',0                                           /*String iProduct */
00282     };
00283     return stringIproductDescriptor;
00284 }