]> git.mxchange.org Git - flightgear.git/blobdiff - src/Network/atc610x.cxx
Moved random ground cover object management code (userdata.[ch]xx) over
[flightgear.git] / src / Network / atc610x.cxx
index e70c0eff469c741a7787bf60a41d0f1b1e43c757..70cf20cbcc3692b8d81c0f4eb57ebf38092adfff 100644 (file)
@@ -43,8 +43,8 @@
 #include <simgear/debug/logstream.hxx>
 #include <simgear/io/iochannel.hxx>
 #include <simgear/math/sg_types.hxx>
-#include <simgear/misc/props.hxx>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
 
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
@@ -53,6 +53,7 @@
 
 SG_USING_STD(string);
 
+
 // Lock the ATC 610 hardware
 static int ATC610xLock( int fd ) {
     // rewind
@@ -323,6 +324,7 @@ bool FGATC610x::open() {
 
     bool home = false;
     int timeout = 900;          // about 30 seconds
+    timeout = 0;
     while ( ! home && timeout > 0 ) {
         if ( timeout % 150 == 0 ) {
             SG_LOG( SG_IO, SG_INFO, "waiting for compass = " << timeout );
@@ -392,16 +394,22 @@ bool FGATC610x::open() {
     // Connect up to property values
     /////////////////////////////////////////////////////////////////////
 
-    mag_compass = fgGetNode( "/steam/mag-compass-deg", true );
+    mag_compass = fgGetNode( "/instrumentation/magnetic-compass/indicated-heading-deg", true );
 
-    dme_min = fgGetNode( "/radios/dme/ete-min", true );
-    dme_kt = fgGetNode( "/radios/dme/speed-kt", true );
-    dme_nm = fgGetNode( "/radios/dme/distance-nm", true );
+    dme_min = fgGetNode( "/instrumentation/dme/indicated-time-min", true );
+    dme_kt = fgGetNode( "/instrumentation/dme/indicated-ground-speed-kt",
+                        true );
+    dme_nm = fgGetNode( "/instrumentation/dme/indicated-distance-nm", true );
+    dme_in_range = fgGetNode( "/instrumentation/dme/in-range", true );
 
-    navcom1_bus_power = fgGetNode( "/systems/electrical/outputs/navcomm[0]",
+    adf_bus_power = fgGetNode( "/systems/electrical/outputs/adf", true );
+    dme_bus_power = fgGetNode( "/systems/electrical/outputs/dme", true );
+    navcom1_bus_power = fgGetNode( "/systems/electrical/outputs/navcom[0]",
                                    true );
-    navcom2_bus_power = fgGetNode( "/systems/electrical/outputs/navcomm[1]",
+    navcom2_bus_power = fgGetNode( "/systems/electrical/outputs/navcom[1]",
                                    true );
+    xpdr_bus_power = fgGetNode( "/systems/electrical/outputs/transponder",
+                                 true );
 
     navcom1_power_btn = fgGetNode( "/radios/comm[0]/inputs/power-btn", true );
     navcom2_power_btn = fgGetNode( "/radios/comm[1]/inputs/power-btn", true );
@@ -417,12 +425,14 @@ bool FGATC610x::open() {
     nav1_freq = fgGetNode( "/radios/nav[0]/frequencies/selected-mhz", true );
     nav1_stby_freq
        = fgGetNode( "/radios/nav[0]/frequencies/standby-mhz", true );
+    nav1_obs = fgGetNode( "/radios/nav[0]/radials/selected-deg", true );
 
     nav2_freq = fgGetNode( "/radios/nav[1]/frequencies/selected-mhz", true );
     nav2_stby_freq
        = fgGetNode( "/radios/nav[1]/frequencies/standby-mhz", true );
+    nav2_obs = fgGetNode( "/radios/nav[1]/radials/selected-deg", true );
 
-    adf_power = fgGetNode( "/radios/kr-87/inputs/power-btn", true );
+    adf_power_btn = fgGetNode( "/radios/kr-87/inputs/power-btn", true );
     adf_vol = fgGetNode( "/radios/kr-87/inputs/volume", true );
     adf_adf_btn = fgGetNode( "/radios/kr-87/inputs/adf-btn", true );
     adf_bfo_btn = fgGetNode( "/radios/kr-87/inputs/bfo-btn", true );
@@ -460,33 +470,63 @@ bool FGATC610x::open() {
     xpdr_sby_ann = fgGetNode( "/radios/kt-70/annunciators/sby", true );
     xpdr_reply_ann = fgGetNode( "/radios/kt-70/annunciators/reply", true );
 
-    elevator_center = fgGetNode( "/input/atc610x/elevator/center", 0 );
-    elevator_min = fgGetNode( "/input/atc610x/elevator/min", 0 );
-    elevator_max = fgGetNode( "/input/atc610x/elevator/max", 0 );
+    ati_bird
+      = fgGetNode( "/instrumentation/attitude-indicator/horizon-offset-deg",
+                  true );
+    alt_press = fgGetNode( "/instrumentation/altimeter/setting-inhg", true );
+    adf_hdg = fgGetNode( "/radios/kr-87/inputs/rotation-deg", true );
+
+    elevator_center = fgGetNode( "/input/atc610x/elevator/center", true );
+    elevator_min = fgGetNode( "/input/atc610x/elevator/min", true );
+    elevator_max = fgGetNode( "/input/atc610x/elevator/max", true );
+
+    ailerons_center = fgGetNode( "/input/atc610x/ailerons/center", true );
+    ailerons_min = fgGetNode( "/input/atc610x/ailerons/min", true );
+    ailerons_max = fgGetNode( "/input/atc610x/ailerons/max", true );
+
+    rudder_center = fgGetNode( "/input/atc610x/rudder/center", true );
+    rudder_min = fgGetNode( "/input/atc610x/rudder/min", true );
+    rudder_max = fgGetNode( "/input/atc610x/rudder/max", true );
 
-    ailerons_center = fgGetNode( "/input/atc610x/ailerons/center", 0 );
-    ailerons_min = fgGetNode( "/input/atc610x/ailerons/min", 0 );
-    ailerons_max = fgGetNode( "/input/atc610x/ailerons/max", 0 );
+    brake_left_min = fgGetNode( "/input/atc610x/brake-left/min", true );
+    brake_left_max = fgGetNode( "/input/atc610x/brake-left/max", true );
 
-    rudder_center = fgGetNode( "/input/atc610x/rudder/center", 0 );
-    rudder_min = fgGetNode( "/input/atc610x/rudder/min", 0 );
-    rudder_max = fgGetNode( "/input/atc610x/rudder/max", 0 );
+    brake_right_min = fgGetNode( "/input/atc610x/brake-right/min", true );
+    brake_right_max = fgGetNode( "/input/atc610x/brake-right/max", true );
 
-    throttle_min = fgGetNode( "/input/atc610x/throttle/min", 0 );
-    throttle_max = fgGetNode( "/input/atc610x/throttle/max", 0 );
+    throttle_min = fgGetNode( "/input/atc610x/throttle/min", true );
+    throttle_max = fgGetNode( "/input/atc610x/throttle/max", true );
 
-    mixture_min = fgGetNode( "/input/atc610x/mixture/min", 0 );
-    mixture_max = fgGetNode( "/input/atc610x/mixture/max", 0 );
+    mixture_min = fgGetNode( "/input/atc610x/mixture/min", true );
+    mixture_max = fgGetNode( "/input/atc610x/mixture/max", true );
 
-    trim_center = fgGetNode( "/input/atc610x/trim/center", 0 );
-    trim_min = fgGetNode( "/input/atc610x/trim/min", 0 );
-    trim_max = fgGetNode( "/input/atc610x/trim/max", 0 );
+    trim_center = fgGetNode( "/input/atc610x/trim/center", true );
+    trim_min = fgGetNode( "/input/atc610x/trim/min", true );
+    trim_max = fgGetNode( "/input/atc610x/trim/max", true );
 
-    nav1vol_min = fgGetNode( "/input/atc610x/nav1vol/min", 0 );
-    nav1vol_max = fgGetNode( "/input/atc610x/nav1vol/max", 0 );
+    nav1vol_min = fgGetNode( "/input/atc610x/nav1vol/min", true );
+    nav1vol_max = fgGetNode( "/input/atc610x/nav1vol/max", true );
 
-    nav2vol_min = fgGetNode( "/input/atc610x/nav2vol/min", 0 );
-    nav2vol_max = fgGetNode( "/input/atc610x/nav2vol/max", 0 );
+    nav2vol_min = fgGetNode( "/input/atc610x/nav2vol/min", true );
+    nav2vol_max = fgGetNode( "/input/atc610x/nav2vol/max", true );
+
+    comm1_servicable = fgGetNode( "/instrumentation/comm[0]/servicable", true );
+    comm2_servicable = fgGetNode( "/instrumentation/comm[1]/servicable", true );
+    nav1_servicable = fgGetNode( "/instrumentation/nav[0]/servicable", true );
+    nav2_servicable = fgGetNode( "/instrumentation/nav[1]/servicable", true );
+    adf_servicable = fgGetNode( "/instrumentation/adf/servicable", true );
+    xpdr_servicable = fgGetNode( "/instrumentation/transponder/servicable",
+                                 true );
+    dme_servicable = fgGetNode( "/instrumentation/dme/servicable", true );
+
+    // default to having everything servicable
+    comm1_servicable->setBoolValue( true );
+    comm2_servicable->setBoolValue( true );
+    nav1_servicable->setBoolValue( true );
+    nav2_servicable->setBoolValue( true );
+    adf_servicable->setBoolValue( true );
+    xpdr_servicable->setBoolValue( true );
+    dme_servicable->setBoolValue( true );
 
     return true;
 }
@@ -496,11 +536,6 @@ bool FGATC610x::open() {
 // Read analog inputs
 /////////////////////////////////////////////////////////////////////
 
-#define ATC_AILERON_CENTER 535
-#define ATC_ELEVATOR_TRIM_CENTER 512
-#define ATC_ELEVATOR_CENTER 543
-#define ATC_RUDDER_CENTER 519
-
 // scale a number between min and max (with center defined) to a scale
 // from -1.0 to 1.0
 static double scale( int center, int min, int max, int value ) {
@@ -543,6 +578,115 @@ static double scale( int min, int max, int value ) {
 }
 
 
+static int tony_magic( int raw, int obs[3] ) {
+    int result = 0;
+
+    obs[0] = raw;
+
+    if ( obs[1] < 30 ) {
+        if ( obs[2] >= 68 && obs[2] < 480 ) {
+            result = -6;
+        } else if ( obs[2] >= 480 ) {
+            result = 6;
+        }
+        obs[2] = obs[1];
+        obs[1] = obs[0];
+    } else if ( obs[1] < 68 ) {
+        // do nothing
+        obs[1] = obs[0];
+    } else if ( obs[2] < 30 ) {
+        if ( obs[1] >= 68 && obs[1] < 480 ) {
+            result = 6;
+           obs[2] = obs[1];
+           obs[1] = obs[0];
+        } else if ( obs[1] >= 480 ) {
+           result = -6;
+            if ( obs[0] < obs[1] ) {
+               obs[2] = obs[1];
+               obs[1] = obs[0];
+           } else {
+               obs[2] = obs[0];
+               obs[1] = obs[0];
+           }
+        }
+    } else if ( obs[1] > 980 ) {
+        if ( obs[2] <= 956 && obs[2] > 480 ) {
+            result = 6;
+        } else if ( obs[2] <= 480 ) {
+            result = -6;
+        }
+        obs[2] = obs[1];
+        obs[1] = obs[0];
+    } else if ( obs[1] > 956 ) {
+        // do nothing
+        obs[1] = obs[0];
+    } else if ( obs[2] > 980 ) {
+        if ( obs[1] <= 956 && obs[1] > 480 ) {
+            result = -6;
+           obs[2] = obs[1];
+           obs[1] = obs[0];
+        } else if ( obs[1] <= 480 ) {
+           result = 6;
+            if ( obs[0] > obs[1] ) {
+               obs[2] = obs[1];
+               obs[1] = obs[0];
+           } else {
+               obs[2] = obs[0];
+               obs[1] = obs[0];
+           }
+        }
+    } else {
+        if ( obs[1] < 480 && obs[2] > 480 ) {
+           // crossed gap going up
+           if ( obs[0] < obs[1] ) {
+               // caught a bogus intermediate value coming out of the gap
+               obs[1] = obs[0];
+           }
+       } else if ( obs[1] > 480 && obs[2] < 480 ) {
+           // crossed gap going down
+           if ( obs[0] > obs[1] ) {
+               // caught a bogus intermediate value coming out of the gap
+             obs[1] = obs[0];
+           }
+       } else if ( obs[0] > 480 && obs[1] < 480 && obs[2] < 480 ) {
+            // crossed the gap going down
+           if ( obs[1] > obs[2] ) {
+               // caught a bogus intermediate value coming out of the gap
+               obs[1] = obs[2];
+           }
+       } else if ( obs[0] < 480 && obs[1] > 480 && obs[2] > 480 ) {
+            // crossed the gap going up
+           if ( obs[1] < obs[2] ) {
+               // caught a bogus intermediate value coming out of the gap
+               obs[1] = obs[2];
+           }
+       }
+        result = obs[1] - obs[2];
+        if ( abs(result) > 400 ) {
+            // ignore
+            result = 0;
+        }
+        obs[2] = obs[1];
+        obs[1] = obs[0];
+    }
+
+    // cout << " result = " << result << endl;
+    if ( result < -500 ) { result += 1024; }
+    if ( result > 500 ) { result -= 1024; }
+
+    return result;
+}
+
+
+static double instr_pot_filter( double ave, double val ) {
+    if ( fabs(ave - val) < 400 || fabs(val) < fabs(ave) ) {
+        return 0.5 * ave + 0.5 * val;
+    } else {
+        return ave;
+    }
+}
+
+
 bool FGATC610x::do_analog_in() {
     // Read raw data in byte form
     ATC610xReadAnalogInputs( analog_in_fd, analog_in_bytes );
@@ -557,44 +701,54 @@ bool FGATC610x::do_analog_in() {
        // printf("%04d ", value );
     }
 
-    float tmp, tmp1, tmp2;
+    float tmp;
 
     // aileron
     tmp = scale( ailerons_center->getIntValue(), ailerons_min->getIntValue(),
                  ailerons_max->getIntValue(), analog_in_data[0] );
-    fgSetFloat( "/controls/aileron", tmp );
+    fgSetFloat( "/controls/flight/aileron", tmp );
     // cout << "aileron = " << analog_in_data[0] << " = " << tmp;
-
     // elevator
     tmp = -scale( elevator_center->getIntValue(), elevator_min->getIntValue(),
                   elevator_max->getIntValue(), analog_in_data[5] );
-    fgSetFloat( "/controls/elevator", tmp );
+    fgSetFloat( "/controls/flight/elevator", tmp * 0.5 );
     // cout << "trim = " << analog_in_data[4] << " = " << tmp;
 
     // elevator trim
     tmp = scale( trim_center->getIntValue(), trim_min->getIntValue(),
                  trim_max->getIntValue(), analog_in_data[4] );
-    fgSetFloat( "/controls/elevator-trim", tmp );
+    fgSetFloat( "/controls/flight/elevator-trim", tmp );
     // cout << " elev = " << analog_in_data[5] << " = " << tmp << endl;
 
     // mixture
     tmp = scale( mixture_min->getIntValue(), mixture_max->getIntValue(),
-                 analog_in_data[7] );
-    fgSetFloat( "/controls/mixture[0]", tmp );
-    fgSetFloat( "/controls/mixture[1]", tmp );
+                 analog_in_data[6] );
+    fgSetFloat( "/controls/engines/engine[0]/mixture", tmp );
+    fgSetFloat( "/controls/engines/engine[1]/mixture", tmp );
 
     // throttle
-    tmp = scale( mixture_min->getIntValue(), mixture_max->getIntValue(),
+    tmp = scale( throttle_min->getIntValue(), throttle_max->getIntValue(),
                  analog_in_data[8] );
-    fgSetFloat( "/controls/throttle[0]", tmp );
-    fgSetFloat( "/controls/throttle[1]", tmp );
-
-#if 0
-    // rudder
-    tmp = scale( rudder_center->getIntValue(), rudder_min->getIntValue(),
-                 rudder_max->getIntValue(), analog_in_data[10] );
-    fgSetFloat( "/controls/rudder", tmp );
-#endif
+    fgSetFloat( "/controls/engines/engine[0]/throttle", tmp );
+    fgSetFloat( "/controls/engines/engine[1]/throttle", tmp );
+    // cout << "throttle = " << tmp << endl;
+
+    if ( use_rudder ) {
+        // rudder
+        tmp = scale( rudder_center->getIntValue(), rudder_min->getIntValue(),
+                     rudder_max->getIntValue(), analog_in_data[10] );
+        fgSetFloat( "/controls/flight/rudder", -tmp );
+
+        // toe brakes
+        tmp = scale( brake_left_min->getIntValue(),
+                     brake_left_max->getIntValue(),
+                     analog_in_data[20] );
+        fgSetFloat( "/controls/gear/wheel[0]/brake", tmp );
+        tmp = scale( brake_right_min->getIntValue(),
+                     brake_right_max->getIntValue(),
+                     analog_in_data[21] );
+        fgSetFloat( "/controls/gear/wheel[1]/brake", tmp );
+    }
 
     // nav1 volume
     tmp = (float)analog_in_data[25] / 1024.0f;
@@ -608,14 +762,63 @@ bool FGATC610x::do_analog_in() {
     tmp = (float)analog_in_data[26] / 1024.0f;
     fgSetFloat( "/radios/kr-87/inputs/volume", tmp );
 
-    // nav2 obs tuner
-    tmp = (float)analog_in_data[29] * 360.0f / 1024.0f;
+    // instrument panel pots
+    static bool first = true;
+    static int obs1[3], obs2[3], obs3[3], obs4[3], obs5[3];
+    static double diff1_ave = 0.0;
+    static double diff2_ave = 0.0;
+    static double diff3_ave = 0.0;
+    static double diff4_ave = 0.0;
+    static double diff5_ave = 0.0;
+
+    if ( first ) {
+        first = false;
+        obs1[0] = obs1[1] = obs1[2] = analog_in_data[11];
+        obs2[0] = obs2[1] = obs2[2] = analog_in_data[28];
+        obs3[0] = obs3[1] = obs3[2] = analog_in_data[29];
+        obs4[0] = obs4[1] = obs4[2] = analog_in_data[30];
+        obs5[0] = obs5[1] = obs5[2] = analog_in_data[31];
+    }
+
+    int diff1 = tony_magic( analog_in_data[11], obs1 );
+    int diff2 = tony_magic( analog_in_data[28], obs2 );
+    int diff3 = tony_magic( analog_in_data[29], obs3 );
+    int diff4 = tony_magic( analog_in_data[30], obs4 );
+    int diff5 = tony_magic( analog_in_data[31], obs5 );
+
+    diff1_ave = instr_pot_filter( diff1_ave, diff1 );
+    diff2_ave = instr_pot_filter( diff2_ave, diff2 );
+    diff3_ave = instr_pot_filter( diff3_ave, diff3 );
+    diff4_ave = instr_pot_filter( diff4_ave, diff4 );
+    diff5_ave = instr_pot_filter( diff5_ave, diff5 );
+
+    tmp = alt_press->getDoubleValue() + (diff1_ave * (0.25/888.0) );
+    if ( tmp < 27.9 ) { tmp = 27.9; }
+    if ( tmp > 31.4 ) { tmp = 31.4; }
+    fgSetFloat( "/instrumentation/altimeter/setting-inhg", tmp );
+
+    tmp = ati_bird->getDoubleValue() + (diff2_ave * (20.0/888.0) );
+    if ( tmp < -10.0 ) { tmp = -10.0; }
+    if ( tmp > 10.0 ) { tmp = 10.0; }
+    fgSetFloat( "/instrumentation/attitude-indicator/horizon-offset-deg", tmp );
+
+    tmp = nav1_obs->getDoubleValue() + (diff3_ave * (72.0/888.0) );
+    while ( tmp >= 360.0 ) { tmp -= 360.0; }
+    while ( tmp < 0.0 ) { tmp += 360.0; }
+    // cout << " obs = " << tmp << endl;
+    fgSetFloat( "/radios/nav[0]/radials/selected-deg", tmp );
+
+    tmp = nav2_obs->getDoubleValue() + (diff4_ave * (72.0/888.0) );
+    while ( tmp >= 360.0 ) { tmp -= 360.0; }
+    while ( tmp < 0.0 ) { tmp += 360.0; }
+    // cout << " obs = " << tmp << endl;
     fgSetFloat( "/radios/nav[1]/radials/selected-deg", tmp );
 
-    // nav1 obs tuner
-    tmp1 = (float)analog_in_data[30] * 360.0f / 1024.0f;
-    tmp2 = (float)analog_in_data[31] * 360.0f / 1024.0f;
-    fgSetFloat( "/radios/nav[0]/radials/selected-deg", tmp1 );
+    tmp = adf_hdg->getDoubleValue() + (diff5_ave * (72.0/888.0) );
+    while ( tmp >= 360.0 ) { tmp -= 360.0; }
+    while ( tmp < 0.0 ) { tmp += 360.0; }
+    // cout << " obs = " << tmp << endl;
+    fgSetFloat( "/radios/kr-87/inputs/rotation-deg", tmp );
 
     return true;
 }
@@ -666,20 +869,28 @@ bool FGATC610x::do_radio_switches() {
     dme_switch = (radio_switch_data[7] >> 4) & 0x03;
     if ( dme_switch == 0 ) {
        // off
-       fgSetInt( "/radios/dme/switch-position", 0 );
+       fgSetInt( "/instrumentation/dme/switch-position", 0 );
     } else if ( dme_switch == 2 ) {
        // nav1
-       fgSetInt( "/radios/dme/switch-position", 1 );
+       fgSetInt( "/instrumentation/dme/switch-position", 1 );
+        fgSetString( "/instrumentation/dme/frequencies/source",
+                     "/radios/nav[0]/frequencies/selected-mhz" );
+       freq = fgGetFloat( "/radios/nav[0]/frequencies/selected-mhz", true );
+        fgSetFloat( "/instrumentation/dme/frequencies/selected-mhz", freq );
     } else if ( dme_switch == 1 ) {
        // nav2
-       fgSetInt( "/radios/dme/switch-position", 3 );
+       fgSetInt( "/instrumentation/dme/switch-position", 3 );
+        fgSetString( "/instrumentation/dme/frequencies/source",
+                     "/radios/nav[1]/frequencies/selected-mhz" );
+       freq = fgGetFloat( "/radios/nav[1]/frequencies/selected-mhz", true );
+        fgSetFloat( "/instrumentation/dme/frequencies/selected-mhz", freq );
     }
 
     // NavCom1 Power
     fgSetBool( "/radios/comm[0]/inputs/power-btn",
                radio_switch_data[7] & 0x01 );
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && comm1_servicable->getBoolValue() ) {
         // Com1 Swap
         int com1_swap = !((radio_switch_data[7] >> 1) & 0x01);
         static int last_com1_swap;
@@ -696,7 +907,7 @@ bool FGATC610x::do_radio_switches() {
     fgSetBool( "/radios/comm[1]/inputs/power-btn",
                radio_switch_data[15] & 0x01 );
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && comm2_servicable->getBoolValue() ) {
         // Com2 Swap
         int com2_swap = !((radio_switch_data[15] >> 1) & 0x01);
         static int last_com2_swap;
@@ -709,7 +920,7 @@ bool FGATC610x::do_radio_switches() {
         last_com2_swap = com2_swap;
     }
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && nav1_servicable->getBoolValue() ) {
         // Nav1 Swap
         int nav1_swap = radio_switch_data[11] & 0x01;
         static int last_nav1_swap;
@@ -722,7 +933,7 @@ bool FGATC610x::do_radio_switches() {
         last_nav1_swap = nav1_swap;
     }
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && nav2_servicable->getBoolValue() ) {
         // Nav2 Swap
         int nav2_swap = !(radio_switch_data[19] & 0x01);
         static int last_nav2_swap;
@@ -735,7 +946,7 @@ bool FGATC610x::do_radio_switches() {
         last_nav2_swap = nav2_swap;
     }
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && comm1_servicable->getBoolValue() ) {
         // Com1 Tuner
         int com1_tuner_fine = ((radio_switch_data[5] >> 4) & 0x0f) - 1;
         int com1_tuner_coarse = (radio_switch_data[5] & 0x0f) - 1;
@@ -787,7 +998,7 @@ bool FGATC610x::do_radio_switches() {
                     coarse_freq + fine_freq / 40.0 );
     }
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && comm2_servicable->getBoolValue() ) {
         // Com2 Tuner
         int com2_tuner_fine = ((radio_switch_data[13] >> 4) & 0x0f) - 1;
         int com2_tuner_coarse = (radio_switch_data[13] & 0x0f) - 1;
@@ -839,7 +1050,7 @@ bool FGATC610x::do_radio_switches() {
                     coarse_freq + fine_freq / 40.0 );
     }
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && nav1_servicable->getBoolValue() ) {
         // Nav1 Tuner
         int nav1_tuner_fine = ((radio_switch_data[9] >> 4) & 0x0f) - 1;
         int nav1_tuner_coarse = (radio_switch_data[9] & 0x0f) - 1;
@@ -891,7 +1102,7 @@ bool FGATC610x::do_radio_switches() {
                     coarse_freq + fine_freq / 20.0 );
     }
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && nav2_servicable->getBoolValue() ) {
         // Nav2 Tuner
         int nav2_tuner_fine = ((radio_switch_data[17] >> 4) & 0x0f) - 1;
         int nav2_tuner_coarse = (radio_switch_data[17] & 0x0f) - 1;
@@ -943,13 +1154,14 @@ bool FGATC610x::do_radio_switches() {
                     coarse_freq + fine_freq / 20.0);
     }
 
-    if ( adf_power->getBoolValue() ) {
-        // ADF Tuner
-        int adf_tuner_fine = ((radio_switch_data[21] >> 4) & 0x0f) - 1;
-        int adf_tuner_coarse = (radio_switch_data[21] & 0x0f) - 1;
-        static int last_adf_tuner_fine = adf_tuner_fine;
-        static int last_adf_tuner_coarse = adf_tuner_coarse;
+    // ADF Tuner
+    
+    int adf_tuner_fine = ((radio_switch_data[21] >> 4) & 0x0f) - 1;
+    int adf_tuner_coarse = (radio_switch_data[21] & 0x0f) - 1;
+    static int last_adf_tuner_fine = adf_tuner_fine;
+    static int last_adf_tuner_coarse = adf_tuner_coarse;
 
+    if ( adf_has_power() && adf_servicable->getBoolValue() ) {
         // cout << "adf_stby_mode = " << adf_stby_mode->getIntValue() << endl;
         if ( adf_count_mode->getIntValue() == 2 ) {
             // tune count down timer
@@ -1004,9 +1216,6 @@ bool FGATC610x::do_radio_switches() {
             if ( value > 1799 ) { value -= 1600; }
         }
  
-        last_adf_tuner_fine = adf_tuner_fine;
-        last_adf_tuner_coarse = adf_tuner_coarse;
-
         if ( adf_count_mode->getIntValue() == 2 ) {
             fgSetFloat( "/radios/kr-87/outputs/elapsed-timer", value );
         } else {
@@ -1017,6 +1226,9 @@ bool FGATC610x::do_radio_switches() {
             }
         }
     }
+    last_adf_tuner_fine = adf_tuner_fine;
+    last_adf_tuner_coarse = adf_tuner_coarse;
+
 
     // ADF buttons 
     fgSetInt( "/radios/kr-87/inputs/adf-btn",
@@ -1024,30 +1236,30 @@ bool FGATC610x::do_radio_switches() {
     fgSetInt( "/radios/kr-87/inputs/bfo-btn",
               !(radio_switch_data[23] >> 1 & 0x01) );
     fgSetInt( "/radios/kr-87/inputs/frq-btn",
-              (radio_switch_data[23] >> 2 & 0x01) );
+              !(radio_switch_data[23] >> 2 & 0x01) );
     fgSetInt( "/radios/kr-87/inputs/flt-et-btn",
-                  !(radio_switch_data[23] >> 3 & 0x01) );
+              !(radio_switch_data[23] >> 3 & 0x01) );
     fgSetInt( "/radios/kr-87/inputs/set-rst-btn",
               !(radio_switch_data[23] >> 4 & 0x01) );
     fgSetInt( "/radios/kr-87/inputs/power-btn",
               radio_switch_data[23] >> 5 & 0x01 );
     /* cout << "adf = " << !(radio_switch_data[23] & 0x01)
          << " bfo = " << !(radio_switch_data[23] >> 1 & 0x01)
-         << " stby = " << !(radio_switch_data[23] >> 2 & 0x01)
-         << " timer = " << !(radio_switch_data[23] >> 3 & 0x01)
+         << " frq = " << !(radio_switch_data[23] >> 2 & 0x01)
+         << " flt/et = " << !(radio_switch_data[23] >> 3 & 0x01)
          << " set/rst = " << !(radio_switch_data[23] >> 4 & 0x01)
          << endl; */
 
     // Transponder Tuner
     int i;
     int digit_tuner[4];
-
     digit_tuner[0] = radio_switch_data[25] & 0x0f;
     digit_tuner[1] = ( radio_switch_data[25] >> 4 ) & 0x0f;
     digit_tuner[2] = radio_switch_data[29] & 0x0f;
     digit_tuner[3] = ( radio_switch_data[29] >> 4 ) & 0x0f;
-    static bool first_time = true;
+
     static int last_digit_tuner[4];
+    static bool first_time = true;
     if ( first_time ) {
         first_time = false;
         for ( i = 0; i < 4; ++i ) {
@@ -1055,40 +1267,44 @@ bool FGATC610x::do_radio_switches() {
         }
     }
 
-    int id_code = xpdr_id_code->getIntValue();
-    int digit[4];
-    int place = 1000;
-    for ( i = 0; i < 4; ++i ) {
-        digit[i] = id_code / place;
-        id_code -= digit[i] * place;
-        place /= 10;
-    }
+    if ( xpdr_has_power() && xpdr_servicable->getBoolValue() ) {
+        int id_code = xpdr_id_code->getIntValue();
+        int digit[4];
+        int place = 1000;
+        for ( i = 0; i < 4; ++i ) {
+            digit[i] = id_code / place;
+            id_code -= digit[i] * place;
+            place /= 10;
+        }
 
-    for ( i = 0; i < 4; ++i ) {
-        if ( digit_tuner[i] != last_digit_tuner[i] ) {
-            diff = digit_tuner[i] - last_digit_tuner[i];
-            if ( abs(diff) > 4 ) {
-                // roll over
-                if ( digit_tuner[i] < last_digit_tuner[i] ) {
-                    // going up
-                    diff = 15 - last_digit_tuner[i] + digit_tuner[i];
-                } else {
-                    // going down
-                    diff = digit_tuner[i] - 15 - last_digit_tuner[i];
+        for ( i = 0; i < 4; ++i ) {
+            if ( digit_tuner[i] != last_digit_tuner[i] ) {
+                diff = digit_tuner[i] - last_digit_tuner[i];
+                if ( abs(diff) > 4 ) {
+                    // roll over
+                    if ( digit_tuner[i] < last_digit_tuner[i] ) {
+                        // going up
+                        diff = 15 - last_digit_tuner[i] + digit_tuner[i];
+                    } else {
+                        // going down
+                        diff = digit_tuner[i] - 15 - last_digit_tuner[i];
+                    }
                 }
+                digit[i] += diff;
             }
-            digit[i] += diff;
+            while ( digit[i] >= 8 ) { digit[i] -= 8; }
+            while ( digit[i] < 0 )  { digit[i] += 8; }
         }
-        while ( digit[i] >= 8 ) { digit[i] -= 8; }
-        while ( digit[i] < 0 )  { digit[i] += 8; }
+
+        fgSetInt( "/radios/kt-70/inputs/digit1", digit[0] );
+        fgSetInt( "/radios/kt-70/inputs/digit2", digit[1] );
+        fgSetInt( "/radios/kt-70/inputs/digit3", digit[2] );
+        fgSetInt( "/radios/kt-70/inputs/digit4", digit[3] );
+    }
+    for ( i = 0; i < 4; ++i ) {
         last_digit_tuner[i] = digit_tuner[i];
     }
 
-    fgSetInt( "/radios/kt-70/inputs/digit1", digit[0] );
-    fgSetInt( "/radios/kt-70/inputs/digit2", digit[1] );
-    fgSetInt( "/radios/kt-70/inputs/digit3", digit[2] );
-    fgSetInt( "/radios/kt-70/inputs/digit4", digit[3] );
-
     int tmp = 0;
     for ( i = 0; i < 5; ++i ) {
         if ( radio_switch_data[27] >> i & 0x01 ) {
@@ -1099,6 +1315,16 @@ bool FGATC610x::do_radio_switches() {
     fgSetInt( "/radios/kt-70/inputs/ident-btn",
               !(radio_switch_data[27] >> 5 & 0x01) );
 
+    // Audio panel switches
+    fgSetInt( "/radios/nav[0]/audio-btn",
+              (radio_switch_data[3] & 0x01) );
+    fgSetInt( "/radios/nav[1]/audio-btn",
+              (radio_switch_data[3] >> 2 & 0x01) );
+    fgSetInt( "/radios/kr-87/inputs/audio-btn",
+              (radio_switch_data[3] >> 4 & 0x01) );
+    fgSetInt( "/radios/marker-beacon/audio-btn",
+              (radio_switch_data[3] >> 6 & 0x01) );
+
     return true;
 }
 
@@ -1112,44 +1338,54 @@ bool FGATC610x::do_radio_display() {
     char digits[10];
     int i;
 
-    if ( dme_switch != 0 ) {
-       // DME minutes
-       float minutes = dme_min->getFloatValue();
-       if ( minutes > 999 ) {
-           minutes = 999.0;
-       }
-       snprintf(digits, 7, "%03.0f", minutes);
-       for ( i = 0; i < 6; ++i ) {
-           digits[i] -= '0';
-       }
-       radio_display_data[0] = digits[1] << 4 | digits[2];
-       radio_display_data[1] = 0xf0 | digits[0];
+    if ( dme_has_power() && dme_servicable->getBoolValue() ) {
+        if ( dme_in_range->getBoolValue() ) {
+            // DME minutes
+            float minutes = dme_min->getFloatValue();
+            if ( minutes > 999 ) {
+                minutes = 999.0;
+            }
+            snprintf(digits, 7, "%03.0f", minutes);
+            for ( i = 0; i < 6; ++i ) {
+                digits[i] -= '0';
+            }
+            radio_display_data[0] = digits[1] << 4 | digits[2];
+            radio_display_data[1] = 0xf0 | digits[0];
        
-       // DME knots
-       float knots = dme_kt->getFloatValue();
-       if ( knots > 999 ) {
-           knots = 999.0;
-       }
-       snprintf(digits, 7, "%03.0f", knots);
-       for ( i = 0; i < 6; ++i ) {
-           digits[i] -= '0';
-       }
-       radio_display_data[2] = digits[1] << 4 | digits[2];
-       radio_display_data[3] = 0xf0 | digits[0];
+            // DME knots
+            float knots = dme_kt->getFloatValue();
+            if ( knots > 999 ) {
+                knots = 999.0;
+            }
+            snprintf(digits, 7, "%03.0f", knots);
+            for ( i = 0; i < 6; ++i ) {
+                digits[i] -= '0';
+            }
+            radio_display_data[2] = digits[1] << 4 | digits[2];
+            radio_display_data[3] = 0xf0 | digits[0];
 
-       // DME distance (nm)
-       float nm = dme_nm->getFloatValue();
-       if ( nm > 99 ) {
-           nm = 99.0;
-       }
-       snprintf(digits, 7, "%04.1f", nm);
-       for ( i = 0; i < 6; ++i ) {
-           digits[i] -= '0';
-       }
-       radio_display_data[4] = digits[1] << 4 | digits[3];
-       radio_display_data[5] = 0x00 | digits[0];
-       // the 0x00 in the upper nibble of the 6th byte of each
-       // display turns on the decimal point
+            // DME distance (nm)
+            float nm = dme_nm->getFloatValue();
+            if ( nm > 99 ) {
+                nm = 99.0;
+            }
+            snprintf(digits, 7, "%04.1f", nm);
+            for ( i = 0; i < 6; ++i ) {
+                digits[i] -= '0';
+            }
+            radio_display_data[4] = digits[1] << 4 | digits[3];
+            radio_display_data[5] = 0x00 | digits[0];
+            // the 0x00 in the upper nibble of the 6th byte of each
+            // display turns on the decimal point
+        } else {
+            // out of range
+            radio_display_data[0] = 0xbb;
+            radio_display_data[1] = 0xfb;
+            radio_display_data[2] = 0xbb;
+            radio_display_data[3] = 0xfb;
+            radio_display_data[4] = 0xbb;
+            radio_display_data[5] = 0x0b;
+        }
     } else {
        // blank dem display
        for ( i = 0; i < 6; ++i ) {
@@ -1157,7 +1393,7 @@ bool FGATC610x::do_radio_display() {
        }
     }
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && comm1_servicable->getBoolValue() ) {
         // Com1 standby frequency
         float com1_stby = com1_stby_freq->getFloatValue();
         if ( fabs(com1_stby) > 999.99 ) {
@@ -1194,7 +1430,7 @@ bool FGATC610x::do_radio_display() {
         radio_display_data[11] = 0xff;
     }
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && comm2_servicable->getBoolValue() ) {
         // Com2 standby frequency
         float com2_stby = com2_stby_freq->getFloatValue();
         if ( fabs(com2_stby) > 999.99 ) {
@@ -1231,7 +1467,7 @@ bool FGATC610x::do_radio_display() {
         radio_display_data[23] = 0xff;
     }
 
-    if ( navcom1_has_power() ) {
+    if ( navcom1_has_power() && nav1_servicable->getBoolValue() ) {
         // Nav1 standby frequency
         float nav1_stby = nav1_stby_freq->getFloatValue();
         if ( fabs(nav1_stby) > 999.99 ) {
@@ -1268,7 +1504,7 @@ bool FGATC610x::do_radio_display() {
         radio_display_data[17] = 0xff;
     }
 
-    if ( navcom2_has_power() ) {
+    if ( navcom2_has_power() && nav2_servicable->getBoolValue() ) {
         // Nav2 standby frequency
         float nav2_stby = nav2_stby_freq->getFloatValue();
         if ( fabs(nav2_stby) > 999.99 ) {
@@ -1306,7 +1542,7 @@ bool FGATC610x::do_radio_display() {
     }
 
     // ADF standby frequency / timer
-    if ( adf_power->getBoolValue() ) {
+    if ( adf_has_power() && adf_servicable->getBoolValue() ) {
         if ( adf_stby_mode->getIntValue() == 0 ) {
             // frequency
             float adf_stby = adf_stby_freq->getFloatValue();
@@ -1358,9 +1594,9 @@ bool FGATC610x::do_radio_display() {
             for ( i = 0; i < 6; ++i ) {
                 digits[i] -= '0';
             }
-            radio_display_data[30] = digits[3] << 4 | 0x0f;
-            radio_display_data[31] = digits[1] << 4 | digits[2];
-            radio_display_data[32] = 0xf0 | digits[0];
+            radio_display_data[30] = digits[2] << 4 | digits[3];
+            radio_display_data[31] = digits[0] << 4 | digits[1];
+            radio_display_data[32] = 0xff;
         }
 
         // ADF in use frequency
@@ -1378,49 +1614,57 @@ bool FGATC610x::do_radio_display() {
         } else {
             radio_display_data[34] = digits[0] << 4 | digits[1];
         }
+        if ( adf_stby_mode->getIntValue() == 0 ) {
+         radio_display_data[35] = 0xff;
+       } else {
+         radio_display_data[35] = 0x0f;
+       }
     } else {
         radio_display_data[30] = 0xff;
         radio_display_data[31] = 0xff;
         radio_display_data[32] = 0xff;
         radio_display_data[33] = 0xff;
         radio_display_data[34] = 0xff;
+        radio_display_data[35] = 0xff;
     }
     
     // Transponder code and flight level
-    if ( xpdr_func_knob->getIntValue() == 2 ) {
-        // test mode
-        radio_display_data[36] = 8 << 4 | 8;
-        radio_display_data[37] = 8 << 4 | 8;
-        radio_display_data[38] = 0xff;
-        radio_display_data[39] = 8 << 4 | 0x0f;
-        radio_display_data[40] = 8 << 4 | 8;
-    } else if ( xpdr_func_knob->getIntValue() > 0 ) {
-        // other on modes
-        int id_code = xpdr_id_code->getIntValue();
-        int place = 1000;
-        for ( i = 0; i < 4; ++i ) {
-            digits[i] = id_code / place;
-            id_code -= digits[i] * place;
-            place /= 10;
-        }
-        radio_display_data[36] = digits[2] << 4 | digits[3];
-        radio_display_data[37] = digits[0] << 4 | digits[1];
-        radio_display_data[38] = 0xff;
-
-        if ( xpdr_func_knob->getIntValue() == 3 ||
-             xpdr_func_knob->getIntValue() == 5 )
-        {
-            // do flight level display
-            snprintf(digits, 7, "%03d", xpdr_flight_level->getIntValue() );
-            for ( i = 0; i < 6; ++i ) {
-                digits[i] -= '0';
-            }
-           radio_display_data[39] = digits[2] << 4 | 0x0f;
-           radio_display_data[40] = digits[0] << 4 | digits[1];
+    if ( xpdr_has_power() && xpdr_servicable->getBoolValue() ) {
+        if ( xpdr_func_knob->getIntValue() == 2 ) {
+            // test mode
+            radio_display_data[36] = 8 << 4 | 8;
+            radio_display_data[37] = 8 << 4 | 8;
+            radio_display_data[38] = 0xff;
+            radio_display_data[39] = 8 << 4 | 0x0f;
+            radio_display_data[40] = 8 << 4 | 8;
         } else {
-            // blank flight level display
-            radio_display_data[39] = 0xff;
-            radio_display_data[40] = 0xff;
+            // other on modes
+            int id_code = xpdr_id_code->getIntValue();
+            int place = 1000;
+            for ( i = 0; i < 4; ++i ) {
+                digits[i] = id_code / place;
+                id_code -= digits[i] * place;
+                place /= 10;
+            }
+            radio_display_data[36] = digits[2] << 4 | digits[3];
+            radio_display_data[37] = digits[0] << 4 | digits[1];
+            radio_display_data[38] = 0xff;
+
+            if ( xpdr_func_knob->getIntValue() == 3 ||
+                 xpdr_func_knob->getIntValue() == 5 )
+            {
+                // do flight level display
+                snprintf(digits, 7, "%03d", xpdr_flight_level->getIntValue() );
+                for ( i = 0; i < 6; ++i ) {
+                    digits[i] -= '0';
+                }
+                radio_display_data[39] = digits[2] << 4 | 0x0f;
+                radio_display_data[40] = digits[0] << 4 | digits[1];
+            } else {
+                // blank flight level display
+                radio_display_data[39] = 0xff;
+                radio_display_data[40] = 0xff;
+            }
         }
     } else {
         // off
@@ -1498,8 +1742,8 @@ bool FGATC610x::do_switches() {
     update_switch_matrix( board, switch_data, switch_matrix );
 
     // master switches
-    fgSetBool( "/controls/switches/master-bat", switch_matrix[board][4][1] );
-    fgSetBool( "/controls/switches/master-alt", switch_matrix[board][5][1] );
+    fgSetBool( "/controls/switches/master-bat", switch_matrix[board][5][1] );
+    fgSetBool( "/controls/switches/master-alt", switch_matrix[board][4][1] );
     fgSetBool( "/controls/switches/master-avionics",
                switch_matrix[board][0][3] );
 
@@ -1530,18 +1774,19 @@ bool FGATC610x::do_switches() {
     mag2 = mag1;
     mag1 = magnetos;
     if ( mag1 == mag2 && mag2 == mag3 ) {
-        fgSetInt( "/controls/magnetos[0]", magnetos );
+        fgSetInt( "/controls/engines/engine[0]/magnetos", magnetos );
     }
     static bool start1, start2, start3;
     start3 = start2;
     start2 = start1;
     start1 = starter;
     if ( start1 == start2 && start2 == start3 ) {
-        fgSetBool( "/controls/starter[0]", starter );
+        fgSetBool( "/controls/engines/engine[0]/starter", starter );
     }
 
     // other toggle switches
-    fgSetBool( "/controls/fuel-pump[0]", switch_matrix[board][0][2] );
+    fgSetBool( "/controls/engines/engine[0]/fuel-pump",
+               switch_matrix[board][0][2] );
     fgSetBool( "/controls/switches/flashing-beacon",
                switch_matrix[board][1][2] );
     fgSetBool( "/controls/switches/landing-light", switch_matrix[board][2][2] );
@@ -1570,7 +1815,7 @@ bool FGATC610x::do_switches() {
     flap2 = flap1;
     flap1 = flaps;
     if ( flap1 == flap2 && flap2 == flap3 ) {
-        fgSetFloat( "/controls/flaps", flaps );
+        fgSetFloat( "/controls/flight/flaps", flaps );
     }
 
     // fuel selector (also filtered)
@@ -1594,11 +1839,12 @@ bool FGATC610x::do_switches() {
     fuel2 = fuel1;
     fuel1 = fuel;
     if ( fuel1 == fuel2 && fuel2 == fuel3 ) {
-        fgSetBool( "/controls/fuel-selector[0]", (fuel & 0x01) > 0 );
-        fgSetBool( "/controls/fuel-selector[1]", (fuel & 0x02) > 0 );
+        fgSetBool( "/controls/fuel/tank[0]/fuel-selector", (fuel & 0x01) > 0 );
+        fgSetBool( "/controls/fuel/tank[1]/fuel-selector", (fuel & 0x02) > 0 );
     }
 
     // circuit breakers
+#ifdef ATC_SUPPORT_CIRCUIT_BREAKERS_NOT_THE_DEFAULT
     fgSetBool( "/controls/circuit-breakers/cabin-lights-pwr",
                switch_matrix[board][0][0] );
     fgSetBool( "/controls/circuit-breakers/instr-ignition-switch",
@@ -1615,6 +1861,21 @@ bool FGATC610x::do_switches() {
                switch_matrix[board][6][0] );
     fgSetBool( "/controls/circuit-breakers/annunciators",
                switch_matrix[board][7][0] );
+#else
+    fgSetBool( "/controls/circuit-breakers/cabin-lights-pwr", true );
+    fgSetBool( "/controls/circuit-breakers/instr-ignition-switch", true );
+    fgSetBool( "/controls/circuit-breakers/flaps", true );
+    fgSetBool( "/controls/circuit-breakers/avn-bus-1", true );
+    fgSetBool( "/controls/circuit-breakers/avn-bus-2", true );
+    fgSetBool( "/controls/circuit-breakers/turn-coordinator", true );
+    fgSetBool( "/controls/circuit-breakers/instrument-lights", true );
+    fgSetBool( "/controls/circuit-breakers/annunciators", true );
+#endif
+
+    fgSetDouble( "/controls/gear/parking-brake",
+                 switch_matrix[board][7][3] );
+    fgSetDouble( "/radios/marker-beacon/power-btn",
+                 switch_matrix[board][6][1] );
 
     return true;
 }