Hi all,

I have Saitek Cyborg Evo Force joystick that does not work with the released MacFG (1.9.1) nor latest CVS flightgear on my Mac (OSX 10.5.6). There are several issues to resolve. I list the issues below and also suggest how to fix them.


1) The latest release of PLIB does not recognize the rudder and throttle axises. I sent a patch to the PLIB developers that resolves the axis issue and the patch was accepted. The developers committed the changes to the PLIB subversion repository, http://plib.svn.sourceforge.net/viewvc/plib?view=rev&revision=2155

I suppose that when the PLIB developers release 1.8.6, the new PLIB version will be incorporated in future FG releases, and the improved joystick support will find its way to MacFlighear.


2) The second issue is that the configuration file for the Saitek Evo line of joysticks (.../Saitek/Cyborg-Evo.xml) does not recognize my joystick. The reason for this is that the name tag for the force variant of the joystick is expected to be '<name>Saitek Cyborg Evo Force</name>' whereas my joystick requires '<name>Cyborg Evo Force</name>'.

The simple fix is to add this new tag to the configuration file but the rudder and trottle axises are interchanged. Again there is a simple fix to the issue, simply change the axis assignments between the rudder and the throttle. Doing this resolves the issue locally for me.

However, on a grander scale I'd like to see the changes get into CVS repository. Adding my rudder/throttle axis change into the repository may break the Saitek Evo joysick configuration for other flightgear users on Mac. I provide 2 solutions for the configuration file problem and would be happy if one of them is pushed into the CVS repository.

A) The polished backward compatible way is to add another configuration file. To this end I have attached Cyborg-Evo-Force.xml to this mail. This configuration files is based on the Cyborg-Gold-3d-USB.xml file and will only catch joysticks that presents them as "Cyborg Evo Force" (new tag not used before).

