]> git.mxchange.org Git - flightgear.git/blobdiff - src/Network/ATC-Inputs.cxx
Fix for bug 1304 - crash loading XML route
[flightgear.git] / src / Network / ATC-Inputs.cxx
index 0d11ca64e7ea154e0e8f24d8b7ac274f0d328cc5..be59770f89fda441e7f2b9bdc8a26da1acfe0afd 100644 (file)
@@ -16,7 +16,7 @@
 //
 // You should have received a copy of the GNU General Public License
 // along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 // $Id$
 
 #  include <sys/types.h>
 #  include <sys/stat.h>
 #  include <fcntl.h>
+#  include <stdlib.h>
+#  include <unistd.h>
+#  include <istream>
 #endif
 
-#include STL_STRING
+#include <errno.h>
+#include <math.h>
+#include <cstdio>
+
+#include <string>
 
 #include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props_io.hxx>
 
 #include <Main/fg_props.hxx>
 
 #include "ATC-Inputs.hxx"
 
-SG_USING_STD(string);
-
+using std::string;
+using std::vector;
 
 
 // Constructor: The _board parameter specifies which board to
@@ -63,6 +72,7 @@ FGATCInput::FGATCInput( const int _board, const SGPath &_config_file ) :
 
 // Read analog inputs
 static void ATCReadAnalogInputs( int fd, unsigned char *analog_in_bytes ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -71,11 +81,13 @@ static void ATCReadAnalogInputs( int fd, unsigned char *analog_in_bytes ) {
        SG_LOG( SG_IO, SG_ALERT, "Read failed" );
        exit( -1 );
     }
+#endif
 }
 
 
 // Read status of radio switches and knobs
 static void ATCReadRadios( int fd, unsigned char *switch_data ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -84,11 +96,13 @@ static void ATCReadRadios( int fd, unsigned char *switch_data ) {
        SG_LOG( SG_IO, SG_ALERT, "Read failed" );
        exit( -1 );
     }
+#endif
 }
 
 
 // Read switch inputs
 static void ATCReadSwitches( int fd, unsigned char *switch_bytes ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -97,6 +111,7 @@ static void ATCReadSwitches( int fd, unsigned char *switch_bytes ) {
        SG_LOG( SG_IO, SG_ALERT, "Read failed" );
        exit( -1 );
     }
+#endif
 }
 
 
@@ -130,12 +145,14 @@ bool FGATCInput::open() {
     init_config();
 
     SG_LOG( SG_IO, SG_ALERT,
-           "Initializing ATC 610x hardware, please wait ..." );
+           "Initializing ATC input hardware, please wait ..." );
 
-    snprintf( lock_file, 256, "/proc/atc610x/board%d/lock", board );
-    snprintf( analog_in_file, 256, "/proc/atc610x/board%d/analog_in", board );
-    snprintf( radios_file, 256, "/proc/atc610x/board%d/radios", board );
-    snprintf( switches_file, 256, "/proc/atc610x/board%d/switches", board );
+    snprintf( analog_in_file, 256,
+              "/proc/atcflightsim/board%d/analog_in", board );
+    snprintf( radios_file, 256,
+              "/proc/atcflightsim/board%d/radios", board );
+    snprintf( switches_file, 256,
+              "/proc/atcflightsim/board%d/switches", board );
 
 #if defined( unix ) || defined( __CYGWIN__ )
 
