Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array

Dependencies:   USBDevice mbed

Fork of Pinscape_Controller by Mike R

Files at this revision

API Documentation at this revision

Comitter:
mjr
Date:
Wed Jul 23 17:53:28 2014 +0000
Parent:
2:c174f9ee414a
Child:
4:02c7cd7b2183
Commit message:
Conversion to interrupt-based sampling of the accelerometer working

Changed in this revision

MMA8451Q/MMA8451Q.cpp Show annotated file Show diff for this revision Revisions of this file
MMA8451Q/MMA8451Q.h Show annotated file Show diff for this revision Revisions of this file
USBJoystick.cpp Show diff for this revision Revisions of this file
USBJoystick.h Show diff for this revision Revisions of this file
USBJoystick/USBJoystick.cpp Show annotated file Show diff for this revision Revisions of this file
USBJoystick/USBJoystick.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/MMA8451Q/MMA8451Q.cpp	Tue Jul 22 04:33:47 2014 +0000
+++ b/MMA8451Q/MMA8451Q.cpp	Wed Jul 23 17:53:28 2014 +0000
@@ -57,12 +57,29 @@
 #define DR_6_HZ           0x30
 #define DR_1_HZ           0x38
 
+#define CTRL_REG3_IPOL_MASK  0x02
+#define CTRL_REG3_PPOD_MASK  0x01
+
+#define INT_EN_DRDY       0x01
+#define INT_CFG_DRDY      0x01
+
 
 MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) 
 {
     // go to standby mode
     standby();
     
+#if 0
+    // reset all registers to power-on reset values
+    uint8_t d0[2] = { REG_CTRL_REG_2, 0x40 };
+    writeRegs(d0,2 );
+    
+    // wait for the reset bit to clear
+    do {
+        readRegs(REG_CTRL_REG_2, d0, 1);
+    } while ((d0[0] & 0x40) != 0);
+#endif
+    
     // read the curent config register
     uint8_t d1[1];
     readRegs(XYZ_DATA_CFG_REG, d1, 1);
@@ -79,10 +96,10 @@
     uint8_t d4[2] = {REG_CTRL_REG_2, (d3[0] & ~MODS_MASK) | MODS1_MASK};
     writeRegs(d4, 2);
     
-    // set 100 Hz mode
+    // set 800 Hz mode
     uint8_t d5[1];
     readRegs(REG_CTRL_REG_1, d5, 1);
-    uint8_t d6[2] = {REG_CTRL_REG_1, (d5[0] & ~DR_MASK) | DR_100_HZ};
+    uint8_t d6[2] = {REG_CTRL_REG_1, (d5[0] & ~DR_MASK) | DR_800_HZ};
     writeRegs(d6, 2);
     
     // enter active mode
@@ -91,6 +108,37 @@
 
 MMA8451Q::~MMA8451Q() { }
 
+void MMA8451Q::setInterruptMode(int pin)
+{
+    // go to standby mode
+    standby();
+
+    // set IRQ push/pull and active high
+    uint8_t d1[1];
+    readRegs(REG_CTRL_REG_3, d1, 1);
+    uint8_t d2[2] = {
+        REG_CTRL_REG_3, 
+        (d1[0] & ~CTRL_REG3_PPOD_MASK) | CTRL_REG3_IPOL_MASK
+    };
+    writeRegs(d2, 2);
+    
+    // set pin 2 or pin 1
+    readRegs(REG_CTRL_REG_5, d1, 1);
+    uint8_t d3[2] = { 
+        REG_CTRL_REG_5, 
+        (d1[0] & ~INT_CFG_DRDY) | (pin == 1 ? INT_CFG_DRDY : 0)
+    };
+    writeRegs(d3, 2);
+    
+    // enable data ready interrupt
+    readRegs(REG_CTRL_REG_4, d1, 1);
+    uint8_t d4[2] = { REG_CTRL_REG_4, d1[0] | INT_EN_DRDY };
+    writeRegs(d4, 2);
+    
+    // enter active mode
+    active();
+}
+
 void MMA8451Q::standby()
 {
     // read the current control register
@@ -138,6 +186,25 @@
     y = int16_t(acc)/(4*4096.0);
 }
 
+void MMA8451Q::getAccXYZ(float &x, float &y, float &z)
+{
+    // read the X, Y, and Z output registers
+    uint8_t res[6];
+    readRegs(REG_OUT_X_MSB, res, 6);
+    
+    // translate the x value
+    uint16_t acc = (res[0] << 8) | (res[1]);
+    x = int16_t(acc)/(4*4096.0);
+    
+    // translate the y value
+    acc = (res[2] << 8) | (res[3]);
+    y = int16_t(acc)/(4*4096.0);
+    
+    // translate the z value
+    acc = (res[4] << 8) | (res[5]);
+    z = int16_t(acc)/(4*4096.0);
+}
+
 float MMA8451Q::getAccY() {
     return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0);
 }