B) The unpolished way is to make the required changes to the Cyborg-Evo.xml file. Since the changes will only affect Mac users, ask MacFG Saitek Evo users to test the new configuration. If there are happy MacFG Cyborg-Evo users they will probably react but if there is no MacFG users with Cyborg-Evo then the suggested changes will not affect anyone. I have added this second suggestion since I have no idea of the number of MacFG Cyborg Evo users, but I note that the Evo line of joysticks is not listed as confidently supported on the MacFG web site (http://macflightgear.sourceforge.net/home/documents/faq/#content_1_3) nor is Saitek themselves pro-Mac. Saitek only market their joysticks as Windows compatible. I have attached a cvs diff with changes to Cyborg-Evo.xml if this second solution is acceptable.

I prefer solution B but it may upset users. Solution B is a cleaner fix in my eyes but it is important not to alienate once user base. The question is, how many MacFG users are there with Saitek Evo joysticks?

Please note, the button assignment between configuration files in solution A and B differ since I prefer the assignments in A (almost the same as in the Cyborg-Gold-3d-USB.xml file).


Can someone with CVS write permissions review my changes and if acceptable commit them to the repository?


Cheers,

Jari
? Input/Joysticks/Saitek/Cyborg-3d-USB.xml
? Input/Joysticks/Saitek/Cyborg-Evo-Force.xml
Index: Input/Joysticks/Saitek/Cyborg-Evo.xml
===================================================================
RCS file: /var/cvs/FlightGear-0.9/data/Input/Joysticks/Saitek/Cyborg-Evo.xml,v
retrieving revision 1.10
diff -u -p -r1.10 Cyborg-Evo.xml
--- Input/Joysticks/Saitek/Cyborg-Evo.xml       20 Nov 2008 18:14:00 -0000      
1.10
+++ Input/Joysticks/Saitek/Cyborg-Evo.xml       8 Mar 2009 14:29:53 -0000
@@ -45,6 +45,7 @@ axis 5:       (hat up-down)           look u/d                
Trim E
 <name>Saitek Cyborg Evo</name>
 <name>Saitek Cyborg evo Wireless</name>
 <name>Saitek Cyborg Evo Force</name>
+<name>Cyborg Evo Force</name>
 
 <!-- ~~~~~~~~~~~~~~~~~~~~~~~~ Axis Bindings ~~~~~~~~~~~~~~~~~~~~~~~~ -->
 
@@ -67,12 +68,7 @@ axis 5:      (hat up-down)           look u/d                
Trim E
        </binding>
 </axis>
 
-<axis>
-       <number>
-               <mac>3</mac>
-               <unix>2</unix>
-               <windows>2</windows> 
-       </number>
+<axis n="2">
        <desc>Throttle</desc>
        <binding>
                <command>nasal</command>
@@ -80,12 +76,7 @@ axis 5:      (hat up-down)           look u/d                
Trim E
        </binding>
 </axis>
 
-<axis>
-       <number>
-               <mac>2</mac>
-               <unix>3</unix>
-               <windows>3</windows>
-       </number>
+<axis n="3">
        <desc>Rudder</desc>
        <binding>
                <command>property-scale</command>
<!--
$Id$

Joystick binding definitions for "Saitek Cyborg Evo Force" Joystick.

This file borrows heavily from "Cyborg-Gold-3d-USB.xml" and
"Cyborg-Evo.xml".

File created by Jari Hakkinen, March 1, 2009.

The Saitek Cyborg Evo Force is designed to be easily switchable
between a left-handed or right handed person. With that in mind {^,
F1, F2} buttons on the left, and {^, F3, F4 } buttons on the right
have repeated functionality as the 'modifier' buttons.

Axis #   (direction)         mapped to
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
axis 0:  (left-right)        aileron
axis 1:  (forward-backward)  elevator
axis 2:  (slider)            throttle
axis 3:  (twist)             rudder
axis 4:  (hat)               see button assignment below
axis 5:  (hat)               see button assignment below

~~~~ Left Side Modifiers ~~~~
button 6:   "F1"             Modifier 1
button 7:   "F2"             Modifier 2
button 10:  "^"              Modifier 3

~~~~ Right Side Modifiers ~~~~
button 8:  "F3"              Modifier 1
button 9:  "F4"              Modifier 2
button 11:  "^"              Modifier 3

button #  (location)     no modifier  modifier 1      modifier 2     modifier 3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
button 0: (trigger)      brakes       parking brake   speed brake    thrust reversers
button 1: (middle)       reset view   tail wheel lock cockpit view   reset all trims
button 2: (left)         flaps up     gear up         previous view  previous view (all)
button 3: (right)        flaps down   gear down       next view      next view (all)
button 4: (left of hat)  brakes left  *               zoom out       *
button 5: (right of hat) brakes right *               zoom in        *

axis 4:   (hat left)     look left    leaner mixture  aileron trim left   trim rudder left
axis 4:   (hat right)    look right   richer mixture  aileron trim right   trim rudder right
axis 5:   (hat down)     look down    dec prop pitch  elev down trim *
axis 5:   (hat up)       look up      inc prop pitch  elev up trim   *

When flying the Harrier, "F3/hat left" and "right" control the thrust vector.

With the keyboard's Control key pressed, the following keys have a different meaning:

Control +            no modifier
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
button 0 (trigger):  trigger selected weapon
button 1 (left):     switch to previous weapon system
button 3 (right):    switch to next weapon system

-->


<PropertyList>
	<name>Cyborg Evo Force</name>

	<data>
		<mode type="int">0</mode>
		<modifier type="int">0</modifier>
	</data>

	<nasal>
		<script>
			var selfN = cmdarg().getParent();
			var dataN = selfN.getNode("data");
			var modeN = dataN.getNode("mode");
			var modifierN = dataN.getNode("modifier");
			var left_brake = 0;
			var right_brake = 0;
			var trigger = 0;

			var modifier = 0;

			var setmodifier = func(bit, val) {
				modifierN.setValue(modifier = bits.switch(modifier, bit, val));
			}

			if (props.globals.getNode("/rotors", 0) != nil) {
				selfN.getNode("axis[0]/binding/power").setIntValue(1);
				selfN.getNode("axis[1]/binding/power").setIntValue(1);
			}

			var viewdir = props.globals.getNode("/sim").getChildren("view");
			forindex (var i; viewdir) {
				var t = viewdir[i].getNode("type");
				viewdir[i] = t != nil and t.getValue() == "lookat" ? 1 : -1;
			}

			var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1);

			var mod = 0;
			var setmode = func mod = modifierN.getValue() + modeN.getValue() * 4;
			setlistener(modeN, setmode);
			setlistener(modifierN, setmode, 1);

			var aircraft = getprop("/sim/aircraft");
			var thrust_display = func nil;
			if (aircraft == "harrier") {
				thrust_display = func {
					thv = getprop("/controls/engines/engine[0]/mixture");
					gui.popupTip("Thrust vector " ~ int(thv * 120 - 20 + 0.5));
				}
			}
		</script>
	</nasal>

	<!-- ~~~~~~~~~~~~~~~~~~~~~~~~ Axis Bindings ~~~~~~~~~~~~~~~~~~~~~~~~ -->

	<axis n="0">
		<desc>aileron</desc>
		<binding>
			<command>property-scale</command>
			<property>/controls/flight/aileron</property>
			<power type="int">2</power>
		</binding>
	</axis>

	<axis n="1">
		<desc>elevator</desc>
		<binding>
			<command>property-scale</command>
			<property>/controls/flight/elevator</property>
			<factor type="double">-1.0</factor>
			<power type="int">2</power>
		</binding>
	</axis>

	<axis n="2">
		<desc>throttle</desc>
		<binding>
			<command>nasal</command>
			<script>controls.throttleAxis()</script>
		</binding>
	</axis>

	<axis n="3">
		<desc>rudder</desc>
		<binding>
			<command>property-scale</command>
			<property>/controls/flight/rudder</property>
			<power type="int">2</power>
		</binding>
	</axis>


	<!-- ~~~~~~~~~~~~~~~~~~~~~~~~ Hat Switch ~~~~~~~~~~~~~~~~~~~~~~~~ -->
	<axis n="4">
		<desc>view left/right; mixture; aileron trim; rudder trim</desc>
		<low>
			<repeatable type="bool">true</repeatable>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						view.panViewDir(-viewdir[view.index]);
					} elsif (mod == 1) {
						controls.adjMixture(-1);
						thrust_display();
					} elsif (mod == 2) {
						controls.aileronTrim(-0.75);
					} elsif (mod == 3) {
						controls.rudderTrim(-0.75);
					}
				</script>
			</binding>
		</low>
		<high>
			<repeatable type="bool">true</repeatable>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						view.panViewDir(viewdir[view.index]);
					} elsif (mod == 1) {
						controls.adjMixture(1);
						thrust_display();
					} elsif (mod == 2) {
						controls.aileronTrim(0.75);
					} elsif (mod == 3) {
						controls.rudderTrim(0.75);
					}
				</script>
			</binding>
		</high>
	</axis>

	<axis n="5">
		<desc>view up/down; propeller pitch; elevator trim; *</desc>
		<low>
			<repeatable type="bool">true</repeatable>
			<binding>
				<command>nasal</command>
				<script>
					if (mod ==nil or mod == 0) {
						view.panViewPitch(-1);
					} elsif (mod == 1) {
						controls.adjPropeller(-1);
					} elsif (mod == 2) {
						controls.elevatorTrim(-0.75);
					} elsif (mod == 3) {
						# not used
					}
				</script>
			</binding>
		</low>
		<high>
			<repeatable type="bool">true</repeatable>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						view.panViewPitch(1);
					} elsif (mod == 1) {
						controls.adjPropeller(1);
					} elsif (mod == 2) {
						controls.elevatorTrim(0.75);
					} elsif (mod == 3) {
						# not used
					}
				</script>
			</binding>
		</high>
	</axis>


	<!-- ~~~~~~~~~~~~~~~~~~~~~~~~ Button Bindings ~~~~~~~~~~~~~~~~~~~~~~~~ -->

	<button n="0">
		<name>Trigger</name>
		<desc>brakes [+Ctrl: fire]; parking brake; speed brake; thrust reverser</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					if (kbdctrl.getBoolValue()) {
						controls.trigger(trigger = 1);
					} else {
						controls.applyBrakes(1);
					}
				} elsif (mod == 1) {
					controls.applyBrakes(1);
				} elsif (mod == 2) {
					#
				} elsif (mod == 3) {
					#
				}
			</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						if (trigger)
							controls.trigger(trigger = 0);
						else
							controls.applyBrakes(0);
					} elsif (mod == 1) {
						i = controls.applyParkingBrake(1);
						gui.popupTip("Parking Brake " ~ (i ? "ON" : "OFF"));
						controls.applyBrakes(0);
					} elsif (mod == 2) {
						i = !getprop("/controls/flight/speedbrake");
						setprop("/controls/flight/speedbrake", i);
						gui.popupTip("Speed Brake " ~ (i ? "ON" : "OFF"));
					} elsif (mod == 3) {
						i = !getprop("/controls/engines/engine[0]/reverser");
						props.setAll("/controls/engines/engine", "reverser", i);
						gui.popupTip("Thrust Reverser " ~ (i ? "ON" : "OFF"));
					}
				</script>
			</binding>
		</mod-up>
	</button>

	<button n="1">
		<name>Middle Button below Hat-switch, labeled "2"</name>
		<desc>center view; toggle tail-wheel lock; cockpit view; reset all trims</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					view.resetView();
				} elsif (mod == 1) {
					i = !getprop("/controls/gear/tailwheel-lock");
					setprop("/controls/gear/tailwheel-lock", i);
					gui.popupTip("Tail Wheel " ~ (i ? "LOCKED" : "UNLOCKED"));
				} elsif (mod == 2) {
					setprop("/sim/current-view/view-number", 0);
					view.resetView();
				} elsif (mod == 3) {
					setprop("/controls/flight/elevator-trim", 0);
					setprop("/controls/flight/aileron-trim", 0);
					setprop("/controls/flight/rudder-trim", 0);
				}
			</script>
		</binding>
	</button>

	<button n="2">
		<name>Left Button below Hat-switch, labeled "3"</name>
		<desc>flaps up [+Ctrl: previous weapon]; gear up; previous active view; previous view</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					if (kbdctrl.getBoolValue())
						controls.weaponSelect(-1);
					else
						controls.flapsDown(-1);
				} elsif (mod == 1) {
					controls.gearDown(-1);
				} elsif (mod == 2) {
					view.stepView(-1, 0);
				} elsif (mod == 3) {
					view.stepView(-1, 1);
				}
			</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						controls.flapsDown(0);
					} elsif (mod == 1) {
						controls.gearDown(0);
					} elsif (mod == 2) {
						#
					} elsif (mod == 3) {
						#
					}
				</script>
			</binding>
		</mod-up>
	</button>

	<button n="3">
		<name>Right Button below Hat-switch, labeled "4"</name>
		<desc>flaps down [+Ctrl: next weapon]; gear down; next active view; next view</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					if (kbdctrl.getBoolValue())
						controls.weaponSelect(1);
					else
						controls.flapsDown(1);
				} elsif (mod == 1) {
					controls.gearDown(1);
				} elsif (mod == 2) {
					view.stepView(1, 0);
				} elsif (mod == 3) {
					view.stepView(1, 1);
				}
			</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						controls.flapsDown(0);
					} elsif (mod == 1) {
						controls.gearDown(0);
					} elsif (mod == 2) {
						#
					} elsif (mod == 3) {
						#
					}
				</script>
			</binding>
		</mod-up>
	</button>

	<button n="4">
		<name>Button left of Hat switch, Labeled "5"</name>
		<desc>brakes left; *; zoom out; *</desc>
		<repeatable type="bool">true</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					if (!left_brake)
						controls.applyBrakes(left_brake = 1, -1);
				} elsif (mod == 1) {
					#
				} elsif (mod == 2) {
					view.increase();
				} elsif (mod == 3) {
					#
				}
			</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						controls.applyBrakes(left_brake = 0, -1);
					} elsif (mod == 1) {
						#
					} elsif (mod == 2) {
						#
					} elsif (mod == 3) {
						#
					}
				</script>
			</binding>
		</mod-up>
	</button>

	<button n="5">
		<name>Button right of Hat switch, Labeled "6"</name>
		<desc>brakes right; *; zoom in; *</desc>
		<repeatable type="bool">true</repeatable>
		<binding>
			<command>nasal</command>
			<script>
				if (mod == 0) {
					if (!right_brake)
						controls.applyBrakes(right_brake = 1, 1);
				} elsif (mod == 1) {
					#
				} elsif (mod == 2) {
					view.decrease();
				} elsif (mod == 3) {
					#
				}
			</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>
					if (mod == 0) {
						controls.applyBrakes(right_brake = 0, 1);
					} elsif (mod == 1) {
						#
					} elsif (mod == 2) {
						#
					} elsif (mod == 3) {
						#
					}
				</script>
			</binding>
		</mod-up>
	</button>


	<!-- ~~~~~~~~~~~~~~~~~~~~~~~~ Modifier Buttons ~~~~~~~~~~~~~~~~~~~~~~~~ -->

	<button n="6">
		<name>F1</name>
		<desc>modifier 1</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(0, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(0, 0)</script>
			</binding>
		</mod-up>
	</button>

	<button n="7">
		<name>F2</name>
		<desc>modifier 2</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(1, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(1, 0)</script>
			</binding>
		</mod-up>
	</button>

	<button n="8">
		<name>F3</name>
		<desc>modifier 1</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(0, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(0, 0)</script>
			</binding>
		</mod-up>
	</button>

	<button n="9">
		<name>F4</name>
		<desc>modifier 2</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(1, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(1, 0)</script>
			</binding>
		</mod-up>
	</button>

	<button n="10">
		<name>Left side ^</name>
		<desc>modifier 3</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(2, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(2, 0)</script>
			</binding>
		</mod-up>
	</button>

	<button n="11">
		<name>Right side ^</name>
		<desc>modifier 3</desc>
		<repeatable type="bool">false</repeatable>
		<binding>
			<command>nasal</command>
			<script>setmodifier(2, 1)</script>
		</binding>
		<mod-up>
			<binding>
				<command>nasal</command>
				<script>setmodifier(2, 0)</script>
			</binding>
		</mod-up>
	</button>

</PropertyList>
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to