Library to handle SpaceBall, SpaceMouse and SpaceOrb on serial port. Gets access to 3D rotation and translation vector as well as button status. (USB is not supported)

Dependents:   SpaceBall_Example

Library to handle SpaceBall, SpaceMouse and SpaceOrb on serial port. Gets access to 3D rotation and translation vector as well as button status. (USB is not supported)

All handling and decoding is done in the RX interrupt and the vector values can be read out asynchronously with different coordinate mappings.

Example:

#include "mbed.h"
#include "SpaceBall.h"
 
PwmOut led[] = {(LED1), (LED2), (LED3), (LED4) };
SpaceBall SBall(p9, p10);   // tx, rx, bSOrb
 
int main() {
    SBall.Init();
    
    while(1) {
 
        led[0] = abs( SBall[TX] ) + abs( SBall[TY] ) + abs( SBall[TZ] );
        led[1] = abs( SBall[RX] );
        led[2] = abs( SBall[RY] );
        led[3] = abs( SBall[RZ] );
        
        wait_us(500);
    }
}

In this exaple the 4 LEDs are powered dependent on force at the Spaceball. LED1 shows the sum of all translation forces. LED2 to LED4 shows the rotation forces.

For more information about SpaceBall devices see manufactorers page http://www.3dconnexion.com

For connecting a SpaceBall (or SpaceMouse or SpaceOrb) to mbed see page wiki/Serial-Connection

Example: SpaceBall 4000

/media/uploads/jocis/spaceball1.jpg