@@ -143,15 +160,6 @@ bool FGATCInput::open() {
     // Open the /proc files
     /////////////////////////////////////////////////////////////////////
 
-    lock_fd = ::open( lock_file, O_RDWR );
-    if ( lock_fd == -1 ) {
-       SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
-       char msg[256];
-       snprintf( msg, 256, "Error opening %s", lock_file );
-       perror( msg );
-       exit( -1 );
-    }
-
     analog_in_fd = ::open( analog_in_file, O_RDONLY );
     if ( analog_in_fd == -1 ) {
        SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
@@ -186,7 +194,7 @@ bool FGATCInput::open() {
     /////////////////////////////////////////////////////////////////////
 
     SG_LOG( SG_IO, SG_ALERT,
-           "Done initializing ATC 610x hardware." );
+           "Done initializing ATC input hardware." );
 
     is_open = true;
 
@@ -219,18 +227,21 @@ bool FGATCInput::open() {
 /////////////////////////////////////////////////////////////////////
 
 // 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 ) {
+// from -1.0 to 1.0.  The deadband value is symmetric, so specifying
+// '1' will give you a deadband of +/-1
+static double scale( int center, int deadband, int min, int max, int value ) {
     // cout << center << " " << min << " " << max << " " << value << " ";
     double result;
     double range;
 
-    if ( value <= center ) {
-        range = center - min;
-        result = (value - center) / range;
+    if ( value <= (center - deadband) ) {
+        range = (center - deadband) - min;
+        result = (value - (center - deadband)) / range;
+    } else if ( value >= (center + deadband) ) {
+        range = max - (center + deadband);
+        result = (value - (center + deadband)) / range;            
     } else {
-        range = max - center;
-        result = (value - center) / range;            
+        result = 0.0;
     }
 
     if ( result < -1.0 ) result = -1.0;
@@ -260,6 +271,18 @@ static double scale( int min, int max, int value ) {
 }
 
 
+static double clamp( double min, double max, double value ) {
+    double result = value;
+
+    if ( result < min ) result = min;
+    if ( result > max ) result = max;
+
+    // cout << result << endl;
+
+    return result;   
+}
+
+
 static int tony_magic( int raw, int obs[3] ) {
     int result = 0;
 
@@ -394,10 +417,13 @@ bool FGATCInput::do_analog_in() {
             string name = "";
             string type = "";
             string subtype = "";
-            vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+            vector <SGPropertyNode *> output_nodes;
             int center = -1;
             int min = 0;
             int max = 1023;
+           int deadband = 0;
+           int hysteresis = 0;
+            float offset = 0.0;
             float factor = 1.0;
             if ( cname == "channel" ) {
                 SGPropertyNode *prop;
@@ -432,6 +458,18 @@ bool FGATCInput::do_analog_in() {
                 if ( prop != NULL ) {
                     max = prop->getIntValue();
                 }
+                prop = child->getChild( "deadband" );
+                if ( prop != NULL ) {
+                    deadband = prop->getIntValue();
+                }
+                prop = child->getChild( "hysteresis" );
+                if ( prop != NULL ) {
+                    hysteresis = prop->getIntValue();
+                }
+                prop = child->getChild( "offset" );
+                if ( prop != NULL ) {
+                    offset = prop->getFloatValue();
+                }
                 prop = child->getChild( "factor" );
                 if ( prop != NULL ) {
                     factor = prop->getFloatValue();
@@ -452,12 +490,37 @@ bool FGATCInput::do_analog_in() {
                     {
                         // "Cook" the raw value
                         float scaled_value = 0.0f;
+
+                       if ( hysteresis > 0 ) {
+                           int last_raw_value = 0;
+                           prop = child->getChild( "last-raw-value", 0, true );
+                           last_raw_value = prop->getIntValue();
+
+                           if ( abs(raw_value - last_raw_value) < hysteresis )
+                           {
+                               // not enough movement stay put
+                               raw_value = last_raw_value;
+                           } else {
+                               // update last raw value
+                               prop->setIntValue( raw_value );
+                           }
+                       }
+
                         if ( center >= 0 ) {
-                            scaled_value = scale( center, min, max, raw_value );
+                            scaled_value = scale( center, deadband,
+                                                 min, max, raw_value );
                         } else {
                             scaled_value = scale( min, max, raw_value );
                         }
                         scaled_value *= factor;
+                        scaled_value += offset;
+
+                        // final sanity clamp
+                        if ( center >= 0 ) {
+                            scaled_value = clamp( -1.0, 1.0, scaled_value );
+                        } else {
+                            scaled_value = clamp( 0.0, 1.0, scaled_value );
+                        }
 
                         // update the property tree values
                         for ( j = 0; j < (int)output_nodes.size(); ++j ) {
@@ -468,11 +531,20 @@ bool FGATCInput::do_analog_in() {
                     // "Cook" the raw value
                     float scaled_value = 0.0f;
                     if ( center >= 0 ) {
-                        scaled_value = scale( center, min, max, raw_value );
+                        scaled_value = scale( center, deadband,
+                                             min, max, raw_value );
                     } else {
                         scaled_value = scale( min, max, raw_value );
                     }
                     scaled_value *= factor;
+                    scaled_value += offset;
+
+                    // final sanity clamp
+                    if ( center >= 0 ) {
+                        scaled_value = clamp( -1.0, 1.0, scaled_value );
+                    } else {
+                        scaled_value = clamp( 0.0, 1.0, scaled_value );
+                    }
 
                     // update the property tree values
                     for ( j = 0; j < (int)output_nodes.size(); ++j ) {
@@ -589,9 +661,13 @@ static void update_switch_matrix(
        unsigned char switches = switch_data[row];
 
        for( int column = 0; column < ATC_NUM_COLS; ++column ) {
-           switch_matrix[board][column][row] = switches & 1;
-           switches = switches >> 1;
-       }                       
+            if ( row < 8 ) {
+                switch_matrix[board][column][row] = switches & 1;
+            } else {
+                switch_matrix[board][row-8][8+column] = switches & 1;
+            }
+            switches = switches >> 1;
+        }
     }
 }                     
 
@@ -612,12 +688,13 @@ bool FGATCInput::do_switches() {
             string cname = child->getName();
             string name = "";
             string type = "";
-            vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+            vector <SGPropertyNode *> output_nodes;
             int row = -1;
             int col = -1;
             float factor = 1.0;
             int filter = -1;
             float scaled_value = 0.0f;
+           bool invert = false;
 
             // get common options
 
@@ -641,6 +718,10 @@ bool FGATCInput::do_switches() {
             if ( prop != NULL ) {
                 factor = prop->getFloatValue();
             }
+            prop = child->getChild( "invert" );
+            if ( prop != NULL ) {
+                invert = prop->getBoolValue();
+            }
             prop = child->getChild( "steady-state-filter" );
             if ( prop != NULL ) {
                 filter = prop->getIntValue();
@@ -661,6 +742,11 @@ bool FGATCInput::do_switches() {
                 // Fetch the raw value
                 int raw_value = switch_matrix[board][row][col];
 
+               // Invert
+               if ( invert ) {
+                   raw_value = !raw_value;
+               }
+
                 // Cook the value
                 scaled_value = (float)raw_value * factor;
 
@@ -700,6 +786,42 @@ bool FGATCInput::do_switches() {
 
                 // Cook the value
                 scaled_value *= factor;
+            } else if ( cname == "additive-switch" ) {
+                float additive_value = 0.0f;
+               float increment = 0.0f;
+
+                SGPropertyNode *pos;
+                int k = 0;
+                while ( (pos = child->getChild("position", k++)) != NULL ) {
+                    // read the combo position entries from the property tree
+
+                    prop = pos->getChild( "row" );
+                    if ( prop != NULL ) {
+                        row = prop->getIntValue();
+                    }
+                    prop = pos->getChild( "col" );
+                    if ( prop != NULL ) {
+                        col = prop->getIntValue();
+                    }
+                    prop = pos->getChild( "value" );
+                    if ( prop != NULL ) {
+                        increment = prop->getFloatValue();
+                    }
+
+                    // Fetch the raw value
+                    int raw_value = switch_matrix[board][row][col];
+                    // cout << "sm[" << board << "][" << row << "][" << col
+                    //      << "] = " << raw_value << endl;
+
+                    if ( raw_value ) {
+                        // set scaled_value to the first combo_value
+                        // that matches and jump out of loop.
+                        additive_value += increment;
+                    }
+                }
+
+                // Cook the value
+                scaled_value = additive_value * factor;
             }
 
             // handle filter request.  The value of the switch must be
@@ -769,7 +891,7 @@ bool FGATCInput::do_radio_switches() {
             if ( cname == "switch" ) {
                 string name = "";
                 string type = "";
-                vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+                vector <SGPropertyNode *> output_nodes;
                 int byte_num = -1;
                 int right_shift = 0;
                 int mask = 0xff;
@@ -863,17 +985,12 @@ bool FGATCInput::close() {
 
 #if defined( unix ) || defined( __CYGWIN__ )
 
-    int result;
-
-    result = ::close( lock_fd );
-    if ( result == -1 ) {
-       SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
-       char msg[256];
-       snprintf( msg, 256, "Error closing %s", lock_file );
-       perror( msg );
-       exit( -1 );
+    if ( !is_open ) {
+        return true;
     }
 
+    int result;
+
     result = ::close( analog_in_fd );
     if ( result == -1 ) {
        SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );