]> git.mxchange.org Git - flightgear.git/blobdiff - src/Network/ATC-Outputs.cxx
Update VS2008 projects : use Boost 1.44.0 available in last 3rd Party archive
[flightgear.git] / src / Network / ATC-Outputs.cxx
index 5747a58b7a1a2bf534d5ff7263651d9aea42697a..97a8df77169a19635f56fcebec117f52d3178f4e 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 <unistd.h>
+#  include <ostream>
 #endif
 
 #include <errno.h>
 #include <math.h>
 
-#include STL_STRING
+#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-Outputs.hxx"
 
-SG_USING_STD(string);
+using std::string;
 
 
 
@@ -94,6 +97,7 @@ static int ATCRelease( int fd ) {
 // specifies the location of the output config file (xml)
 FGATCOutput::FGATCOutput( const int _board, const SGPath &_config_file ) :
     is_open(false),
+    analog_out_node(NULL),
     lamps_out_node(NULL),
     radio_display_node(NULL),
     steppers_node(NULL)
@@ -103,6 +107,27 @@ FGATCOutput::FGATCOutput( const int _board, const SGPath &_config_file ) :
 }
 
 
+// Write analog out data
+static int ATCSetAnalogOut( int fd,
+                           unsigned char data[ATC_ANALOG_OUT_CHANNELS*2] )
+{
+#if defined( unix ) || defined( __CYGWIN__ )
+    // rewind
+    lseek( fd, 0, SEEK_SET );
+
+    int result = write( fd, data, ATC_ANALOG_OUT_CHANNELS*2 );
+
+    if ( result != ATC_ANALOG_OUT_CHANNELS*2 ) {
+       SG_LOG( SG_IO, SG_DEBUG, "Write failed" );
+    }
+
+    return result;
+#else
+    return -1;
+#endif
+}
+
+
 // Write a radios command
 static int ATCSetRadios( int fd, unsigned char data[ATC_RADIO_DISPLAY_BYTES] ) {
 #if defined( unix ) || defined( __CYGWIN__ )
@@ -148,6 +173,7 @@ static int ATCSetStepper( int fd, unsigned char channel,
 }
 
 
+#ifdef ATCFLIGHTSIM_HAVE_COMPASS
 // Read status of last stepper written to
 static unsigned char ATCReadStepper( int fd ) {
 #if defined( unix ) || defined( __CYGWIN__ )
@@ -170,6 +196,7 @@ static unsigned char ATCReadStepper( int fd ) {
     return 0;
 #endif
 }
+#endif
 
 
 // Turn a lamp on or off
@@ -229,6 +256,8 @@ bool FGATCOutput::open( int lock_fd ) {
     SG_LOG( SG_IO, SG_ALERT,
            "Initializing ATC output hardware, please wait ..." );
 
+    snprintf( analog_out_file, 256,
+              "/proc/atcflightsim/board%d/analog_out", board );
     snprintf( lamps_file, 256,
               "/proc/atcflightsim/board%d/lamps", board );
     snprintf( radio_display_file, 256,
@@ -242,6 +271,15 @@ bool FGATCOutput::open( int lock_fd ) {
     // Open the /proc files
     /////////////////////////////////////////////////////////////////////
 
+    analog_out_fd = ::open( analog_out_file, O_WRONLY );
+    if ( analog_out_fd == -1 ) {
+       SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
+       char msg[256];
+       snprintf( msg, 256, "Error opening %s", analog_out_file );
+       perror( msg );
+       exit( -1 );
+    }
+
     lamps_fd = ::open( lamps_file, O_WRONLY );
     if ( lamps_fd == -1 ) {
        SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
@@ -310,9 +348,7 @@ bool FGATCOutput::open( int lock_fd ) {
 
        ATCRelease( lock_fd );
 
-#if defined( _MSC_VER )
-       ulMilliSecondSleep(33);
-#elif defined (WIN32) && !defined(__CYGWIN__)
+#ifdef _WIN32
         Sleep (33);
 #else
        usleep(33);
@@ -324,6 +360,23 @@ bool FGATCOutput::open( int lock_fd ) {
     compass_position = 0.0;
 #endif
 
+    // Lock the hardware, keep trying until we succeed
+    while ( ATCLock( lock_fd ) <= 0 );
+
+    /////////////////////////////////////////////////////////////////////
+    // Zero the analog outputs
+    /////////////////////////////////////////////////////////////////////
+
+    SG_LOG( SG_IO, SG_ALERT,
+           "  - Zeroing Analog Outputs." );
+
+    for ( int channel = 0; channel < ATC_ANALOG_OUT_CHANNELS; ++channel ) {
+       analog_out_data[2*channel] = 0;
+       analog_out_data[2*channel + 1] = 0;
+    }
+    ATCSetAnalogOut( analog_out_fd, analog_out_data );
+
+
     /////////////////////////////////////////////////////////////////////
     // Blank the radio display
     /////////////////////////////////////////////////////////////////////
@@ -336,11 +389,6 @@ bool FGATCOutput::open( int lock_fd ) {
     for ( int channel = 0; channel < ATC_RADIO_DISPLAY_BYTES; ++channel ) {
        radio_display_data[channel] = value;
     }
-
-    // Lock the hardware, keep trying until we succeed
-    while ( ATCLock( lock_fd ) <= 0 );
-
-    // Set radio display
     ATCSetRadios( radio_display_fd, radio_display_data );
 
     ATCRelease( lock_fd );
@@ -368,6 +416,9 @@ bool FGATCOutput::open( int lock_fd ) {
 
     char base_name[256];
 
+    snprintf( base_name, 256, "/output/atc-board[%d]/analog-outputs", board );
+    analog_out_node = fgGetNode( base_name );
+
     snprintf( base_name, 256, "/output/atc-board[%d]/lamps", board );
     lamps_out_node = fgGetNode( base_name );
 
@@ -381,6 +432,75 @@ bool FGATCOutput::open( int lock_fd ) {
 }
 
 
+/////////////////////////////////////////////////////////////////////
+// Write the lanalog outputs
+/////////////////////////////////////////////////////////////////////
+
+bool FGATCOutput::do_analog_out() {
+    if ( analog_out_node != NULL ) {
+        for ( int i = 0; i < analog_out_node->nChildren(); ++i ) {
+            // read the next config entry from the property tree
+
+            SGPropertyNode *child = analog_out_node->getChild(i);
+            string cname = child->getName();
+            int index = child->getIndex();
+            string name = "";
+            string type = "";
+            SGPropertyNode *src_prop = NULL;
+           double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0;
+            if ( cname == "analog-out" ) {
+                SGPropertyNode *prop;
+                prop = child->getChild( "name" );
+                if ( prop != NULL ) {
+                    name = prop->getStringValue();
+                }
+                prop = child->getChild( "type" );
+                if ( prop != NULL ) {
+                    type = prop->getStringValue();
+                }
+                prop = child->getChild( "prop" );
+                if ( prop != NULL ) {
+                    src_prop = fgGetNode( prop->getStringValue(), true );
+                }
+                prop = child->getChild( "value-lo" );
+                if ( prop != NULL ) {
+                   x0 = prop->getDoubleValue();
+                }
+                prop = child->getChild( "meter-lo" );
+                if ( prop != NULL ) {
+                   y0 = prop->getDoubleValue();
+                }
+                prop = child->getChild( "value-hi" );
+                if ( prop != NULL ) {
+                   x1 = prop->getDoubleValue();
+                }
+                prop = child->getChild( "meter-hi" );
+                if ( prop != NULL ) {
+                   y1 = prop->getDoubleValue();
+                }
+               // crunch linear interpolation formula
+               double dx = x1 - x0;
+               double dy = y1 - y0;
+               double slope = dy / dx;
+               double value = src_prop->getDoubleValue();
+               int meter = (value - x0) * slope + y0;
+               if ( meter < 0 ) { meter = 0; }
+               if ( meter > 1023 ) { meter = 1023; }
+               analog_out_data[2*index] = meter / 256;
+               analog_out_data[2*index + 1] = meter - analog_out_data[2*index] * 256;
+           } else {
+                SG_LOG( SG_IO, SG_DEBUG,
+                        "Input config error, expecting 'analog-out' but found "
+                        << cname );
+            }
+           ATCSetAnalogOut( analog_out_fd, analog_out_data );
+        }
+    }
+
+    return true;
+}
+
+
 /////////////////////////////////////////////////////////////////////
 // Write the lights
 /////////////////////////////////////////////////////////////////////
@@ -933,6 +1053,7 @@ bool FGATCOutput::process() {
        return false;
     }
 
+    do_analog_out();
     do_lamps();
     do_radio_display();
 #ifdef ATCFLIGHTSIM_HAVE_COMPASS