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

SpaceBall.h

Committer:
jocis
Date:
2014-09-03
Revision:
4:f953792e45cb
Parent:
3:7bacae57a30b

File content as of revision 4:f953792e45cb:

/* mbed SpaceBall, SpaceMouse and SpaceOrb Library
 * Copyright (c) 2012 Jochen Krapf
 *
 * 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 "mbed.h"

/** Spaceball Button bit-masks */
#define SBALL_BUTTON_1        0x0001   /* bit  0 */
#define SBALL_BUTTON_2        0x0002   /* bit  1 */
#define SBALL_BUTTON_3        0x0004   /* bit  2 */
#define SBALL_BUTTON_4        0x0008   /* bit  3 */
#define SBALL_BUTTON_5        0x0010   /* bit  4 */
#define SBALL_BUTTON_6        0x0020   /* bit  5 */
#define SBALL_BUTTON_7        0x0040   /* bit  6 */
#define SBALL_BUTTON_8        0x0080   /* bit  7 */
#define SBALL_BUTTON_9        0x0100   /* bit  8 */
#define SBALL_BUTTON_10       0x0200   /* bit  9 */
#define SBALL_BUTTON_11       0x0400   /* bit 10 */
#define SBALL_BUTTON_12       0x0800   /* bit 11 */

/* The Spaceball 3003 and 3003 FLX only have "left" and "right" buttons */
#define SBALL_BUTTON_RIGHT    0x1000   /* bit 12 */
#define SBALL_BUTTON_LEFT     0x2000   /* bit 13 */

/* The Spaceball 2003A and 2003B have a dedicated pick button on the ball */
/* The Spaceball 2003 FLX uses "button 9" as the pick button.             */
/* All of them return this as "button 9" in their encoded button data     */
#define SBALL_BUTTON_PICK      SBALL_BUTTON_RIGHT   /* bit  12 */

/* On Spaceball 2003A and 2003B, the Rezero is "button 8" on the device */
/* On the newer devices, there are dedicated rezero buttons */
#define SBALL_BUTTON_REZERO  0x4000   /* bit 14 */

/* The Spaceball 4000 FLX has a configurable palm rest which can be in    */
/* either "left" or "right" handed mode.  When it is configured in "left" */
/* handed mode, the "lefty" bit is set, and coordinate systems need to be */
/* inverted on one axis.                                                  */
#define SBALL_MODE_LEFTY     0x8000   /* bit 15 */


#define SPACEBALL_MAX_LENGTH    128

/** Axis enumeration for function GetAxis() */
enum eSpaceBallAxis { 
    TX=0, TY, TZ, 
    Right=0, Forward, Up, 
    RX=3, RY, RZ,
    Pitch=3, Roll, Yaw };

/** Mapping enumeration for function GetAxis() to adapt coordinate system */
enum eSpaceBallMapping { 
    RAW=0, CNC, CNCvert };

/** SpaceBall class, based on serial connection
*
* Library to handle SpaceBall, SpaceMouse and SpaceOrb on serial port. Gets access to 3D rotation and translation vector as well as button status
*
* Supported devices:
* - Spaceball 2003A
* - Spaceball 2003B
* - Spaceball 2003 FLX
* - Spaceball 3003
* - Spaceball 3003 FLX
* - Spaceball 4000 FLX
* - SpaceMouse
* - SpaceOrb (Note: Flag has to be set in constructor)
*
* Note: USB or wireless devices are NOT supported by this class
*
* Serial connection (D-Sub 9p male):
* - 3 <--- RS232 Driver <--- mbed TX
* - 2 ---> RS232 Driver ---> mbed RX
* - 5 ----| GND
* - 4 <--- Power +9...+12 volt
* - 7 <--- Power +9...+12 volt
*
* Example: (illuminates LEDs dependent on force at the Spaceball)
* @code
#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);
    }
}
 * @endcode
 */
class SpaceBall {
public:
    
    /** Create a input object connected to the specified serial pin
     *
     * @param tx    Serial TX pin to connect to 
     * @param rx    Serial RX pin to connect to 
     * @param bSpaceOrb    Flag to select device. false = SpaceBall and SpaceMouse. true = SpaceOrb  
     */
    SpaceBall ( PinName tx, PinName rx, bool bSpaceOrb=false );
    
