<?xml version="1.0" ?>
<!-- $Id$ -->
<!-- Saitek X36F + X35T binding.

  Copyright (C) 2005-2007  Anders Gidenstam  (anders(at)gidenstam.org)
  This file is released under the GPL license.
-->
<!--
  Remember to tell the joystick driver that it is a full CHF stick:
  On GNU/Linux this can be done in this way:

  % modprobe analog js=0x7ff,0x7ff

-->
<PropertyList>

 <!-- NOTE: The X36 is a game port device so it may get a generic name. -->
 <name>Saitek X36</name>
 <name>Analog 4-axis 6-button 2-hat CHF joystick</name>

 <data>
  <view-mode type="int">0</view-mode>
  <old-heading-offset type="double">0</old-heading-offset>
  <old-pitch-offset type="double">0</old-pitch-offset>
  <old-field-of-view type="double">0</old-field-of-view>
  <quick-view-active type="int">0</quick-view-active>
 </data>

 <nasal>
  <script>
   <![CDATA[
     self = cmdarg().getParent();
     data = self.getNode("data");
     view_mode           = data.getNode("view-mode");
     old_heading_offset  = data.getNode("old-heading-offset");
     old_pitch_offset    = data.getNode("old-pitch-offset");
     old_field_of_view   = data.getNode("old-field-of-view");
     quick_view_active   = data.getNode("quick-view-active");

     heading_offset      =
       props.globals.getNode("/sim/current-view/heading-offset-deg", 1);
     pitch_offset        =
       props.globals.getNode("/sim/current-view/pitch-offset-deg", 1);
     goal_heading_offset =
       props.globals.getNode("/sim/current-view/goal-heading-offset-deg", 1);
     goal_pitch_offset   =
       props.globals.getNode("/sim/current-view/goal-pitch-offset-deg", 1);

     kbdshift = props.globals.getNode("/devices/status/keyboard/shift", 1);
     kbdctrl  = props.globals.getNode("/devices/status/keyboard/ctrl", 1);
     kbdalt   = props.globals.getNode("/devices/status/keyboard/alt", 1);

     quick_view = func {
       dir = arg[0];
       if (dir == 0) {
         quick_view_active.setIntValue(0);
         goal_heading_offset.setDoubleValue
           (old_heading_offset.getValue());
         goal_pitch_offset.setDoubleValue(old_pitch_offset.getValue());
         view.fovProp.setDoubleValue(old_field_of_view.getValue());
       } else {
         if (quick_view_active.getValue() == 0) {
           quick_view_active.setIntValue(1);
           old_heading_offset.setDoubleValue(heading_offset.getValue());
           old_pitch_offset.setDoubleValue(pitch_offset.getValue());
           old_field_of_view.setDoubleValue(view.fovProp.getValue());

           if (dir == 1) {
             goal_heading_offset.setDoubleValue
               (getprop("/sim/view/config/left-direction-deg"));
             goal_pitch_offset.setDoubleValue
               (getprop("/sim/view/config/pitch-offset-deg"));
             view.fovProp.setDoubleValue
               (getprop("/sim/view/config/default-field-of-view-deg"));
           } if (dir == 2) {
             goal_heading_offset.setDoubleValue
               (getprop("/sim/view/config/right-direction-deg"));
             goal_pitch_offset.setDoubleValue
               (getprop("/sim/view/config/pitch-offset-deg"));
             view.fovProp.setDoubleValue
               (getprop("/sim/view/config/default-field-of-view-deg"));
           } if (dir == 3) {
             goal_heading_offset.setDoubleValue
               (getprop("/sim/view/config/front-direction-deg"));
             goal_pitch_offset.setDoubleValue
               (getprop("/sim/view/config/pitch-offset-deg"));
             view.fovProp.setDoubleValue
               (getprop("/sim/view/config/default-field-of-view-deg"));
           } if (dir == 4) {
             goal_heading_offset.setDoubleValue
               (getprop("/sim/view/config/back-direction-deg"));
             goal_pitch_offset.setDoubleValue
               (getprop("/sim/view/config/pitch-offset-deg"));
             view.fovProp.setDoubleValue
               (getprop("/sim/view/config/default-field-of-view-deg"));
           }
         }
       }
     }
   ]]>
  </script>
 </nasal>

 <!-- Analog axis 0. Aileron -->
 <axis n="0">
  <desc>aileron</desc>
  <binding>
   <command>property-scale</command>
   <property>/controls/flight/aileron</property>
   <dead-band type="double">0.0</dead-band>
   <offset type="double">0.0</offset>
   <squared type="bool">true</squared>
  </binding>
 </axis>

 <!-- Analog axis 1. Elevator -->
 <axis n="1">
  <desc>elevator</desc>
  <binding>
   <command>property-scale</command>
   <property>/controls/flight/elevator</property>
   <dead-band type="double">0.0</dead-band>
   <offset type="double">0.0</offset>
   <factor type="double">-1.0</factor>
   <squared type="bool">true</squared>
  </binding>
 </axis>

 <!-- Analog axis 3. Rudder -->
 <!-- NOTE: This axis is tweaked due to faulty hardware.
            The standard case should be offset=0, factor=1.
 -->
 <axis n="3">
  <desc>rudder</desc>
  <binding>
   <command>property-scale</command>
   <property>/controls/flight/rudder</property>
   <dead-band type="double">0.030</dead-band>
   <offset type="double">0.1</offset>
   <factor type="double">0.9</factor>
  </binding>
 </axis>

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

 <!-- Axis 4. Hat 1 -->
 <axis n="4">
  <name>Right hat left/right</name>
  <desc>
   view-mode 0: horizontal view pan, view-mode 1: quick view left/right
  </desc>
  <low>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
     <![CDATA[
       #print("X36.xml: Axis 4, Hat 1: low!");
       m = view_mode.getValue();
       if (m == 0) {
         view.panViewDir(0.5);
       } if (m == 1) {
         quick_view(1);
       }
     ]]>
    </script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>
        #print("X36.xml: Axis 4, Hat 1: low released!");
        m = view_mode.getValue();
        if (m == 1) {
          quick_view(0);
        }
     </script>
    </binding>
   </mod-up>
  </low>
  <high>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
     <![CDATA[
       #print("X36.xml: Axis 4, Hat 1: high!");
       m = view_mode.getValue();
       if (m == 0) {
         view.panViewDir(-0.5);
       } if (m == 1) {
         quick_view(2);
       }
     ]]>
    </script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>
        #print("X36.xml: Axis 4, Hat 1: low released!");
        m = view_mode.getValue();
        if (m == 1) {
          quick_view(0);
        }
     </script>
    </binding>
   </mod-up>
  </high>
 </axis>

 <!-- Axis 5. Hat 1 -->
 <axis n="5">
  <name>Right hat up/down</name>
  <desc>
   view-mode 0: vertical view pan, view-mode 1: quick view front/view reset
  </desc>
  <low>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
     <![CDATA[
       #print("X36.xml: Axis 5, Hat 1: low!");
       m = view_mode.getValue();
       if (m == 0) {
         view.panViewPitch(0.5);
       } if (m == 1) {
         quick_view(3);
       }
     ]]>
    </script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>
        #print("X36.xml: Axis 4, Hat 1: low released!");
        m = view_mode.getValue();
        if (m == 1) {
          quick_view(0);
        }
     </script>
    </binding>
   </mod-up>
  </low>
  <high>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
     <![CDATA[
       #print("X36.xml: Axis 5, Hat 1: low!");
       m = view_mode.getValue();
       if (m == 0) {
         view.panViewPitch(-0.5);
       } if (m == 1) {
         view.resetView();
         #quick_view(4);
       }
     ]]>
    </script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>
        #print("X36.xml: Axis 4, Hat 1: low released!");
        m = view_mode.getValue();
        if (m == 1) {
          #quick_view(0);
        }
     </script>
    </binding>
   </mod-up>
  </high>
 </axis>

 <!-- Axis 6. Hat 2.
     NOTE: The axes of hat 2 are messed up on the X36.
           Up - Down    := Axis 6.low  - Axis 7.high
           Left - Right := Axis 6.high - Axis 7.low
 -->
 <axis n="6">
  <name>Left hat up/down</name>
  <desc>elevator trim (hat up/down)</desc>
  <low>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
       #print("X36.xml: Axis 6, Hat 1: low!");
       controls.elevatorTrim(-1)
    </script>
   </binding>
  </low>
  <high>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
       #print("X36.xml: Axis 6, Hat 1: high!");
       view.increase()
    </script>
   </binding>
  </high>
 </axis>

 <!-- Axis 7. Hat 2.  -->
 <axis n="7">
  <name>Left hat left/right</name>
  <desc>Zoom out/in (hat left/right)</desc>
  <low>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
       #print("X36.xml: Axis 7, Hat 1: low!");
       view.decrease()
    </script>
   </binding>
  </low>
  <high>
   <repeatable type="bool">true</repeatable>
   <binding>
    <command>nasal</command>
    <script>
       #print("X36.xml: Axis 7, Hat 1: high!");
       controls.elevatorTrim(1)
    </script>
   </binding>
  </high>
 </axis>

 <!-- Button: Trigger -->
 <button n="0">
  <name>Trigger</name>
  <desc>brakes, +Shift: Toggle parking brake</desc>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 0 pressed!");
      if (kbdshift.getBoolValue()) {
        controls.applyParkingBrake(1);
      } else {
       controls.applyBrakes(1);
      }
   </script>
  </binding>
  <mod-up>
   <binding>
    <command>nasal</command>
    <script>
       controls.applyBrakes(0);
    </script>
   </binding>
  </mod-up>
 </button>

 <!-- Button: Fire C -->
 <button n="1">
  <name>Fire C</name>
  <desc>cycle views</desc>
  <repeatable>false</repeatable>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 1 pressed!");
      view.stepView(1)
   </script>
  </binding>
 </button>

 <!-- Button: A -->
 <button n="2">
  <name>A</name>
  <desc>left brake</desc>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 2 pressed!");
      controls.applyBrakes(1, -1);
   </script>
  </binding>
  <mod-up>
   <binding>
    <command>nasal</command>
    <script>
       controls.applyBrakes(0, -1);
    </script>
   </binding>
  </mod-up>
 </button>

 <!-- Button: B -->
 <button n="3">
  <name>B</name>
  <desc>right brake</desc>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 3 pressed!");
      controls.applyBrakes(1, 1);
   </script>
  </binding>
  <mod-up>
   <binding>
    <command>nasal</command>
    <script>
       controls.applyBrakes(0, 1);
    </script>
   </binding>
  </mod-up>
 </button>

 <!-- Button: Launch -->
 <button n="4">
  <name>Launch</name>
  <desc>toggle view mode</desc>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 4 pressed!");
      if (view_mode.getValue() == 0) {
        view_mode.setIntValue(1);
      } else {
        view_mode.setIntValue(0);
      }
   </script>
  </binding>
 </button>

 <!-- Button: F.lock -->
 <button n="5">
  <name>F.lock</name>
  <desc>disarm speed brakes, +Shift: deploy speed brakes</desc>
  <binding>
   <command>nasal</command>
   <script>
      #print("X36.xml: Button 5 pressed!");
      var p = "/controls/flight/speedbrake";
      if (kbdshift.getBoolValue()) {
        setprop(p, 1.0);
      } else {
        setprop(p, 0.0);
      }
   </script>
  </binding>
 </button>

</PropertyList>
<!--
 * Overrides tab width for this buffer in Emacs so the tab width is reasonable.
 * This must remain at the end of the file.
 * ===========================================================================
 * Local variables:
 * tab-width: 1
 * indent-tabs-mode: nil
 * End:
-->