--- a/MMA8451Q/MMA8451Q.h	Tue Jul 22 04:33:47 2014 +0000
+++ b/MMA8451Q/MMA8451Q.h	Wed Jul 23 17:53:28 2014 +0000
@@ -98,6 +98,13 @@
    *  Read an X,Y pair
    */
   void getAccXY(float &x, float &y);
+  
+  /**
+   *  Read X,Y,Z.  This is the most efficient way to fetch
+   *  all of the axes at once, since it fetches all three
+   *  in a single I2C transaction.
+   */
+  void getAccXYZ(float &x, float &y, float &z);
 
   /**
    * Get Z axis acceleration
@@ -112,6 +119,13 @@
    * @param res array where acceleration data will be stored
    */
   void getAccAllAxis(float * res);
+  
+  /**
+   * Set interrupt mode.  'pin' is 1 for INT1_ACCEL (PTA14) and 2 for INT2_ACCEL (PTA15).
+   * The caller is responsible for setting up an interrupt handler on the corresponding
+   * PTAxx pin.
+   */
+  void setInterruptMode(int pin);
 
 private:
   I2C m_i2c;
--- a/USBJoystick.cpp	Tue Jul 22 04:33:47 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/* Copyright (c) 2010-2011 mbed.org, MIT License
-* Modified Mouse code for Joystick - WH 2012
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-* and associated documentation files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all copies or
-* substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
- 
-#include "stdint.h"
-#include "USBJoystick.h"
- 
-bool USBJoystick::update(int16_t x, int16_t y, int16_t z, uint16_t buttons) 
-{
-   _x = x;
-   _y = y;
-   _z = z;
-   _buttons = buttons;     
- 
-   // send the report
-   return update();
-}
- 
-bool USBJoystick::update() {
-   HID_REPORT report;
- 
-   // Fill the report according to the Joystick Descriptor
-   report.data[0] = _buttons & 0xff;
-   report.data[1] = (_buttons >> 8) & 0xff;
-   report.data[2] = _x & 0xff;            
-   report.data[3] = _y & 0xff;            
-   report.data[4] = _z & 0xff;
-   report.length = 5; 
- 
-   return sendNB(&report);
-}
- 
-bool USBJoystick::move(int16_t x, int16_t y) {
-     _x = x;
-     _y = y;
-     return update();
-}
-
-bool USBJoystick::setZ(int16_t z) {
-    _z = z;
-    return update();
-}
- 
-bool USBJoystick::buttons(uint16_t buttons) {
-     _buttons = buttons;
-     return update();
-}
- 
- 
-void USBJoystick::_init() {
- 
-   _x = 0;                       
-   _y = 0;     
-   _z = 0;
-   _buttons = 0x0000;
-}
- 
- 
-uint8_t * USBJoystick::reportDesc() 
-{    
-    static uint8_t reportDescriptor[] = 
-    {         
-         USAGE_PAGE(1), 0x01,            // Generic desktop
-         USAGE(1), 0x04,                 // Joystick
-
-         COLLECTION(1), 0x01,            // Application
-      //     COLLECTION(1), 0x00,          // Physical
-           
-             USAGE_PAGE(1), 0x09,        // Buttons
-             USAGE_MINIMUM(1), 0x01,     // { buttons }
-             USAGE_MAXIMUM(1), 0x10,     // {  1-16   }
-             LOGICAL_MINIMUM(1), 0x00,   // 1-bit buttons - 0...
-             LOGICAL_MAXIMUM(1), 0x01,   // ...to 1
-             REPORT_SIZE(1), 0x01,       // 1 bit per report
-             REPORT_COUNT(1), 0x10,      // 16 reports
-             UNIT_EXPONENT(1), 0x00,     // Unit_Exponent (0)
-             UNIT(1), 0x00,              // Unit (None)                                           
-             INPUT(1), 0x02,             // Data, Variable, Absolute
-           
-             USAGE_PAGE(1), 0x01,        // Generic desktop
-             USAGE(1), 0x30,             // X
-             USAGE(1), 0x31,             // Y
-             USAGE(1), 0x32,             // Z
-             LOGICAL_MINIMUM(1), 0x81,   // each value ranges -127...
-             LOGICAL_MAXIMUM(1), 0x7f,   // ...to 127
-             REPORT_SIZE(1), 0x08,       // 8 bits per report
-             REPORT_COUNT(1), 0x03,      // 2 reports
-             INPUT(1), 0x02,             // Data, Variable, Absolute
-
-             REPORT_COUNT(1), 0x08,      // input report count (LEDWiz messages)
-             0x09, 0x01,                 // usage
-             0x91, 0x01,                 // Output (array)
-
-     //      END_COLLECTION(0),
-         END_COLLECTION(0)
-      };
- 
-      reportLength = sizeof(reportDescriptor);
-      return reportDescriptor;
-}
- 
- uint8_t * USBJoystick::stringImanufacturerDesc() {
-    static uint8_t stringImanufacturerDescriptor[] = {
-        0x10,                                            /*bLength*/
-        STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
-        'm',0,'j',0,'r',0,'c',0,'o',0,'r',0,'p',0        /*bString iManufacturer - mjrcorp*/
-    };
-    return stringImanufacturerDescriptor;
-}
-
-uint8_t * USBJoystick::stringIserialDesc() {
-    static uint8_t stringIserialDescriptor[] = {
-        0x16,                                                           /*bLength*/
-        STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
-        '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,    /*bString iSerial - 0123456789*/
-    };
-    return stringIserialDescriptor;
-}
-
-uint8_t * USBJoystick::stringIproductDesc() {
-    static uint8_t stringIproductDescriptor[] = {
-        0x1E,                                                       /*bLength*/
-        STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
-        'P',0,'i',0,'n',0,'M',0,'a',0,'s',0,'t',0,'e',0,'r',0,
-        ' ',0,'2',0,'0',0,'0',0,'0',0                               /*String iProduct - PinMaster 2000*/
-    };
-    return stringIproductDescriptor;
-}
--- a/USBJoystick.h	Tue Jul 22 04:33:47 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/* USBJoystick.h */
-/* USB device example: Joystick*/
-/* Copyright (c) 2011 ARM Limited. All rights reserved. */
-/* Modified Mouse code for Joystick - WH 2012 */
- 
-#ifndef USBJOYSTICK_H
-#define USBJOYSTICK_H
- 
-#include "USBHID.h"
- 
-#define REPORT_ID_JOYSTICK  4
- 
-/* Common usage */
-enum JOY_BUTTON {
-     JOY_B0 = 0x0001,
-     JOY_B1 = 0x0002,
-     JOY_B2 = 0x0004,
-     JOY_B3 = 0x0008,
-     JOY_B4 = 0x0010,
-     JOY_B5 = 0x0020,
-     JOY_B6 = 0x0040,
-     JOY_B7 = 0x0080,
-     JOY_B8 = 0x0100,
-     JOY_B9 = 0x0200,
-     JOY_B10 = 0x0400,
-     JOY_B11 = 0x0800,
-     JOY_B12 = 0x1000,
-     JOY_B13 = 0x2000,
-     JOY_B14 = 0x4000,
-     JOY_B15 = 0x8000
-};
- 
-/* X, Y and T limits */
-/* These values do not directly map to screen pixels */
-/* Zero may be interpreted as meaning 'no movement' */
-#define JX_MIN_ABS    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
-#define JY_MIN_ABS    (-127)     /*!< The maximum value that we can move up on the y-axis */
-#define JZ_MIN_ABS    (-127)     /*!< The minimum value for the Z axis */
-#define JX_MAX_ABS    (127)      /*!< The maximum value that we can move to the right on the x-axis */
-#define JY_MAX_ABS    (127)      /*!< The maximum value that we can move down on the y-axis */
-#define JZ_MAX_ABS    (127)      /*!< The maximum value for the Z axis */
- 
-/**
- *
- * USBJoystick example
- * @code
- * #include "mbed.h"
- * #include "USBJoystick.h"
- *
- * USBJoystick joystick;
- *
- * int main(void)
- * {
- *   while (1)
- *   {
- *      joystick.move(20, 0);
- *      wait(0.5);
- *   }
- * }
- *
- * @endcode
- *
- *
- * @code
- * #include "mbed.h"
- * #include "USBJoystick.h"
- * #include <math.h>
- *
- * USBJoystick joystick;
- *
- * int main(void)
- * {   
- *   while (1) {
- *       // Basic Joystick
- *       joystick.update(tx, y, z, buttonBits);
- *       wait(0.001);
- *   }
- * }
- * @endcode
- */
- 
- 
-class USBJoystick: public USBHID {
-   public:
- 
-        /**
-         *   Constructor
-         *
-         * @param vendor_id Your vendor_id (default: 0x1234)
-         * @param product_id Your product_id (default: 0x0002)
-         * @param product_release Your product_release (default: 0x0001)
-         */
-         USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0100, uint16_t product_release = 0x0001): 
-             USBHID(8, 8, vendor_id, product_id, product_release, false)
-             { 
-                 _init();
-                 connect();
-             };
-         
-         /**
-         * Write a state of the mouse
-         *
-         * @param x x-axis position
-         * @param y y-axis position
-         * @param z z-axis position
-         * @param buttons buttons state, as a bit mask (combination with '|' of JOY_Bn values)
-         * @returns true if there is no error, false otherwise
-         */
-         bool update(int16_t x, int16_t y, int16_t z, uint16_t buttons);
- 
-         /**
-         * Write a state of the mouse
-         *
-         * @returns true if there is no error, false otherwise
-         */
-         bool update();
- 
-         /**
-         * Move the cursor to (x, y)
-         *
-         * @param x x-axis position
-         * @param y y-axis position
-         * @returns true if there is no error, false otherwise
-         */
-         bool move(int16_t x, int16_t y);
-         
-         /**
-         * Set the z position
-         *
-         * @param z z-axis osition
-         */
-         bool setZ(int16_t z);
-         
-         /**
-         * Press one or several buttons
-         *
-         * @param buttons button state, as a bitwise combination of JOY_Bn values
-         * @returns true if there is no error, false otherwise
-         */
-         bool buttons(uint16_t buttons);
-         
-         /*
-         * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
-         *
-         * @returns pointer to the report descriptor
-         */
-         virtual uint8_t * reportDesc();
- 
-         /* USB descriptor string overrides */
-         virtual uint8_t *stringImanufacturerDesc();
-         virtual uint8_t *stringIserialDesc();
-         virtual uint8_t *stringIproductDesc();
- 
-     private:
-         int8_t _x;                       
-         int8_t _y;     
-         int8_t _z;
-         uint16_t _buttons;
-         
-         void _init();                 
-};
- 
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBJoystick/USBJoystick.cpp	Wed Jul 23 17:53:28 2014 +0000
@@ -0,0 +1,150 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+* Modified Mouse code for Joystick - WH 2012
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+ 
+#include "stdint.h"
+#include "USBJoystick.h"
+ 
+bool USBJoystick::update(int16_t x, int16_t y, int16_t z, int16_t rx, int16_t ry, uint16_t buttons) 
+{
+   _x = x;
+   _y = y;
+   _z = z;
+   _rx = rx;
+   _ry = ry;
+   _buttons = buttons;     
+ 
+   // send the report
+   return update();
+}
+ 
+bool USBJoystick::update() {
+   HID_REPORT report;
+ 
+   // Fill the report according to the Joystick Descriptor
+   report.data[0] = _buttons & 0xff;
+   report.data[1] = (_buttons >> 8) & 0xff;
+   report.data[2] = _x & 0xff;            
+   report.data[3] = _y & 0xff;            
+   report.data[4] = _z & 0xff;
+   report.data[5] = _rx & 0xff;
+   report.data[6] = _ry & 0xff;
+   report.length = 7; 
+ 
+   return sendNB(&report);
+}
+ 
+bool USBJoystick::move(int16_t x, int16_t y) {
+     _x = x;
+     _y = y;
+     return update();
+}
+
+bool USBJoystick::setZ(int16_t z) {
+    _z = z;
+    return update();
+}
+ 
+bool USBJoystick::buttons(uint16_t buttons) {
+     _buttons = buttons;
+     return update();
+}
+ 
+ 
+void USBJoystick::_init() {
+ 
+   _x = 0;                       
+   _y = 0;     
+   _z = 0;
+   _buttons = 0x0000;
+}
+ 
+ 
+uint8_t * USBJoystick::reportDesc() 
+{    
+    static uint8_t reportDescriptor[] = 
+    {         
+         USAGE_PAGE(1), 0x01,            // Generic desktop
+         USAGE(1), 0x04,                 // Joystick
+
+         COLLECTION(1), 0x01,            // Application
+      //     COLLECTION(1), 0x00,          // Physical
+           
+             USAGE_PAGE(1), 0x09,        // Buttons
+             USAGE_MINIMUM(1), 0x01,     // { buttons }
+             USAGE_MAXIMUM(1), 0x10,     // {  1-16   }
+             LOGICAL_MINIMUM(1), 0x00,   // 1-bit buttons - 0...
+             LOGICAL_MAXIMUM(1), 0x01,   // ...to 1
+             REPORT_SIZE(1), 0x01,       // 1 bit per report
+             REPORT_COUNT(1), 0x10,      // 16 reports
+             UNIT_EXPONENT(1), 0x00,     // Unit_Exponent (0)
+             UNIT(1), 0x00,              // Unit (None)                                           
+             INPUT(1), 0x02,             // Data, Variable, Absolute
+           
+             USAGE_PAGE(1), 0x01,        // Generic desktop
+             USAGE(1), 0x30,             // X
+             USAGE(1), 0x31,             // Y
+             USAGE(1), 0x32,             // Z
+             USAGE(1), 0x33,             // Rx
+             USAGE(1), 0x34,             // Ry
+             LOGICAL_MINIMUM(1), 0x81,   // each value ranges -127...
+             LOGICAL_MAXIMUM(1), 0x7f,   // ...to 127
+             REPORT_SIZE(1), 0x08,       // 8 bits per report
+             REPORT_COUNT(1), 0x05,      // 5 reports (X, Y, Z, Rx, Ry)
+             INPUT(1), 0x02,             // Data, Variable, Absolute
+
+             REPORT_COUNT(1), 0x08,      // input report count (LEDWiz messages)
+             0x09, 0x01,                 // usage
+             0x91, 0x01,                 // Output (array)
+
+     //      END_COLLECTION(0),
+         END_COLLECTION(0)
+      };
+ 
+      reportLength = sizeof(reportDescriptor);
+      return reportDescriptor;
+}
+ 
+ uint8_t * USBJoystick::stringImanufacturerDesc() {
+    static uint8_t stringImanufacturerDescriptor[] = {
+        0x10,                                            /*bLength*/
+        STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
+        'm',0,'j',0,'r',0,'c',0,'o',0,'r',0,'p',0        /*bString iManufacturer - mjrcorp*/
+    };
+    return stringImanufacturerDescriptor;
+}
+
+uint8_t * USBJoystick::stringIserialDesc() {
+    static uint8_t stringIserialDescriptor[] = {
+        0x16,                                                           /*bLength*/
+        STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
+        '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,    /*bString iSerial - 0123456789*/
+    };
+    return stringIserialDescriptor;
+}
+
+uint8_t * USBJoystick::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x2E,                                                       /*bLength*/
+        STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
+        'P',0,'i',0,'n',0,'s',0,'c',0,'a',0,'p',0,'e',0,
+        ' ',0,'C',0,'o',0,'n',0,'t',0,'r',0,'o',0,'l',0,
+        'l',0,'e',0,'r',0                                           /*String iProduct */
+    };
+    return stringIproductDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBJoystick/USBJoystick.h	Wed Jul 23 17:53:28 2014 +0000
@@ -0,0 +1,165 @@
+/* USBJoystick.h */
+/* USB device example: Joystick*/
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+/* Modified Mouse code for Joystick - WH 2012 */
+ 
+#ifndef USBJOYSTICK_H
+#define USBJOYSTICK_H
+ 
+#include "USBHID.h"
+ 
+#define REPORT_ID_JOYSTICK  4
+ 
+/* Common usage */
+enum JOY_BUTTON {
+     JOY_B0 = 0x0001,
+     JOY_B1 = 0x0002,
+     JOY_B2 = 0x0004,
+     JOY_B3 = 0x0008,
+     JOY_B4 = 0x0010,
+     JOY_B5 = 0x0020,
+     JOY_B6 = 0x0040,
+     JOY_B7 = 0x0080,
+     JOY_B8 = 0x0100,
+     JOY_B9 = 0x0200,
+     JOY_B10 = 0x0400,
+     JOY_B11 = 0x0800,
+     JOY_B12 = 0x1000,
+     JOY_B13 = 0x2000,
+     JOY_B14 = 0x4000,
+     JOY_B15 = 0x8000
+};
+ 
+/* X, Y and T limits */
+/* These values do not directly map to screen pixels */
+/* Zero may be interpreted as meaning 'no movement' */
+#define JX_MIN_ABS    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
+#define JY_MIN_ABS    (-127)     /*!< The maximum value that we can move up on the y-axis */
+#define JZ_MIN_ABS    (-127)     /*!< The minimum value for the Z axis */
+#define JX_MAX_ABS    (127)      /*!< The maximum value that we can move to the right on the x-axis */
+#define JY_MAX_ABS    (127)      /*!< The maximum value that we can move down on the y-axis */
+#define JZ_MAX_ABS    (127)      /*!< The maximum value for the Z axis */
+ 
+/**
+ *
+ * USBJoystick example
+ * @code
+ * #include "mbed.h"
+ * #include "USBJoystick.h"
+ *
+ * USBJoystick joystick;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *      joystick.move(20, 0);
+ *      wait(0.5);
+ *   }
+ * }
+ *
+ * @endcode
+ *
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "USBJoystick.h"
+ * #include <math.h>
+ *
+ * USBJoystick joystick;
+ *
+ * int main(void)
+ * {   
+ *   while (1) {
+ *       // Basic Joystick
+ *       joystick.update(tx, y, z, buttonBits);
+ *       wait(0.001);
+ *   }
+ * }
+ * @endcode
+ */
+ 
+ 
+class USBJoystick: public USBHID {
+   public:
+ 
+        /**
+         *   Constructor
+         *
+         * @param vendor_id Your vendor_id (default: 0x1234)
+         * @param product_id Your product_id (default: 0x0002)
+         * @param product_release Your product_release (default: 0x0001)
+         */
+         USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0100, uint16_t product_release = 0x0001): 
+             USBHID(8, 8, vendor_id, product_id, product_release, false)
+             { 
+                 _init();
+                 connect();
+             };
+         
+         /**
+         * Write a state of the mouse
+         *
+         * @param x x-axis position
+         * @param y y-axis position
+         * @param z z-axis position
+         * @param buttons buttons state, as a bit mask (combination with '|' of JOY_Bn values)
+         * @returns true if there is no error, false otherwise
+         */
+         bool update(int16_t x, int16_t y, int16_t z, int16_t rx, int16_t ry, uint16_t buttons);
+ 
+         /**
+         * Write a state of the mouse
+         *
+         * @returns true if there is no error, false otherwise
+         */
+         bool update();
+ 
+         /**
+         * Move the cursor to (x, y)
+         *
+         * @param x x-axis position
+         * @param y y-axis position
+         * @returns true if there is no error, false otherwise
+         */
+         bool move(int16_t x, int16_t y);
+         
+         /**
+         * Set the z position
+         *
+         * @param z z-axis osition
+         */
+         bool setZ(int16_t z);
+         
+         /**
+         * Press one or several buttons
+         *
+         * @param buttons button state, as a bitwise combination of JOY_Bn values
+         * @returns true if there is no error, false otherwise
+         */
+         bool buttons(uint16_t buttons);
+         
+         /*
+         * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+         *
+         * @returns pointer to the report descriptor
+         */
+         virtual uint8_t * reportDesc();
+ 
+         /* USB descriptor string overrides */
+         virtual uint8_t *stringImanufacturerDesc();
+         virtual uint8_t *stringIserialDesc();
+         virtual uint8_t *stringIproductDesc();
+ 
+     private:
+         int8_t _x;                       
+         int8_t _y;     
+         int8_t _z;
+         int8_t _rx;
+         int8_t _ry;
+         uint16_t _buttons;
+         
+         void _init();                 
+};
+ 
+#endif
\ No newline at end of file
--- a/main.cpp	Tue Jul 22 04:33:47 2014 +0000
+++ b/main.cpp	Wed Jul 23 17:53:28 2014 +0000
@@ -12,20 +12,16 @@
     MyUSBJoystick(uint16_t vendor_id, uint16_t product_id, uint16_t product_release) 
         : USBJoystick(vendor_id, product_id, product_release)
     {
-        connected_ = false;
         suspended_ = false;
     }
     