Committer:
jocis
Date:
Wed Sep 03 07:36:43 2014 +0000
Revision:
4:f953792e45cb
Parent:
3:7bacae57a30b
Added documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jocis 3:7bacae57a30b 1 /* mbed SpaceBall, SpaceMouse and SpaceOrb Library
jocis 3:7bacae57a30b 2 * Copyright (c) 2012 Jochen Krapf
jocis 3:7bacae57a30b 3 *
jocis 3:7bacae57a30b 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
jocis 3:7bacae57a30b 5 * of this software and associated documentation files (the "Software"), to deal
jocis 3:7bacae57a30b 6 * in the Software without restriction, including without limitation the rights
jocis 3:7bacae57a30b 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jocis 3:7bacae57a30b 8 * copies of the Software, and to permit persons to whom the Software is
jocis 3:7bacae57a30b 9 * furnished to do so, subject to the following conditions:
jocis 3:7bacae57a30b 10 *
jocis 3:7bacae57a30b 11 * The above copyright notice and this permission notice shall be included in
jocis 3:7bacae57a30b 12 * all copies or substantial portions of the Software.
jocis 3:7bacae57a30b 13 *
jocis 3:7bacae57a30b 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jocis 3:7bacae57a30b 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jocis 3:7bacae57a30b 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jocis 3:7bacae57a30b 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jocis 3:7bacae57a30b 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jocis 3:7bacae57a30b 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jocis 3:7bacae57a30b 20 * THE SOFTWARE.
jocis 3:7bacae57a30b 21 */
jocis 3:7bacae57a30b 22
jocis 0:f67a8fffd94a 23 #include "mbed.h"
jocis 0:f67a8fffd94a 24
jocis 4:f953792e45cb 25 /** Spaceball Button bit-masks */
jocis 0:f67a8fffd94a 26 #define SBALL_BUTTON_1 0x0001 /* bit 0 */
jocis 0:f67a8fffd94a 27 #define SBALL_BUTTON_2 0x0002 /* bit 1 */
jocis 0:f67a8fffd94a 28 #define SBALL_BUTTON_3 0x0004 /* bit 2 */
jocis 0:f67a8fffd94a 29 #define SBALL_BUTTON_4 0x0008 /* bit 3 */
jocis 0:f67a8fffd94a 30 #define SBALL_BUTTON_5 0x0010 /* bit 4 */
jocis 0:f67a8fffd94a 31 #define SBALL_BUTTON_6 0x0020 /* bit 5 */
jocis 0:f67a8fffd94a 32 #define SBALL_BUTTON_7 0x0040 /* bit 6 */
jocis 0:f67a8fffd94a 33 #define SBALL_BUTTON_8 0x0080 /* bit 7 */
jocis 0:f67a8fffd94a 34 #define SBALL_BUTTON_9 0x0100 /* bit 8 */
jocis 0:f67a8fffd94a 35 #define SBALL_BUTTON_10 0x0200 /* bit 9 */
jocis 0:f67a8fffd94a 36 #define SBALL_BUTTON_11 0x0400 /* bit 10 */
jocis 0:f67a8fffd94a 37 #define SBALL_BUTTON_12 0x0800 /* bit 11 */
jocis 0:f67a8fffd94a 38
jocis 0:f67a8fffd94a 39 /* The Spaceball 3003 and 3003 FLX only have "left" and "right" buttons */
jocis 0:f67a8fffd94a 40 #define SBALL_BUTTON_RIGHT 0x1000 /* bit 12 */
jocis 0:f67a8fffd94a 41 #define SBALL_BUTTON_LEFT 0x2000 /* bit 13 */
jocis 0:f67a8fffd94a 42
jocis 0:f67a8fffd94a 43 /* The Spaceball 2003A and 2003B have a dedicated pick button on the ball */
jocis 0:f67a8fffd94a 44 /* The Spaceball 2003 FLX uses "button 9" as the pick button. */
jocis 0:f67a8fffd94a 45 /* All of them return this as "button 9" in their encoded button data */
jocis 0:f67a8fffd94a 46 #define SBALL_BUTTON_PICK SBALL_BUTTON_RIGHT /* bit 12 */
jocis 0:f67a8fffd94a 47
jocis 0:f67a8fffd94a 48 /* On Spaceball 2003A and 2003B, the Rezero is "button 8" on the device */
jocis 0:f67a8fffd94a 49 /* On the newer devices, there are dedicated rezero buttons */
jocis 0:f67a8fffd94a 50 #define SBALL_BUTTON_REZERO 0x4000 /* bit 14 */
jocis 0:f67a8fffd94a 51
jocis 0:f67a8fffd94a 52 /* The Spaceball 4000 FLX has a configurable palm rest which can be in */
jocis 0:f67a8fffd94a 53 /* either "left" or "right" handed mode. When it is configured in "left" */
jocis 0:f67a8fffd94a 54 /* handed mode, the "lefty" bit is set, and coordinate systems need to be */
jocis 0:f67a8fffd94a 55 /* inverted on one axis. */
jocis 0:f67a8fffd94a 56 #define SBALL_MODE_LEFTY 0x8000 /* bit 15 */
jocis 0:f67a8fffd94a 57
jocis 0:f67a8fffd94a 58
jocis 1:e6282b645d9b 59 #define SPACEBALL_MAX_LENGTH 128
jocis 1:e6282b645d9b 60
jocis 4:f953792e45cb 61 /** Axis enumeration for function GetAxis() */
jocis 0:f67a8fffd94a 62 enum eSpaceBallAxis {
jocis 0:f67a8fffd94a 63 TX=0, TY, TZ,
jocis 0:f67a8fffd94a 64 Right=0, Forward, Up,
jocis 0:f67a8fffd94a 65 RX=3, RY, RZ,
jocis 0:f67a8fffd94a 66 Pitch=3, Roll, Yaw };
jocis 0:f67a8fffd94a 67
jocis 4:f953792e45cb 68 /** Mapping enumeration for function GetAxis() to adapt coordinate system */
jocis 2:a7c0fcd157f7 69 enum eSpaceBallMapping {
jocis 2:a7c0fcd157f7 70 RAW=0, CNC, CNCvert };
jocis 2:a7c0fcd157f7 71
jocis 3:7bacae57a30b 72 /** SpaceBall class, based on serial connection
jocis 4:f953792e45cb 73 *
jocis 4:f953792e45cb 74 * Library to handle SpaceBall, SpaceMouse and SpaceOrb on serial port. Gets access to 3D rotation and translation vector as well as button status
jocis 4:f953792e45cb 75 *
jocis 4:f953792e45cb 76 * Supported devices:
jocis 4:f953792e45cb 77 * - Spaceball 2003A
jocis 4:f953792e45cb 78 * - Spaceball 2003B
jocis 4:f953792e45cb 79 * - Spaceball 2003 FLX
jocis 4:f953792e45cb 80 * - Spaceball 3003
jocis 4:f953792e45cb 81 * - Spaceball 3003 FLX
jocis 4:f953792e45cb 82 * - Spaceball 4000 FLX
jocis 4:f953792e45cb 83 * - SpaceMouse
jocis 4:f953792e45cb 84 * - SpaceOrb (Note: Flag has to be set in constructor)
jocis 4:f953792e45cb 85 *
jocis 4:f953792e45cb 86 * Note: USB or wireless devices are NOT supported by this class
jocis 4:f953792e45cb 87 *
jocis 4:f953792e45cb 88 * Serial connection (D-Sub 9p male):
jocis 4:f953792e45cb 89 * - 3 <--- RS232 Driver <--- mbed TX
jocis 4:f953792e45cb 90 * - 2 ---> RS232 Driver ---> mbed RX
jocis 4:f953792e45cb 91 * - 5 ----| GND
jocis 4:f953792e45cb 92 * - 4 <--- Power +9...+12 volt
jocis 4:f953792e45cb 93 * - 7 <--- Power +9...+12 volt
jocis 4:f953792e45cb 94 *
jocis 4:f953792e45cb 95 * Example: (illuminates LEDs dependent on force at the Spaceball)
jocis 4:f953792e45cb 96 * @code
jocis 4:f953792e45cb 97 #include "mbed.h"
jocis 4:f953792e45cb 98 #include "SpaceBall.h"
jocis 4:f953792e45cb 99
jocis 4:f953792e45cb 100 PwmOut led[] = {(LED1), (LED2), (LED3), (LED4) };
jocis 4:f953792e45cb 101 SpaceBall SBall(p9, p10); // tx, rx, bSOrb
jocis 4:f953792e45cb 102
jocis 4:f953792e45cb 103 int main() {
jocis 4:f953792e45cb 104 SBall.Init();
jocis 4:f953792e45cb 105
jocis 4:f953792e45cb 106 while(1) {
jocis 4:f953792e45cb 107
jocis 4:f953792e45cb 108 led[0] = abs( SBall[TX] ) + abs( SBall[TY] ) + abs( SBall[TZ] );
jocis 4:f953792e45cb 109 led[1] = abs( SBall[RX] );
jocis 4:f953792e45cb 110 led[2] = abs( SBall[RY] );
jocis 4:f953792e45cb 111 led[3] = abs( SBall[RZ] );
jocis 4:f953792e45cb 112
jocis 4:f953792e45cb 113 wait_us(500);
jocis 4:f953792e45cb 114 }
jocis 4:f953792e45cb 115 }
jocis 3:7bacae57a30b 116 * @endcode
jocis 3:7bacae57a30b 117 */
jocis 0:f67a8fffd94a 118 class SpaceBall {
jocis 0:f67a8fffd94a 119 public:
jocis 0:f67a8fffd94a 120
jocis 3:7bacae57a30b 121 /** Create a input object connected to the specified serial pin
jocis 3:7bacae57a30b 122 *
jocis 4:f953792e45cb 123 * @param tx Serial TX pin to connect to
jocis 4:f953792e45cb 124 * @param rx Serial RX pin to connect to
jocis 4:f953792e45cb 125 * @param bSpaceOrb Flag to select device. false = SpaceBall and SpaceMouse. true = SpaceOrb
jocis 3:7bacae57a30b 126 */
jocis 0:f67a8fffd94a 127 SpaceBall ( PinName tx, PinName rx, bool bSpaceOrb=false );
jocis 4:f953792e45cb 128
jocis 4:f953792e45cb 129 /** destructor */
jocis 0:f67a8fffd94a 130 ~SpaceBall() {};
jocis 0:f67a8fffd94a 131
jocis 4:f953792e45cb 132 /** initializing the connection to the device
jocis 3:7bacae57a30b 133 *
jocis 3:7bacae57a30b 134 */
jocis 0:f67a8fffd94a 135 void Init();
jocis 0:f67a8fffd94a 136
jocis 4:f953792e45cb 137 /** Set mapping mode for function GetAxis() to adapt coordinate system
jocis 4:f953792e45cb 138 *
jocis 4:f953792e45cb 139 * @param mapping Mapping mode
jocis 4:f953792e45cb 140 */
jocis 2:a7c0fcd157f7 141 void SetMapping ( int mapping )
jocis 2:a7c0fcd157f7 142 { _mapping = mapping; }
jocis 2:a7c0fcd157f7 143
jocis 4:f953792e45cb 144 /** Gets the translation axis (push, pull) as 3D vector
jocis 4:f953792e45cb 145 *
jocis 4:f953792e45cb 146 * @param fValue[] Return vector with X, Y and Z
jocis 4:f953792e45cb 147 */
jocis 0:f67a8fffd94a 148 void GetTranslation ( float* fValue[3] ) const
jocis 0:f67a8fffd94a 149 {
jocis 0:f67a8fffd94a 150 *fValue[0] = GetAxis ( TX );
jocis 0:f67a8fffd94a 151 *fValue[1] = GetAxis ( TY );
jocis 0:f67a8fffd94a 152 *fValue[2] = GetAxis ( TZ );
jocis 0:f67a8fffd94a 153 }
jocis 2:a7c0fcd157f7 154
jocis 4:f953792e45cb 155 /** Gets the rotation axis as 3D vector
jocis 4:f953792e45cb 156 *
jocis 4:f953792e45cb 157 * @param fValue[] Return vector with Pitch, Roll and Yaw
jocis 4:f953792e45cb 158 */
jocis 0:f67a8fffd94a 159 void GetRotation ( float* fValue[3] ) const
jocis 0:f67a8fffd94a 160 {
jocis 0:f67a8fffd94a 161 *fValue[0] = GetAxis ( RX );
jocis 0:f67a8fffd94a 162 *fValue[1] = GetAxis ( RY );
jocis 0:f67a8fffd94a 163 *fValue[2] = GetAxis ( RZ );
jocis 0:f67a8fffd94a 164 }
jocis 2:a7c0fcd157f7 165
jocis 4:f953792e45cb 166 /** Gets a single axis value. Coordinate system is mapped according function SetMapping()
jocis 4:f953792e45cb 167 *
jocis 4:f953792e45cb 168 * @param nAxis Axis index/name
jocis 4:f953792e45cb 169 * @return Axis value as scaled float
jocis 4:f953792e45cb 170 */
jocis 2:a7c0fcd157f7 171 float GetAxis ( int nAxis ) const;
jocis 2:a7c0fcd157f7 172
jocis 4:f953792e45cb 173 /** Gets a single axis value. Coordinate system is mapped according function SetMapping()
jocis 4:f953792e45cb 174 *
jocis 4:f953792e45cb 175 * @param nAxis Axis index/name
jocis 4:f953792e45cb 176 * @return Axis value as unscaled int (as provided by the SpaceBall)
jocis 4:f953792e45cb 177 */
jocis 2:a7c0fcd157f7 178 int GetAxisRaw ( int nAxis ) const;
jocis 2:a7c0fcd157f7 179
jocis 4:f953792e45cb 180 /** Gets a single axis value as [] operator. Coordinate system is mapped according function SetMapping()
jocis 4:f953792e45cb 181 *
jocis 4:f953792e45cb 182 * Usage: float x = spaceball[RX];
jocis 4:f953792e45cb 183 *
jocis 4:f953792e45cb 184 * @param nAxis Axis index/name
jocis 4:f953792e45cb 185 * @return Axis value as scaled float
jocis 4:f953792e45cb 186 */
jocis 0:f67a8fffd94a 187 float operator[] (eSpaceBallAxis nAxis) const
jocis 0:f67a8fffd94a 188 { return GetAxis ( nAxis ); }
jocis 4:f953792e45cb 189
jocis 4:f953792e45cb 190 /** Gets a single axis value as [] operator. Coordinate system is mapped according function SetMapping()
jocis 4:f953792e45cb 191 *
jocis 4:f953792e45cb 192 * Usage: float x = spaceball[3];
jocis 4:f953792e45cb 193 *
jocis 4:f953792e45cb 194 * @param nAxis Axis index/name
jocis 4:f953792e45cb 195 * @return Axis value as scaled float
jocis 4:f953792e45cb 196 */
jocis 0:f67a8fffd94a 197 float operator[] (int nAxis) const
jocis 0:f67a8fffd94a 198 { return GetAxis ( nAxis ); }
jocis 0:f67a8fffd94a 199
jocis 4:f953792e45cb 200 /** Gets the button states as an bit-combination. See definitions of Spaceball Button bit-masks
jocis 4:f953792e45cb 201 *
jocis 4:f953792e45cb 202 * @return Buttons bit-combination
jocis 4:f953792e45cb 203 */
jocis 0:f67a8fffd94a 204 int GetButtons() const
jocis 2:a7c0fcd157f7 205 { return _buttons; }
jocis 2:a7c0fcd157f7 206
jocis 4:f953792e45cb 207 /** Gets the button states as an bit-combination as int operator. See definitions of Spaceball Button bit-masks
jocis 4:f953792e45cb 208 *
jocis 4:f953792e45cb 209 * Usage: int b = spaceball;
jocis 4:f953792e45cb 210 *
jocis 4:f953792e45cb 211 * @return Buttons bit-combination
jocis 4:f953792e45cb 212 */
jocis 0:f67a8fffd94a 213 operator int (void) const
jocis 0:f67a8fffd94a 214 { return GetButtons(); }
jocis 0:f67a8fffd94a 215
jocis 4:f953792e45cb 216 /** Sets the additional scaling factor for function GetAxis()
jocis 4:f953792e45cb 217 *
jocis 4:f953792e45cb 218 * @param fScale Scaling factor
jocis 4:f953792e45cb 219 */
jocis 0:f67a8fffd94a 220 void SetScale ( float fScale=1.0f )
jocis 0:f67a8fffd94a 221 { _fScale = fScale; }
jocis 4:f953792e45cb 222
jocis 4:f953792e45cb 223 /** Gets the additional scaling factor for function GetAxis()
jocis 4:f953792e45cb 224 *
jocis 4:f953792e45cb 225 * @return Scaling factor
jocis 4:f953792e45cb 226 */
jocis 0:f67a8fffd94a 227 float GetScale ( void )
jocis 0:f67a8fffd94a 228 { return _fScale; }
jocis 0:f67a8fffd94a 229
jocis 0:f67a8fffd94a 230
jocis 0:f67a8fffd94a 231 protected:
jocis 0:f67a8fffd94a 232 Serial _serial;
jocis 0:f67a8fffd94a 233 bool _bSpaceOrb;
jocis 0:f67a8fffd94a 234 float _fScale;
jocis 0:f67a8fffd94a 235
jocis 2:a7c0fcd157f7 236 int _axis[6]; /* last translational data received */
jocis 2:a7c0fcd157f7 237 int _buttons; /* current button status */
jocis 0:f67a8fffd94a 238
jocis 0:f67a8fffd94a 239 void SerialISR(void);
jocis 0:f67a8fffd94a 240 void Process ( char c );
jocis 0:f67a8fffd94a 241
jocis 0:f67a8fffd94a 242 virtual void DoChangedAxis (void) {};
jocis 0:f67a8fffd94a 243 virtual void DoChangedButtons (void) {};
jocis 0:f67a8fffd94a 244
jocis 0:f67a8fffd94a 245 private:
jocis 0:f67a8fffd94a 246 int m_erroroccured; /* if set, we've received an error packet or packets */
jocis 0:f67a8fffd94a 247 int m_resetoccured; /* if set, ball was reset, so have to reinitialize it */
jocis 0:f67a8fffd94a 248 int m_spaceball4000; /* if set, its a Spaceball 4000 */
jocis 0:f67a8fffd94a 249 int m_leftymode4000; /* if set, Spaceball 4000 in "lefty" orientation */
jocis 0:f67a8fffd94a 250
jocis 1:e6282b645d9b 251 bool _escape;
jocis 1:e6282b645d9b 252 int _idx;
jocis 1:e6282b645d9b 253 char _data[SPACEBALL_MAX_LENGTH];
jocis 2:a7c0fcd157f7 254
jocis 2:a7c0fcd157f7 255 float _fScaleR;
jocis 2:a7c0fcd157f7 256 float _fScaleT;
jocis 2:a7c0fcd157f7 257 int _mapping;
jocis 1:e6282b645d9b 258
jocis 1:e6282b645d9b 259 void InitSB();
jocis 1:e6282b645d9b 260 void InitSO();
jocis 0:f67a8fffd94a 261
jocis 0:f67a8fffd94a 262 void ProcessSB ( char c );
jocis 0:f67a8fffd94a 263 void ProcessSO ( char c );
jocis 1:e6282b645d9b 264
jocis 1:e6282b645d9b 265 void ProcessPacketSB ( void );
jocis 1:e6282b645d9b 266 void ProcessPacketSO ( void );
jocis 1:e6282b645d9b 267
jocis 0:f67a8fffd94a 268 };