
Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array
Fork of Pinscape_Controller by
Revision 3:3514575d4f86, committed 2014-07-23
- 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
--- 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