-    int isConnected() const { return connected_; }
+    int isConnected() { return configured(); }
     int isSuspended() const { return suspended_; }
     
 protected:
-    virtual void connectStateChanged(unsigned int connected) 
-        { connected_ = connected; }
     virtual void suspendStateChanged(unsigned int suspended)
         { suspended_ = suspended; }
 
-    int connected_;
     int suspended_; 
 };
 
@@ -117,6 +113,104 @@
     } d;
 };
 
+// Accelerometer handler
+const int MMA8451_I2C_ADDRESS = (0x1d<<1);
+class Accel
+{
+public:
+    Accel(PinName sda, PinName scl, int i2cAddr, PinName irqPin)
+        : mma_(sda, scl, i2cAddr), intIn_(irqPin)
+    {
+        // set the initial ball velocity to zero
+        vx_ = vy_ = 0;
+        
+        // set the initial raw acceleration reading to zero
+        xRaw_ = yRaw_ = 0;
+
+        // enable the interrupt
+        mma_.setInterruptMode(irqPin == PTA14 ? 1 : 2);
+        
+        // set up the interrupt handler
+        intIn_.rise(this, &Accel::isr);
+        
+        // read the current registers to clear the data ready flag
+        float z;
+        mma_.getAccXYZ(xRaw_, yRaw_, z);
+
+        // start our timers
+        tGet_.start();
+        tInt_.start();
+    }
+    
+    void get(float &x, float &y, float &rx, float &ry) 
+    {
+         // disable interrupts while manipulating the shared data
+         __disable_irq();
+         
+         // read the shared data and store locally for calculations
+         float vx = vx_, vy = vy_, xRaw = xRaw_, yRaw = yRaw_;
+
+         // reset the velocity
+         vx_ = vy_ = 0;
+         
+         // get the time since the last get() sample
+         float dt = tGet_.read_us()/1.0e6;
+         tGet_.reset();
+         
+         // done manipulating the shared data
+         __enable_irq();
+         
+         // calculate the acceleration since the last get(): a = dv/dt
+         x = vx/dt;
+         y = vy/dt;         
+         
+         // return the raw accelerometer data in rx,ry
+         rx = xRaw;
+         ry = yRaw;
+     }    
+    
+private:
+    // interrupt handler
+    void isr()
+    {
+        // Read the axes.  Note that we have to read all three axes
+        // (even though we only really use x and y) in order to clear
+        // the "data ready" status bit in the accelerometer.  The
+        // interrupt only occurs when the "ready" bit transitions from
+        // off to on, so we have to make sure it's off.
+        float z;
+        mma_.getAccXYZ(xRaw_, yRaw_, z);
+        
+        // calculate the time since the last interrupt
+        float dt = tInt_.read_us()/1.0e6;
+        tInt_.reset();
+        
+        // Accelerate the model ball: v = a*dt.  Assume that the raw
+        // data from the accelerometer reflects the average physical
+        // acceleration over the interval since the last sample.
+        vx_ += xRaw_ * dt;
+        vy_ += yRaw_ * dt;
+    }
+    
+    // current modeled ball velocity
+    float vx_, vy_;
+    
+    // last raw axis readings
+    float xRaw_, yRaw_;
+    
+    // underlying accelerometer object
+    MMA8451Q mma_;
+    
+    // interrupt router
+    InterruptIn intIn_;
+    
+    // timer for measuring time between get() samples
+    Timer tGet_;
+    
+    // timer for measuring time between interrupts
+    Timer tInt_;
+};
+
 int main(void)
 {
     // turn off our on-board indicator LED
@@ -188,13 +282,12 @@
     // Create the joystick USB client.  Light the on-board indicator LED
     // red while connecting, and change to green after we connect.
     led1 = 0;
-    MyUSBJoystick js(0xFAFA, 0x00F7, 0x0001);
+    MyUSBJoystick js(0xFAFA, 0x00F7, 0x0003);
     led1 = 1;
     led2 = 0;
 
     // create the accelerometer object
-    const int MMA8451_I2C_ADDRESS = (0x1d<<1);
-    MMA8451Q accel(PTE25, PTE24, MMA8451_I2C_ADDRESS);
+    Accel accel(PTE25, PTE24, MMA8451_I2C_ADDRESS, PTA15);
     
     // create the CCD array object
     TSL1410R ccd(PTE20, PTE21, PTB0);
@@ -362,13 +455,16 @@
             newCalBtnLit = false;
             break;
         }
