******************* Programming and Use ******************* Compatible Devices ================== Spacetec SpaceOrb 360 --------------------- The Spacetec SpaceOrb 360 works with the Orbduino. In default configuration, chording (see below) is enabled and the orb is set up in a "face" configuration such that if you hold the orb with the ball at the top, pushing the ball away from you is the +y direction. SpaceBall 4000 -------------- The SpaceBall 4000 is a fantastic gaming device, with a desk-mounted ball supporting 12 buttons. Chording is disabled by default for the SpaceBall 4000. The default configuration for the SpaceBall 4000 is in a "left-handed" mode; if you use the SpaceBall 4000 in a right-handed mode, you may need to switch the polarities of several axes. The desk-mounted SpaceBall 4000 and 5000 allow the orb to be manipulated by the left hand while the regular mouse can be used by the right hand for precision aiming. The combination is very effective. Initialization ^^^^^^^^^^^^^^ The SpaceBall requires an initialization string before sending updates. When the device is plugged in, you should hear two beeps as it initializes. Once the dip switches on the orbduino are turned on (see below) you must press button 1 on the SpaceBall. You should hear two more beeps and the device will be ready for operation. SpaceBall 5000 and Magellan SpaceMouse -------------------------------------- The Orbduino has been tested with the Magellan SpaceMouse and should thus be compatible with the SpaceBall 5000. Magellan SpaceMouse Buttons ^^^^^^^^^^^^^^^^^^^^^^^^^^^ It should be noted that the buttons on the Magellan SpaceMouse are labeled 1-8 with a "*" button in the centre. The "*" button is actually button 1, and the buttons labeled 1-8 are numbered as 2-9 by the Orbduino. Initialization ^^^^^^^^^^^^^^ Like the SpaceBall 4000 (see above) the Magellan needs an initialization string from the Orbduino. This will be sent the first time button 1 (the "*" button) is pressed after the DIP switches are on. Unlike the SpaceBall 4000, the Magellan does not make a second series of beeps. Programming the orb =================== Turn dip switches OFF --------------------- In order to program the Arduino, the computer must be able to talk to it. For this, the DIP switches on the OrbShield must be turned OFF: .. image:: use01_dipswitchoff.* Plug in the Arduino ------------------- Now plug in the Arduino using the Arduino's USB connector (not the OrbShield's!) .. image:: use01_plugprogram.* Plug the other end of the USB cable into the computer. Your computer should detect the Arduino. Program the Arduino ------------------- Refer to the Arduino software documentation for programming if you have any questions, but in general you should start the Arduino software, set the board type and com port, and open a sketch. To begin with, open the BasicJoystick sketch. Look for the lines:: //change value below to SpaceOrb360, SpaceBall4000, or SpaceBall5000 Logical_orb orb_buffer( SpaceOrb360 ); and change the value to that appropriate for the device. Finally, click the upload button: .. image:: use02_arduino.* After a short delay, you should see a success message in the Arduino software's display: .. image:: use03_arduino.* The sketch size could be different depending on the version of the software. Normal Use ========== Unplug/Replug ------------- The Arduino's USB port is only used for serial communication to the Arduino. We will use the OrbShield's USB port for use as a HID device. Unplug the Arduino from the computer, and switch the plug from the Arduino's USB port to the OrbShield's. Plug the SpaceOrb into the DB-9 socket: .. image:: use04_plugorb.* Note: once the Arduino is programmed, you may use it without reprogramming until you need its behaviour changed; turning off the computer or unplugging the Arduino will not affect it or require reprogramming. Turn DIP switch #1 ON --------------------- To allow the orb to communicate with the Arduino, we now have to connect the input line by switching DIP switch #1 ON. You can set DIP switch #2 on as well; it should not matter with the SpaceOrb (in the case of the SpaceBall series, you must set switch #2 on, as the SpaceBall series needs an initialization string from the OrbShield before it begins sending data). .. image:: use05_dipswitchon.* Plug in the OrbShield --------------------- You should see a message that the Orb has been detected. It will show up in your control panel joystick applet as UsbJoystick, with the following properties: .. image:: use06_controlpanel.* Wiggle the orb and verify that the axes move and buttons press. Congratulations on building your OrbShield! OrbShield concepts and demos ============================ The Basic Orb Sketch -------------------- The most basic thing you can do with the OrbShield and a device is to make it appear to the operating system as a USB HID Joystick. The sketch to do this is the BasicJoystick sketch:: #include "orb_device.h" #include "orb_translator.h" #include "hid_keys.h" #include "chart_4.h" //change value below to SpaceOrb360, SpaceBall4000, or SpaceBall5000 Logical_orb orb_buffer( SpaceOrb360 ); Orb_translator translator; void setup() { Serial.begin( 9600 ); translator.default_setup(orb_buffer.orb_type); } void loop() { orbduino_checkinit( orb_buffer, translator, orb_device ); orbduino_translate( orb_buffer, translator, orb_device ); } The loop() function should almost always be the same, but varying the setup function may be important depending on the sensitivity, bindings, polarity, etc you desire. The default settings (particularly axis assignments and polarity) work for many people. If you are using the SpaceOrb in an "edge" configuration or are using the SpaceBall 4000 in a right-handed configuration, you may need to adjust axis assignments and polarity settings. Chording -------- The original SpaceOrb only came with six buttons, a serious limitation with most games. However, the OrbShield portrays the SpaceOrb to the host computer as a six-axis, sixteen-button device. It is possible to use the six buttons on the SpaceOrb to seem as if sixteen buttons are available through the use of multiple buttons, a technique known as *chording*. When chording is enabled, the two edge buttons on the orb (A and B) are used to select a "page" for the other four buttons (c-f). The assignments work as follows: * if neither A nor B is pressed, C-F are buttons 1-4 * If A is pressed, C-F are buttons 5-8 * If B is pressed, C-F are buttons 9-12 * If A and B are pressed together, C-F are buttons 13-16 To enable chording, insert the following line in the ``setup()`` function of your orb sketch:: translator.set_chording( true ); You can examine chording in the ``BasicJoystick`` sketch by adding the above line and setting the value to true or false. **SpaceOrb users** : Chording is enabled by default for the SpaceOrb 360. **SpaceBall users** : It is not suggested to use chording with the SpaceBall 4000FLX at this time. The 4000FLX has twelve buttons already, but the HID reports going to the computer only support sixteen buttons. Sensitivity and Gain -------------------- Sensitivity ^^^^^^^^^^^ The SpaceOrb by default has a linear response, meaning that if you push it halfway from center to one edge, the result will be halfway along its possible range. However, to make the response flatter near the center, the creators of the SpaceOrb preferred a cubic response. This is more easily envisioned with the following figure: .. image:: sensitivity.jpg The preferred curve is curve #4 in the above picture. As you can see, near the center the curve is relatively flat, to permit reasonably fine-grained control, but ramps up sharply near the edges for fast movement when necessary. This curve is called the *sensitivity* curve. To use the sensitivity curve in your sketches, add the line:: #include "chart_4.h" At the top of your sketch, and in the ``setup()`` function, add:: translator.set_sensitivity_table( sensitivity_4_chart ); Gain ^^^^ You may find that you need even more control over the motion of the orb. If so, you may add *gain* to your sketch. Gain acts as a 1/10th multiplier or divider for the final value of the orb; for example, if you would ordinarily have moved the orb so that its x-value is halfway from the center to the edge, with a gain of "20" you would have it at full deflection. Positive values of gain amplify the orb's motion, such that a gain of 30 would be three times normal value; negative values of gain reduce the orb's motion, such that a gain of -30 would be 1/3 normal value. To set the global gain of your orb, add the following line to the ``setup()`` function of your sketch, changing the value of 30 to your desired value:: translator.set_gain( 30 ); Precision Gain ^^^^^^^^^^^^^^ You may find that you want the orb to be more sensitive during motion, but wish to have it be less sensitive during aiming. To do this, you can use the *precision gain* feature of the OrbShield. Precision gain changes the orb's gain setting to a different value (typically a negative value to damp the orb's reaction) when a particular button combination is pressed. This button combination is a binary number representing the combination of buttons used to activate precision gain. For example, if you wish to enable precision mode when button A is pressed, you would use a mask of ``1`` or ``0x01``. If you wished to enable it with button B pressed, use a mask of ``2`` or ``0x02``, or ``(0x01 << 1)``. If you wanted to use it only when BOTH button A and button B were pressed, use a mask of ``3``, or ``0x01 || (0x01 <<1)``. You can enable precision mode in your own sketches by adding the following lines to the ``setup()`` function of your sketch:: translator.set_precision_gain( -20 ); translator.set_precision_mask( 0x01 ); You may explore sensitivity, gain, and precision gain in the ``GainDemo`` demo sketch. Upload the ``GainDemo`` sketch to your orb, open the control panel joystick applet, and move the orb about the X and Y axes; notice that the orb seems to have different sensitivity on the X axis vs the Y axis. Press button 1 and notice that the motion of the two axes changes dramatically. Keyboard Axis Binding --------------------- Many games do not support joysticks, or if they do they do not support six-axis controllers such as the SpaceOrb. To add to the flexibility of the SpaceOrb, we implemented the ability to bind keyboard keypresses to various axes ranges. This is best illustrated by an example, demonstrated (among other concepts) in the ``WASD`` demo. If you upload this to your SpaceOrb, you will discover on replugging that the X and Y axes now also produce *WASD* keypresses for motion in first-person shooter games (see below), and that pulling up or pushing down on the Z-axis results in space (jump) or control (duck) keypresses. The latter is done by first adding some lines above the ``setup()`` function which describe the bindings:: PROGMEM Axis_key_binding axis_key_bindings[] = { { 2, 773, 1023, MOD_CONTROL_LEFT, 0 }, { 2, 0, 250, 0, KEY_SPACE } }; Each line of the structure represents a binding in the form:: { axis_number, min value, max value, modifiers, keypress } Remember that the axes of the spaceorb go from 0 to 1023, with 512 the central value. You *must not* forget the ``PROGMEM`` keyword before the structure! This places the bindings in static flash memory on the Arduino microcontroller where they will not interfere with the program itself. Once your bindings are created, you must add these lines in the ``setup()`` function:: translator.set_axis_key_bindings( axis_key_bindings, 2 ); This sets the key bindings to those you defined above, and lets the OrbDuino software know there are six bindings. Keyboard Fourway Bindings ------------------------- Axis bindings as described above are ideal for binding a single axis to keypresses, but have difficulty when binding a plane of movement to keys representing directions of motion. The reason for this can be easily demonstrated when trying to bind the orb to the WASD keys used by many FPS games for motion. A naive implementation would be to bind the X-axis to A and D, and the Y-axis to W and S as shown below: .. image:: wasd_biglanes.* This works reasonably well, but leaves a huge "null area" in the centre of the plane, requiring large motions to move. It may seem that the way to fix this is to shrink the size of the null area: .. image:: wasd_smallanes.* ...however, this will not have the desired effect, because now it is almost impossible to, say, walk straight forward without moving to the left or right. What is more desirable is to have keyboard assignments to arcs in the plane: .. image:: wasd_arcs.* To do this, the Fourway_keyboard_binding mechanism was created:: struct Fourway_keyboard_binding { unsigned short axis_x; unsigned short axis_y; char n; char s; char e; char w; long deadzone_radius_squared; }; To use it, create a ``Fourway_keyboard_binding`` in your arduino code:: const PROGMEM Fourway_keyboard_binding WASD_fourway_binding = { 0, 1, KEY_S, KEY_W, KEY_D, KEY_A, 75*75 }; and in your setup function, include the line:: translator.set_fourway_bindings( &WASD_fourway_binding, 1 ); In the WASD sketch, the X-Y plane is bound to WASD, the usual first-person shooter movement keys. Keyboard Button Bindings ------------------------ You can also bind button presses to keyboard events. To understand how these work, examine the ``WASD`` demo sketch. Again, bindings are defined in a similar way, by using structures:: // sets buttons 4-7 to keyboard 1-4 (eg for weapon select) PROGMEM Button_key_binding button_key_bindings[] = { { 0x01 << 2, 0, KEY_1 }, { 0x01 << 3, 0, KEY_2 }, { 0x01 << 4, 0, KEY_3 }, { 0x01 << 5, 0, KEY_4 }, }; In this case, the bindings take the form:: { button id, modifier, keypress } You must also add the following line in ``setup()``:: translator.set_button_key_bindings( button_key_bindings, 4 ); Again, the number reflects the number of bindings. In the WASD sketch, buttons 3,4,5,6 are bound to keyboard keys 1,2,3,4. Mouse Bindings -------------- In the event a game does not accept joystick bindings at all, you may bind SpaceOrb axes to mouse movements and buttons to mouse buttons. Examine the ``WASD`` demo sketch to see this in action. With the ``WASD`` sketch loaded, your orb's Rx and Rz axes will move the mouse, while buttons 1 and 2 are the left and right mouse buttons. The third button is available as well. Binding Axes ^^^^^^^^^^^^ To bind orb axes to mouse axes, add lines like the following to the top of your sketch:: PROGMEM Axis_mouse_binding axis_mouse_bindings[] = { { 0, MOUSE_AXIS_X, 3 }, { 1, MOUSE_AXIS_Y, 3 } }; These bindings take the form:: { spaceball axis, mouse axis, scale } For now (0.9b2) scale is a *shift*; in other words "3" means that the value of the orb axis will be shifted three times to the right (divided by 8) to get the mouse axis value. To reverse the polarity of a mouse binding, negate the value of scale (in other words, if your y-axis is moving opposite the direction you expect, try setting the scale to "-3" instead of "3") You must also add the following line to the ``setup()`` function: translator.set_axis_mouse_bindings( axis_mouse_bindings, 2 ); ...where "2" is the appropriate number of bindings. In the WASD sketch, the mouse x/y axes are bound to the orb's Rz and Rx axes respectively. Binding Buttons ^^^^^^^^^^^^^^^ Binding buttons to mouse buttons is very similar. Add lines like the following to the top of your sketch:: PROGMEM Button_mouse_binding button_mouse_bindings[] = { { 0x01, 0x01 }, { 0x01 << 1, 0x01 << 1 }, { 0x01 << 2, 0x01 << 2 } }; These are in the form:: { spaceorb button, mouse button ) In the WASD sketch, buttons 1 and 2 are bound to mouse buttons 1 and 2.