4 This is X52.xml, the joystick config file for the Saitek X52
5 USB stick and throttle.
7 This configuration is meant to be suitable for a generic single-engine
10 Here are some of the features of a real aircraft that we would like to
11 implement, and our "preferred" way of assigning them on the X52.
15 Elevator stick fwd/aft
16 Rudder stick twist (or pedals!)
18 Speedbrakes shift T3/T4
19 Pitch trim stick upper hat
20 Rudder trim stick upper hat
21 Aileron trim throttle rocker
24 Mixture throttle lower rotary
25 Propeller RPM throttle thumb slider
26 Carb heat (alt air) T5/T6
27 Cowl Flaps shift T5/T6
28 Fuel tank select **not implemented**
29 Mag switch keyboard "{" and "}"
31 Other important stuff:
32 gear handle up/down T1/T2
33 Overall brakes pinky trigger
34 L/R toe brakes keyboard dot and comma
35 Parking brakes keyboard capital-B
36 Push-to-talk button (A) is a good candidate
38 Timer reset MultiFunc reset
39 Timer -> clock MultiFunc function
40 Autopilot disengage **not implemented**
41 Autopilot go-around **not implemented**
43 Master **not implemented**
44 Radio master **not implemented**
45 Landing lights **not implemented**
46 Rotating beacon **not implemented**
47 Strobes **not implemented**
48 Cabin lights **not implemented**
49 Instrument lights **not implemented**
50 Circuit breakers **not implemented**
52 Alternate static **not implemented**
53 Instruments on/off mouse
54 Instruments tuning mouse or popup dialog
55 Simulator and view control:
56 Pan L/R Tilt Up/Dn throttle lower hat
57 Shift PoV D-shift + throttle lower hat
58 Restore std view (C) button
60 Zoom in D-shift + (B) button
62 =============================================================
64 Here are the Unix axes observed by jsd using js_demo, and Windows axes
65 observed by Satia Lumbar. Mac axes are little more than guesses based
66 on reports of X45 behavior. An "x" means observed to have no effect
67 using js_demo. U/M/W means unix/mac/windows:
69 U/ M/ W Hardware Function Interpretation
70 ======= ================= ==============
71 0/ 0/ 0 Stick yaw +=R Aileron
72 1/ 1/ 1 Stick pitch +=aft Elevator
73 2/ 2/ 2 Throttle +=aft Throttle
74 3/ 5/ 5 Throttle lower rotary +=cw Mixture (fwd = rich)
75 4/ 8/ 8x Throttle upper rotary +=cw [unassigned]
76 5/ 3/ 3 Stick twist +=R Rudder
77 6/ 4/ 4 Throttle thumb slider +=up Prop (fwd = high RPM)
78 7/ 6/ 6 Stick lower hat +=R Pan View Left/Right ... or shift
79 8/ 7/ 7 Stick lower hat +=down Tilt View Up/Down ... or shift
80 9/ 9/ 9x Green mouse +=up [Mouse???]
81 10/10/10x Green mouse +=away [Mouse???]
84 On the Windows platform, the assignment of axes 8, 9, and 10 as
85 given above is only a hint, suggesting how the axes /should/ be
86 assigned, if the lower-level implementation ever gets around to
89 In the meantime, I have maintained cross-platform compatibility by not
90 assigning any critical functions to axes that don't work on the
93 =======================
95 Now for the buttons. Unix button numbers observed by jsd using
96 js_demo. (Others rumored to be identical on Unix/Mac/Windows.)
98 Before 1 Jan 2007, all versions of plib had a bug that affecting bits
99 32 and 33. The C and C++ language spec says that an out-of-range
100 shift (such as shifting a 32-bit word 32 or more places) produces an
101 /undefined/ result. It is really not a good practice to be generating
104 I observe that on /some/ systems, bit #32 creates a conflict with bit
105 #0, and bit #33 creates a conflict with bit #1. That is, they "wrap
106 around" the word boundary. This means that if you roll the gray trim
107 wheel, it fires the gun! If that weren't bad enough, this behavior is
108 not guaranteed from compiler to compiler or from hardware to hardware.
109 Remember, according to the C language spec, an out-of-range shift
110 produces an "undefined" result, so implementers can do anything they
114 Bit Binary Hardware Function Interpretation
115 === ========= ================= ====================
116 0 = 0000 0001 Trigger (see also #14)
118 1 = 0000 0002 FIRE Button (guarded)
120 2 = 0000 0004 (A) Button (should be push-to-talk)
121 3 = 0000 0008 (B) Button Expand field of view (shift: contract)
122 4 = 0000 0010 (C) Button Reset View
123 5 = 0000 0020 Pinky subtrigger Apply brakes
124 6 = 0000 0040 (D) Button D-Shift, modifies other functions
125 7 = 0000 0080 (E) Button
126 8 = 0000 0100 T1 Gear Handle Up
127 9 = 0000 0200 T2 Gear Handle Down
128 10 = 0000 0400 T3 Flaps retract 1 notch (shift: speed brakes extend)
129 11 = 0000 0800 T4 Flaps extend 1 notch (shift: speed brakes retract)
130 12 = 0000 1000 T5 Carb heat on (shift: cowl flaps close)
131 13 = 0000 2000 T6 Carb heat off (shift: cowl flaps open)
132 14 = 0000 4001 More Trigger (==> #0)
133 15 = 0000 8000 Yoke upper hat Fwd Elevator trim
134 16 = 0001 0000 Yoke upper hat R Rudder trim
135 17 = 0002 0000 Yoke upper hat Aft Elevator trim
136 18 = 0004 0000 Yoke upper hat L Rudder trim
137 19 = 0008 0000 Throttle rocker aft
138 20 = 0010 0000 Throttle rocker R Aileron trim
139 21 = 0020 0000 Throttle rocker fwd
140 22 = 0040 0000 Throttle rocker L Aileron trim
141 23 = 0080 0000 Mode Aft (green)
142 24 = 0100 0000 Mode Mid (pink)
143 25 = 0200 0000 Mode Fwd (red)
144 26 = 0400 0000 MultiFunc Function Timer -> clock again
145 27 = 0800 0000 MultiFunc Start/Stop ** Timer start/stop not implemented **
146 28 = 1000 0000 MultiFunc Reset Timer reset
147 29 = 2000 0000 (i) Button
148 30 = 4000 0000 Green mouse click
150 32 = 1 0000 0000 Gray Roller step fwd (see also bit #0)
151 33 = 2 0000 0000 Gray Roller step aft (see also bit #1)
155 *) Note that some joystick configurations specify square-law behavior
156 for some flight control axes (e.g. ailerons and/or rudder). This is
157 very unlike the behavior of flight controls on real aircraft.
159 Aileron authority should be mushy at low airspeeds and crisp at high
160 airspeeds ... but this should be part of the flight dynamics of the
161 aircraft. Building the correct behavior into the control stick
162 configuration is neither possible nor desirable.
165 *) There are some aircraft in the simulator fleet that have very
166 little roll damping and very little yaw damping. (You could also say
167 they have very little damping of the Dutch roll mode, but this is
168 merely a natural consequence of the roll and yaw issues, not really a
171 Such aircraft are vastly easier to fly with auto-coordination turned
172 on. In my opinion, you want auto-coordination on for flying an ILS
173 partial panel, i.e. no DG and no AI.
175 For a crosswind landing, you need to have auto-coordination turned off.
176 That's why the switch to do that is on the yoke.
178 *) This configuration does not bind the parking brake to any button on
179 the joystick (or throttle). Using the keyboard (shift-B) seems
180 entirely satisfactory and more realistic than putting the /parking/
181 brake button on the stick.
183 *) In general, he HOTAS idea (hands on throttle and stick) should
184 apply to things you need /in flight/.
190 <name>Saitek X52</name>
191 <name>Saitek X52 Flight Controller USB</name>
192 <name>Saitek X52 Flight Controller</name>
193 <name>Saitek X52 Flight Control Stick </name>
194 <name>Saitek X52 Flight Stick (USB)</name>
195 <name>Saitek X52 Flight Control System</name>
196 <name>Saitek Saitek X52</name>
197 <name>Saitek Saitek X52 Flight Stick (USB)</name>
198 <name>Saitek Saitek X52 Flight Control Stick</name>
199 <name>Saitek Saitek X52 Flight Control System</name>
201 <axis> <!-- 0/0/0 -->
209 <command>property-scale</command>
210 <property>/controls/flight/aileron</property>
214 <axis> <!-- 1/1/1 -->
215 <desc>Elevator</desc>
222 <command>property-scale</command>
223 <property>/controls/flight/elevator</property>
224 <factor type="double">-1.0</factor>
228 <axis> <!-- 2/2/2 -->
229 <desc>Throttle</desc>
236 <command>nasal</command>
237 <script>controls.throttleAxis()</script>
241 <axis> <!-- 3/5/5 -->
249 <command>nasal</command>
250 <script>controls.mixtureAxis(-1)</script>
254 <!-- Alternate Prop RPM :: throttle upper rotary -->
255 <axis> <!-- 4/8/8 -->
256 <desc>unassigned (was: Propeller RPM)</desc>
263 <command>nasal</command>
265 ####controls.propellerAxis(-1)
270 <!-- Rudder :: stick twist -->
271 <axis> <!-- 5/3/3 -->
279 <command>property-scale</command>
280 <property>/controls/flight/rudder</property>
284 <!-- Propeller RPM :: throttle thumb slider -->
285 <axis> <!-- 6/4/4 -->
286 <desc>Propeller RPM</desc>
293 <command>nasal</command>
294 <script>controls.propellerAxis(-1)</script>
299 <!-- View Direction :: stick lower hat -->
300 <axis> <!-- 7/6/6 -->
301 <desc>View Pan Left/Right (D-shift: move PoV)</desc>
308 <repeatable>true</repeatable>
310 <command>nasal</command>
312 if (getprop("/sim/gui/d-button")){
313 setprop("/sim/current-view/x-offset-m",
314 -0.01 + getprop("/sim/current-view/x-offset-m"));
322 <repeatable>true</repeatable>
324 <command>nasal</command>
326 if (getprop("/sim/gui/d-button")){
327 setprop("/sim/current-view/x-offset-m",
328 0.01 + getprop("/sim/current-view/x-offset-m"));
337 <axis> <!-- 8/7/7 -->
338 <desc>View Tilt Up/Down (D-shift: move PoV)</desc>
345 <repeatable>true</repeatable>
347 <command>nasal</command>
349 if (getprop("/sim/gui/d-button")){
350 setprop("/sim/current-view/y-offset-m",
351 0.01 + getprop("/sim/current-view/y-offset-m"));
359 <repeatable>true</repeatable>
361 <command>nasal</command>
363 if (getprop("/sim/gui/d-button")){
364 setprop("/sim/current-view/y-offset-m",
365 -0.01 + getprop("/sim/current-view/y-offset-m"));
367 view.panViewPitch(-1)
375 <!-- End of axes; now on to buttons -->
378 <desc>(FIRE) : Auto-Coordination off (D-shift: on)</desc>
380 <command>nasal</command>
382 setprop("/controls/flight/auto-coordination", ! !getprop("/sim/gui/d-button"));
389 <desc>(B) : Zoom out i.e. increase field of view (D-shift: zoom in)</desc>
390 <repeatable type="bool">true</repeatable>
392 <command>nasal</command>
394 if ( getprop("/sim/gui/d-button") ) {
395 view.decrease(0.5) # zoom in
397 view.increase(0.5) # zoom out
404 <desc>(C) : Reset View</desc>
406 <command>nasal</command>
408 view.resetView(); # only resets tilt/pan/zoom:
409 # must reset x/y/z view point separately
410 vn = getprop("/sim/current-view/view-number");
411 conf = sprintf("/sim/view[%d]/config", vn);
412 foreach (parm ; ["x-offset-m", "y-offset-m", "z-offset-m"]) {
413 setprop("/sim/current-view/", parm, getprop(conf, parm));
419 <!-- Main brakes (not parking brakes) :: pinky subtrigger -->
421 <desc>(Pinky) : Brakes</desc>
423 <command>nasal</command>
424 <script>controls.applyBrakes(1)</script>
428 <command>nasal</command>
429 <script>controls.applyBrakes(0)</script>
434 <!-- Shift :: (D) button -->
436 <desc>(D) : Shift Key</desc>
438 <command>nasal</command>
440 setprop("/sim/gui/d-button", 1);
445 <command>nasal</command>
447 setprop("/sim/gui/d-button", 0);
454 <!-- gear handle up/down :: button T1/T2 -->
456 <desc>(T1) : Landing Gear Handle Up</desc>
458 <command>nasal</command>
460 controls.gearDown(-1)
465 <desc>(T2) : Landing Gear Handle Down</desc>
467 <command>nasal</command>
475 <!-- Pitch trim :: stick upper hat Up/Dn -->
477 <desc>Elevator trim down</desc>
478 <repeatable type="bool">true</repeatable>
480 <command>nasal</command>
481 <script>controls.elevatorTrim(0.6)</script>
485 <desc>Elevator trim up</desc>
486 <repeatable type="bool">true</repeatable>
488 <command>nasal</command>
489 <script>controls.elevatorTrim(-0.6)</script>
493 <!-- Rudder trim :: stick upper hat L/R -->
495 <desc>(Throttle Rocker) : Rudder trim right</desc>
496 <repeatable type="bool">true</repeatable>
498 <command>nasal</command>
499 <script>controls.rudderTrim(1)</script>
503 <desc>(Throttle Rocker) : Rudder trim left</desc>
504 <repeatable type="bool">true</repeatable>
506 <command>nasal</command>
507 <script>controls.rudderTrim(-1)</script>
511 <!-- Flaps (shift: Speed Brakes) :: T3/T4 -->
513 <desc>(T3) : Decrease flaps (shift: Speed Brakes extend)</desc>
515 <command>nasal</command>
517 if ( getprop("/sim/gui/d-button") ) {
518 setprop("/controls/flight/speedbrake", 1);
520 controls.flapsDown(-1)
526 <command>nasal</command>
528 if ( getprop("/sim/gui/d-button") ) {
531 controls.flapsDown(0)
538 <desc>(T4) : Increase flaps (shift: Speed Brakes retract)</desc>
540 <command>nasal</command>
542 if ( getprop("/sim/gui/d-button") ) {
543 setprop("/controls/flight/speedbrake", 0);
545 controls.flapsDown(1)
551 <command>nasal</command>
553 if ( getprop("/sim/gui/d-button") ) {
556 controls.flapsDown(0)
563 <!-- Carb Heat (shift: Cowl Flaps) :: T6/T5 -->
565 <desc>(T5) : Carb Heat On (shift: Cowl Flaps Close)</desc>
567 <command>nasal</command>
569 if ( getprop("/sim/gui/d-button") ) {
570 props.setAll("/controls/engines/engine", "cowl-flaps-norm", 1);
572 props.setAll("/controls/engines/engine", "carb-heat", 0);
578 <desc>(T6) : Carb Heat Off (shift: Cowl Flaps Open)</desc>
580 <command>nasal</command>
582 if ( getprop("/sim/gui/d-button") ) {
583 props.setAll("/controls/engines/engine", "cowl-flaps-norm", 0);
585 props.setAll("/controls/engines/engine", "carb-heat", 1);
591 <!-- Aileron trim :: throttle rocker -->
593 <desc>Aileron trim right</desc>
594 <repeatable type="bool">true</repeatable>
596 <command>nasal</command>
597 <script>controls.aileronTrim(0.5)</script>
601 <desc>Aileron trim left</desc>
602 <repeatable type="bool">true</repeatable>
604 <command>nasal</command>
605 <script>controls.aileronTrim(-0.5)</script>
610 <!-- Mode roller switch (buttons 23-25). -->
611 <!-- Just put it in the property tree, -->
612 <!-- in case somebody wants to look at it. -->
616 <command>nasal</command>
618 setprop("/input/joysticks/js/saitek-x52-mode",1)
625 <command>nasal</command>
627 setprop("/input/joysticks/js/saitek-x52-mode",2)
634 <command>nasal</command>
636 setprop("/input/joysticks/js/saitek-x52-mode",3)
642 <desc>(MFD Func) : Stopwatch timer becomes clock again</desc>
644 <command>nasal</command>
646 props.globals.getNode("/instrumentation/clock/offset-sec", 1).setValue(0);
652 <desc>(MFD Reset) : Stopwatch timer reset</desc>
654 <command>nasal</command>
656 <!-- Note that the "indicated-sec" variable is a large number,
657 probably seconds since midnight ... *not* modulo 60. -->
658 ttt = props.globals.getNode("/instrumentation/clock/indicated-sec", 1).getValue();
659 node = props.globals.getNode("/instrumentation/clock/offset-sec", 1);
660 off = node.getValue();
661 node.setValue(off-ttt);
666 <!-- (i) button :: unbound key -->
667 <!-- just put it in the property tree -->
671 <command>nasal</command>
673 setprop("/input/joysticks/js/saitek-x52-i",1)
677 <command>nasal</command>
679 setprop("/input/joysticks/js/saitek-x52-i",0)
685 <!-- Parking brake :: unbound function -->
687 <desc>Toggle parking brake on or off</desc>
689 <command>property-toggle</command>
690 <property>/controls/gear/brake-parking</property>