+        
+        // light or flash the external calibration button LED, and 
+        // do the same with the on-board blue LED
         if (calBtnLit != newCalBtnLit)
         {
             calBtnLit = newCalBtnLit;
             if (calBtnLit) {
                 calBtnLed = 1;
-                led1 = 0;
-                led2 = 0;
+                led1 = 1;
+                led2 = 1;
                 led3 = 1;
             }
             else {
@@ -447,8 +543,8 @@
         }
         
         // read the accelerometer
-        float xa, ya;
-        accel.getAccXY(xa, ya);
+        float xa, ya, rxa, rya;
+        accel.get(xa, ya, rxa, rya);
         
         // check for auto-centering every so often
         if (acTimer.read_ms() - t0ac > 1000) 
@@ -521,17 +617,13 @@
             }
         }
 
-        // Send the status report.  Note one of the axes needs to be
-        // reversed, because the native accelerometer reports seem to
-        // assume that the card is component side down; we have to
-        // reverse one or the other axis to account for the reversed
-        // coordinate system.  It doesn't really matter which one,
-        // but reversing Y seems to give intuitive results when viewed
-        // in the Windows joystick control panel.  Note that the 
-        // coordinate system we report is ultimately arbitrary, since
-        // Visual Pinball has preference settings that let us set up
-        // axis reversals and a global rotation for the joystick.
-        js.update(x, -y, z, 0);
+        // Send the status report.  It doesn't really matter what
+        // coordinate system we use, since Visual Pinball has config
+        // options for rotations and axis reversals, but reversing y
+        // at the device level seems to produce the most intuitive 
+        // results for the Windows joystick control panel view, which
+        // is an easy way to check that the device is working.
+        js.update(x, -y, z, int(rxa*127), int(rya*127), 0);
         
         // show a heartbeat flash in blue every so often if not in 
         // calibration mode
@@ -566,7 +658,7 @@
                 hb = !hb;
                 led1 = (hb ? 0 : 1);
                 led2 = 0;
-                led3 = 0;
+                led3 = 1;
             }
             
             // reset the heartbeat timer