]> 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 29ae37f05239bf3cab35017fbadf1269aad55386..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 STL_STRING
+#include <errno.h>
+#include <math.h>
+
+#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;
 
 
 
 // Lock the ATC hardware
 static int ATCLock( int fd ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -57,11 +65,15 @@ static int ATCLock( int fd ) {
     }
 
     return result;
+#else
+    return -1;
+#endif
 }
 
 
 // Release the ATC hardware
 static int ATCRelease( int fd ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -74,6 +86,9 @@ static int ATCRelease( int fd ) {
     }
 
     return result;
+#else
+    return -1;
+#endif
 }
 
 
@@ -82,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)
@@ -91,8 +107,30 @@ 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__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -103,6 +141,9 @@ static int ATCSetRadios( int fd, unsigned char data[ATC_RADIO_DISPLAY_BYTES] ) {
     }
 
     return result;
+#else
+    return -1;
+#endif
 }
 
 
@@ -110,6 +151,7 @@ static int ATCSetRadios( int fd, unsigned char data[ATC_RADIO_DISPLAY_BYTES] ) {
 static int ATCSetStepper( int fd, unsigned char channel,
                              unsigned char value )
 {
+#if defined( unix ) || defined( __CYGWIN__ )
     // rewind
     lseek( fd, 0, SEEK_SET );
 
@@ -125,11 +167,16 @@ static int ATCSetStepper( int fd, unsigned char channel,
     SG_LOG( SG_IO, SG_DEBUG,
            "Sent cmd = " << (int)channel << " value = " << (int)value );
     return result;
+#else
+    return -1;
+#endif
 }
 
 
+#ifdef ATCFLIGHTSIM_HAVE_COMPASS
 // Read status of last stepper written to
 static unsigned char ATCReadStepper( int fd ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     int result;
 
     // rewind
@@ -145,11 +192,16 @@ static unsigned char ATCReadStepper( int fd ) {
     SG_LOG( SG_IO, SG_DEBUG, "Read result = " << (int)buf[0] );
 
     return buf[0];
+#else
+    return 0;
+#endif
 }
+#endif
 
 
 // Turn a lamp on or off
 void ATCSetLamp( int fd, int channel, bool value ) {
+#if defined( unix ) || defined( __CYGWIN__ )
     // lamp channels 0-63 are written to LampPort0, channels 64-127
     // are written to LampPort1
 
@@ -168,6 +220,7 @@ void ATCSetLamp( int fd, int channel, bool value ) {
         SG_LOG( SG_IO, SG_ALERT,  "Write failed" );
         exit( -1 );
     }
+#endif
 }
 
 
@@ -203,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,
@@ -216,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 );
@@ -245,6 +309,7 @@ bool FGATCOutput::open( int lock_fd ) {
 
 #endif
 
+#ifdef ATCFLIGHTSIM_HAVE_COMPASS
     /////////////////////////////////////////////////////////////////////
     // Home the compass stepper motor
     /////////////////////////////////////////////////////////////////////
@@ -283,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);
@@ -295,6 +358,24 @@ 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
@@ -308,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 );
@@ -340,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 );
 
@@ -353,12 +432,80 @@ 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
 /////////////////////////////////////////////////////////////////////
 
 bool FGATCOutput::do_lamps() {
-
     if ( lamps_out_node != NULL ) {
         for ( int i = 0; i < lamps_out_node->nChildren(); ++i ) {
             // read the next config entry from the property tree
@@ -442,7 +589,7 @@ static bool xpdr_has_power() {
     static SGPropertyNode *xpdr_bus_power
         = fgGetNode( "/systems/electrical/outputs/transponder", true );
     static SGPropertyNode *xpdr_func_knob
-        = fgGetNode( "/instrumentation/kt-70/inputs/func-knob", true );
+        = fgGetNode( "/instrumentation/transponder/inputs/func-knob", true );
 
     return (xpdr_bus_power->getDoubleValue() > 1.0)
         && (xpdr_func_knob->getIntValue() > 0);
@@ -506,13 +653,13 @@ bool FGATCOutput::do_radio_display() {
         = fgGetNode( "/instrumentation/kr-87/outputs/elapsed-timer", true );
 
     static SGPropertyNode *xpdr_serviceable
-        = fgGetNode( "/instrumentation/kt-70/inputs/serviceable", true );
+        = fgGetNode( "/instrumentation/transponder/inputs/serviceable", true );
     static SGPropertyNode *xpdr_func_knob
-        = fgGetNode( "/instrumentation/kt-70/inputs/func-knob", true );
+        = fgGetNode( "/instrumentation/transponder/inputs/func-knob", true );
     static SGPropertyNode *xpdr_flight_level
-        = fgGetNode( "/instrumentation/kt-70/outputs/flight-level", true );
+        = fgGetNode( "/instrumentation/transponder/outputs/flight-level", true );
     static SGPropertyNode *xpdr_id_code
-        = fgGetNode( "/instrumentation/kt-70/outputs/id-code", true );
+        = fgGetNode( "/instrumentation/transponder/outputs/id-code", true );
 
     char digits[10];
     int i;
@@ -906,9 +1053,12 @@ bool FGATCOutput::process() {
        return false;
     }
 
+    do_analog_out();
     do_lamps();
     do_radio_display();
+#ifdef ATCFLIGHTSIM_HAVE_COMPASS
     do_steppers();
+#endif
        
     return true;
 }