    /** destructor */
    ~SpaceBall() {};

    /** initializing the connection to the device
     *
     */
    void Init();
    
    /** Set mapping mode for function GetAxis() to adapt coordinate system
     *
     * @param mapping   Mapping mode
     */
    void SetMapping ( int mapping )
    {   _mapping = mapping; }
    
    /** Gets the translation axis (push, pull) as 3D vector
     *
     * @param fValue[]   Return vector with X, Y and Z
     */
    void GetTranslation ( float* fValue[3] ) const
    {
        *fValue[0] = GetAxis ( TX );
        *fValue[1] = GetAxis ( TY );
        *fValue[2] = GetAxis ( TZ );
    }
    
    /** Gets the rotation axis as 3D vector
     *
     * @param fValue[]   Return vector with Pitch, Roll and Yaw
     */
    void GetRotation ( float* fValue[3] ) const
    {
        *fValue[0] = GetAxis ( RX );
        *fValue[1] = GetAxis ( RY );
        *fValue[2] = GetAxis ( RZ );
    }
    
    /** Gets a single axis value. Coordinate system is mapped according function SetMapping() 
     *
     * @param nAxis   Axis index/name
     * @return        Axis value as scaled float
     */
    float GetAxis ( int nAxis ) const;
    
    /** Gets a single axis value. Coordinate system is mapped according function SetMapping() 
     *
     * @param nAxis   Axis index/name
     * @return        Axis value as unscaled int (as provided by the SpaceBall)
     */
    int GetAxisRaw ( int nAxis ) const;
    
    /** Gets a single axis value as [] operator. Coordinate system is mapped according function SetMapping() 
     *
     * Usage: float x = spaceball[RX];
     *
     * @param nAxis   Axis index/name
     * @return        Axis value as scaled float
     */
    float operator[] (eSpaceBallAxis nAxis) const
    {   return GetAxis ( nAxis ); }
    
    /** Gets a single axis value as [] operator. Coordinate system is mapped according function SetMapping() 
     *
     * Usage: float x = spaceball[3];
     *
     * @param nAxis   Axis index/name
     * @return        Axis value as scaled float
     */
    float operator[] (int nAxis) const
    {   return GetAxis ( nAxis ); }
    
    /** Gets the button states as an bit-combination. See definitions of Spaceball Button bit-masks
     *
     * @return        Buttons bit-combination
     */
    int GetButtons() const
    {   return _buttons; }
    
    /** Gets the button states as an bit-combination as int operator. See definitions of Spaceball Button bit-masks
     *
     * Usage: int b = spaceball;
     *
     * @return        Buttons bit-combination
     */
    operator int (void) const
    {   return GetButtons(); }
    
    /** Sets the additional scaling factor for function GetAxis() 
     *
     * @param fScale  Scaling factor
     */
    void SetScale ( float fScale=1.0f )
    {   _fScale = fScale; }

    /** Gets the additional scaling factor for function GetAxis() 
     *
     * @return        Scaling factor
     */
    float GetScale ( void )
    {   return _fScale; }


protected:
    Serial _serial;
    bool _bSpaceOrb;
    float _fScale;
    
    int _axis[6];      /* last translational data received */
    int _buttons;       /* current button status */
    
    void SerialISR(void);
    void Process ( char c );
    
    virtual void DoChangedAxis (void) {};
    virtual void DoChangedButtons (void) {};
    
private:
    int m_erroroccured;  /* if set, we've received an error packet or packets */
    int m_resetoccured;  /* if set, ball was reset, so have to reinitialize it */
    int m_spaceball4000; /* if set, its a Spaceball 4000 */
    int m_leftymode4000; /* if set, Spaceball 4000 in "lefty" orientation */

    bool _escape;
    int _idx;
    char _data[SPACEBALL_MAX_LENGTH];

    float _fScaleR;
    float _fScaleT;
    int _mapping;
    
    void InitSB();
    void InitSO();

    void ProcessSB ( char c );
    void ProcessSO ( char c );
    
    void ProcessPacketSB ( void );
    void ProcessPacketSO ( void );

};