fgfs_SOURCES = \
fg_init.cxx fg_init.hxx \
- fg_serial.cxx fg_serial.hxx \
+ fg_io.cxx fg_io.hxx \
keyboard.cxx keyboard.hxx \
main.cxx \
options.cxx options.hxx \
splash.cxx splash.hxx \
views.cxx views.hxx
+# fg_serial.cxx fg_serial.hxx \
+
fgfs_LDADD = \
$(top_builddir)/Simulator/Aircraft/libAircraft.a \
$(top_builddir)/Simulator/Astro/libAstro.a \
$(top_builddir)/Simulator/Controls/libControls.a \
$(top_builddir)/Simulator/FDM/libFlight.a \
$(top_builddir)/Simulator/FDM/Balloon/libBalloon.a \
- $(top_builddir)/Simulator/FDM/External/libExternal.a \
$(top_builddir)/Simulator/FDM/JSBsim/libJSBsim.a \
$(top_builddir)/Simulator/FDM/LaRCsim/libLaRCsim.a \
$(top_builddir)/Simulator/GUI/libGUI.a \
$(top_builddir)/Lib/Screen/libScreen.a \
$(top_builddir)/Lib/Math/libMath.a \
$(top_builddir)/Lib/Bucket/libBucket.a \
- $(top_builddir)/Lib/Voronoi/libVoronoi.a \
$(top_builddir)/Lib/Debug/libDebug.a \
-lpu -lfnt -lssg -lsg \
$(top_builddir)/Lib/Misc/libMisc.a \
#include <Autopilot/autopilot.hxx>
#include <Cockpit/cockpit.hxx>
#include <FDM/Balloon.h>
+#include <FDM/External.hxx>
#include <FDM/JSBsim.hxx>
#include <FDM/LaRCsim.hxx>
#include <FDM/MagicCarpet.hxx>
#endif
#include "fg_init.hxx"
+#include "fg_io.hxx"
#include "options.hxx"
#include "views.hxx"
-#include "fg_serial.hxx"
#if defined(FX) && defined(XMESA)
#include <GL/xmesa.h>
// General house keeping initializations
bool fgInitGeneral( void ) {
string root;
+
+#if defined(FX) && defined(XMESA)
char *mesa_win_state;
+#endif
FG_LOG( FG_GENERAL, FG_INFO, "General Initialization" );
FG_LOG( FG_GENERAL, FG_INFO, "======= ==============" );
} else if ( current_options.get_flight_model() ==
FGInterface::FG_MAGICCARPET ) {
cur_fdm_state = new FGMagicCarpet;
+ } else if ( current_options.get_flight_model() ==
+ FGInterface::FG_EXTERNAL ) {
+ cur_fdm_state = new FGExternal;
} else {
FG_LOG( FG_GENERAL, FG_ALERT,
"No flight model, can't init aircraft" );
// Autopilot init added here, by Jeff Goeke-Smith
fgAPInit(¤t_aircraft);
- // Initialize serial ports
+ // Initialize I/O channels
#if ! defined( MACOS )
- fgSerialInit();
+ fgIOInit();
#endif
FG_LOG( FG_GENERAL, FG_INFO, endl);
--- /dev/null
+// fg_io.cxx -- higher level I/O channel management routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Include/compiler.h>
+
+// #ifdef FG_HAVE_STD_INCLUDES
+// # include <cmath>
+// # include <cstdlib> // atoi()
+// #else
+// # include <math.h>
+// # include <stdlib.h> // atoi()
+// #endif
+
+#include STL_STRING
+// #include STL_IOSTREAM
+// #include <vector>
+
+#include <Debug/logstream.hxx>
+// #include <Aircraft/aircraft.hxx>
+// #include <Include/fg_constants.h>
+#include <Include/fg_types.hxx>
+#include <Main/options.hxx>
+
+#include <Network/iochannel.hxx>
+#include <Network/fg_file.hxx>
+#include <Network/fg_serial.hxx>
+
+#include <Network/protocol.hxx>
+#include <Network/garmin.hxx>
+#include <Network/nmea.hxx>
+
+// #include <Time/fg_time.hxx>
+#include <Time/timestamp.hxx>
+
+FG_USING_STD(string);
+
+
+// define the global I/O channel list
+io_container global_io_list;
+
+
+// configure a port based on the config string
+static FGProtocol *parse_port_config( const string& config )
+{
+ string::size_type begin, end;
+
+ begin = 0;
+
+ FG_LOG( FG_IO, FG_INFO, "Parse I/O channel request: " << config );
+
+ // determine protocol
+ end = config.find(",", begin);
+ if ( end == string::npos ) {
+ return NULL; // dummy
+ }
+
+ string protocol = config.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " protocol = " << protocol );
+
+ FGProtocol *io;
+ if ( protocol == "nmea" ) {
+ FGNMEA *nmea = new FGNMEA;
+ io = nmea;
+ } else if ( protocol == "garmin" ) {
+ FGGarmin *garmin = new FGGarmin;
+ io = garmin;
+ } else {
+ return NULL;
+ }
+
+ // determine medium
+ end = config.find(",", begin);
+ if ( end == string::npos ) {
+ return NULL; // dummy
+ }
+
+ string medium = config.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " medium = " << medium );
+
+ // determine direction
+ end = config.find(",", begin);
+ if ( end == string::npos ) {
+ return NULL; // dummy
+ }
+
+ string direction = config.substr(begin, end - begin);
+ begin = end + 1;
+ io->set_direction( direction );
+ FG_LOG( FG_IO, FG_INFO, " direction = " << direction );
+
+ // determine hertz
+ end = config.find(",", begin);
+ if ( end == string::npos ) {
+ return NULL; // dummy
+ }
+
+ string hertz_str = config.substr(begin, end - begin);
+ begin = end + 1;
+ double hertz = atof( hertz_str.c_str() );
+ io->set_hz( hertz );
+ FG_LOG( FG_IO, FG_INFO, " hertz = " << hertz );
+
+ if ( medium == "serial" ) {
+ FGSerial *ch = new FGSerial;
+ io->set_io_channel( ch );
+
+ // device name
+ end = config.find(",", begin);
+ if ( end == string::npos ) {
+ return NULL;
+ }
+
+ ch->set_device( config.substr(begin, end - begin) );
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " device = " << ch->get_device() );
+
+ // baud
+ ch->set_baud( config.substr(begin) );
+ FG_LOG( FG_IO, FG_INFO, " baud = " << ch->get_baud() );
+
+ io->set_io_channel( ch );
+ } else if ( medium == "file" ) {
+ FGFile *ch = new FGFile;
+
+ // file name
+ ch->set_file_name( config.substr(begin) );
+ FG_LOG( FG_IO, FG_INFO, " file name = " << ch->get_file_name() );
+
+ io->set_io_channel( ch );
+ } else if ( medium == "socket" ) {
+ // ch = new FGSocket;
+ }
+
+ return io;
+}
+
+
+// step through the port config streams (from fgOPTIONS) and setup
+// serial port channels for each
+void fgIOInit() {
+ FGProtocol *p;
+ string_list channel_options_list =
+ current_options.get_channel_options_list();
+
+ // we could almost do this in a single step except pushing a valid
+ // port onto the port list copies the structure and destroys the
+ // original, which closes the port and frees up the fd ... doh!!!
+
+ // parse the configuration strings and store the results in the
+ // appropriate FGIOChannel structures
+ for ( int i = 0; i < (int)channel_options_list.size(); ++i ) {
+ p = parse_port_config( channel_options_list[i] );
+ if ( p != NULL ) {
+ p->open();
+ global_io_list.push_back( p );
+ if ( !p->is_enabled() ) {
+ FG_LOG( FG_IO, FG_INFO, "I/O Channel config failed." );
+ }
+ } else {
+ FG_LOG( FG_IO, FG_INFO, "I/O Channel parse failed." );
+ }
+ }
+}
+
+
+static void send_fgfs_out( FGIOChannel *p ) {
+}
+
+static void read_fgfs_in( FGIOChannel *p ) {
+}
+
+
+// "RUL" output format (for some sort of motion platform)
+//
+// The Baud rate is 2400 , one start bit, eight data bits, 1 stop bit,
+// no parity.
+//
+// For position it requires a 3-byte data packet defined as follows:
+//
+// First bite: ascII character "P" ( 0x50 or 80 decimal )
+// Second byte X pos. (1-255) 1 being 0* and 255 being 359*
+// Third byte Y pos.( 1-255) 1 being 0* and 255 359*
+//
+// So sending 80 127 127 to the two axis motors will position on 180*
+// The RS- 232 port is a nine pin connector and the only pins used are
+// 3&5.
+
+static void send_rul_out( FGIOChannel *p ) {
+#if 0
+ char rul[256];
+
+ FGInterface *f;
+ FGTime *t;
+
+ f = current_aircraft.fdm_state;
+ t = FGTime::cur_time_params;
+
+ // run as often as possibleonce per second
+
+ // this runs once per second
+ // if ( p->last_time == t->get_cur_time() ) {
+ // return;
+ // }
+ // p->last_time = t->get_cur_time();
+ // if ( t->get_cur_time() % 2 != 0 ) {
+ // return;
+ // }
+
+ // get roll and pitch, convert to degrees
+ double roll_deg = f->get_Phi() * RAD_TO_DEG;
+ while ( roll_deg < -180.0 ) {
+ roll_deg += 360.0;
+ }
+ while ( roll_deg > 180.0 ) {
+ roll_deg -= 360.0;
+ }
+
+ double pitch_deg = f->get_Theta() * RAD_TO_DEG;
+ while ( pitch_deg < -180.0 ) {
+ pitch_deg += 360.0;
+ }
+ while ( pitch_deg > 180.0 ) {
+ pitch_deg -= 360.0;
+ }
+
+ // scale roll and pitch to output format (1 - 255)
+ // straight && level == (128, 128)
+
+ int roll = (int)( (roll_deg+180.0) * 255.0 / 360.0) + 1;
+ int pitch = (int)( (pitch_deg+180.0) * 255.0 / 360.0) + 1;
+
+ sprintf( rul, "p%c%c\n", roll, pitch);
+
+ FG_LOG( FG_IO, FG_INFO, "p " << roll << " " << pitch );
+
+ string rul_sentence = rul;
+ p->port.write_port(rul_sentence);
+#endif
+}
+
+
+// "PVE" (ProVision Entertainment) output format (for some sort of
+// motion platform)
+//
+// Outputs a 5-byte data packet defined as follows:
+//
+// First bite: ASCII character "P" ( 0x50 or 80 decimal )
+// Second byte: "roll" value (1-255) 1 being 0* and 255 being 359*
+// Third byte: "pitch" value (1-255) 1 being 0* and 255 being 359*
+// Fourth byte: "heave" value (or vertical acceleration?)
+//
+// So sending 80 127 127 to the two axis motors will position on 180*
+// The RS- 232 port is a nine pin connector and the only pins used are
+// 3&5.
+
+static void send_pve_out( FGIOChannel *p ) {
+#if 0
+ char pve[256];
+
+ FGInterface *f;
+ FGTime *t;
+
+
+ f = current_aircraft.fdm_state;
+ t = FGTime::cur_time_params;
+
+ // run as often as possibleonce per second
+
+ // this runs once per second
+ // if ( p->last_time == t->get_cur_time() ) {
+ // return;
+ // }
+ // p->last_time = t->get_cur_time();
+ // if ( t->get_cur_time() % 2 != 0 ) {
+ // return;
+ // }
+
+ // get roll and pitch, convert to degrees
+ double roll_deg = f->get_Phi() * RAD_TO_DEG;
+ while ( roll_deg <= -180.0 ) {
+ roll_deg += 360.0;
+ }
+ while ( roll_deg > 180.0 ) {
+ roll_deg -= 360.0;
+ }
+
+ double pitch_deg = f->get_Theta() * RAD_TO_DEG;
+ while ( pitch_deg <= -180.0 ) {
+ pitch_deg += 360.0;
+ }
+ while ( pitch_deg > 180.0 ) {
+ pitch_deg -= 360.0;
+ }
+
+ short int heave = (int)(f->get_W_body() * 128.0);
+
+ // scale roll and pitch to output format (1 - 255)
+ // straight && level == (128, 128)
+
+ short int roll = (int)(roll_deg * 32768 / 180.0);
+ short int pitch = (int)(pitch_deg * 32768 / 180.0);
+
+ unsigned char roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2;
+ roll_b1 = roll >> 8;
+ roll_b2 = roll & 0x00ff;
+ pitch_b1 = pitch >> 8;
+ pitch_b2 = pitch & 0x00ff;
+ heave_b1 = heave >> 8;
+ heave_b2 = heave & 0x00ff;
+
+ sprintf( pve, "p%c%c%c%c%c%c\n",
+ roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
+
+ // printf( "p [ %u %u ] [ %u %u ] [ %u %u ]\n",
+ // roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
+
+ FG_LOG( FG_IO, FG_INFO, "roll=" << roll << " pitch=" << pitch <<
+ " heave=" << heave );
+
+ string pve_sentence = pve;
+ p->port.write_port(pve_sentence);
+#endif
+}
+
+
+// one more level of indirection ...
+static void process_port( FGIOChannel *p ) {
+#if 0
+ if ( p->kind == fgIOCHANNEL::FG_SERIAL_NMEA_OUT ) {
+ send_nmea_out(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_NMEA_IN ) {
+ read_nmea_in(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_GARMIN_OUT ) {
+ send_garmin_out(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_GARMIN_IN ) {
+ read_garmin_in(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_FGFS_OUT ) {
+ send_fgfs_out(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_FGFS_IN ) {
+ read_fgfs_in(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_RUL_OUT ) {
+ send_rul_out(p);
+ } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_PVE_OUT ) {
+ send_pve_out(p);
+ }
+#endif
+}
+
+
+// process any serial port work
+void fgIOProcess() {
+ FGProtocol *p;
+
+ // cout << "processing I/O channels" << endl;
+
+ static int inited = 0;
+ int interval;
+ static FGTimeStamp last;
+ FGTimeStamp current;
+
+ if ( ! inited ) {
+ inited = 1;
+ last.stamp();
+ interval = 0;
+ } else {
+ current.stamp();
+ interval = current - last;
+ last = current;
+ }
+
+ for ( int i = 0; i < (int)global_io_list.size(); ++i ) {
+ // cout << " channel = " << i << endl;
+ p = global_io_list[i];
+
+ if ( p->is_enabled() ) {
+ p->dec_count_down( interval );
+ if ( p->get_count_down() < 0 ) {
+ p->process();
+ p->set_count_down( 1000000.0 / p->get_hz() );
+ }
+ }
+ }
+}
--- /dev/null
+// fg_io.hxx -- Higher level I/O managment routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _FG_IO_HXX
+#define _FG_IO_HXX
+
+
+#include "Include/compiler.h"
+
+// #include <string>
+
+// #ifdef FG_HAVE_STD_INCLUDES
+// # include <ctime>
+// #else
+// # include <time.h>
+// #endif
+
+#include <Network/iochannel.hxx>
+
+
+// initialize I/O channels based on command line options (if any)
+void fgIOInit();
+
+
+// process any I/O work
+void fgIOProcess();
+
+
+#endif // _FG_IO_HXX
+
+
+++ /dev/null
-// fg_serial.cxx -- higher level serial port management routines
-//
-// Written by Curtis Olson, started November 1998.
-//
-// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// 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.
-//
-// $Id$
-
-
-#include <Include/compiler.h>
-
-#ifdef FG_HAVE_STD_INCLUDES
-# include <cmath>
-# include <cstdlib> // atoi()
-#else
-# include <math.h>
-# include <stdlib.h> // atoi()
-#endif
-
-#include STL_STRING
-#include STL_IOSTREAM
-#include <vector>
-
-#include <Debug/logstream.hxx>
-#include <Aircraft/aircraft.hxx>
-#include <Include/fg_constants.h>
-#include <Serial/serial.hxx>
-#include <Time/fg_time.hxx>
-
-#include "options.hxx"
-
-#include "fg_serial.hxx"
-
-FG_USING_STD(string);
-FG_USING_STD(vector);
-
-// support an arbitrary number of serial channels. Each channel can
-// be assigned to an arbitrary port. Bi-directional communication is
-// supported by the underlying layer, but probably will never be
-// needed by FGFS?
-
-typedef vector < fgIOCHANNEL > io_container;
-typedef io_container::iterator io_iterator;
-typedef io_container::const_iterator const_io_iterator;
-
-// define the four channels
-io_container port_list;
-
-
-fgIOCHANNEL::fgIOCHANNEL() :
- kind( FG_SERIAL_DISABLED ),
- valid_config( false )
-{
-}
-
-
-fgIOCHANNEL::~fgIOCHANNEL() {
-}
-
-
-// configure a port based on the config string
-static fgIOCHANNEL parse_port_config( const string& config )
-{
- fgIOCHANNEL p;
-
- string::size_type begin, end;
-
- begin = 0;
-
- FG_LOG( FG_SERIAL, FG_INFO, "Parse serial port config: " << config );
-
- // device name
- end = config.find(",", begin);
- if ( end == string::npos ) {
- return p;
- }
-
- p.device = config.substr(begin, end - begin);
- begin = end + 1;
- FG_LOG( FG_SERIAL, FG_INFO, " device = " << p.device );
-
- // format
- end = config.find(",", begin);
- if ( end == string::npos ) {
- return p;
- }
-
- p.format = config.substr(begin, end - begin);
- begin = end + 1;
- FG_LOG( FG_SERIAL, FG_INFO, " format = " << p.format );
-
- // baud
- end = config.find(",", begin);
- if ( end == string::npos ) {
- return p;
- }
-
- p.baud = config.substr(begin, end - begin);
- begin = end + 1;
- FG_LOG( FG_SERIAL, FG_INFO, " baud = " << p.baud );
-
- // direction
- p.direction = config.substr(begin);
- FG_LOG( FG_SERIAL, FG_INFO, " direction = " << p.direction );
-
- p.valid_config = true;
-
- return p;
-}
-
-
-// configure a port based on the config info
-static bool config_port( fgIOCHANNEL &p )
-{
- if ( p.port.is_enabled() ) {
- FG_LOG( FG_SERIAL, FG_ALERT, "This shouldn't happen, but the port "
- << "is already in use, ignoring" );
- return false;
- }
-
- if ( ! p.port.open_port( p.device ) ) {
- FG_LOG( FG_SERIAL, FG_ALERT, "Error opening device: " << p.device );
- return false;
- }
-
- // cout << "fd = " << p.port.fd << endl;
-
- if ( ! p.port.set_baud( atoi( p.baud.c_str() ) ) ) {
- FG_LOG( FG_SERIAL, FG_ALERT, "Error setting baud: " << p.baud );
- return false;
- }
-
- if ( p.format == "nmea" ) {
- if ( p.direction == "out" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_OUT;
- } else if ( p.direction == "in" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_IN;
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
- return false;
- }
- } else if ( p.format == "garmin" ) {
- if ( p.direction == "out" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_GARMIN_OUT;
- } else if ( p.direction == "in" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_GARMIN_IN;
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
- return false;
- }
- } else if ( p.format == "fgfs" ) {
- if ( p.direction == "out" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_OUT;
- } else if ( p.direction == "in" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_IN;
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
- return false;
- }
- } else if ( p.format == "rul" ) {
- if ( p.direction == "out" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_RUL_OUT;
- } else if ( p.direction == "in" ) {
- FG_LOG( FG_SERIAL, FG_ALERT, "RUL format is outgoing only" );
- return false;
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
- return false;
- }
- } else if ( p.format == "pve" ) {
- if ( p.direction == "out" ) {
- p.kind = fgIOCHANNEL::FG_SERIAL_PVE_OUT;
- } else if ( p.direction == "in" ) {
- FG_LOG( FG_SERIAL, FG_ALERT,
- "ProVision Entertainment format is outgoing only" );
- return false;
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
- return false;
- }
- } else {
- FG_LOG( FG_SERIAL, FG_ALERT, "Unknown format" );
- return false;
- }
-
- return true;
-}
-
-
-// step through the port config streams (from fgOPTIONS) and setup
-// serial port channels for each
-void fgSerialInit() {
- fgIOCHANNEL port;
- bool result;
- str_container port_options_list = current_options.get_port_options_list();
-
- // we could almost do this in a single step except pushing a valid
- // port onto the port list copies the structure and destroys the
- // original, which closes the port and frees up the fd ... doh!!!
-
- // parse the configuration strings and store the results in stub
- // fgIOCHANNEL structures
- const_str_iterator current_str = port_options_list.begin();
- const_str_iterator last_str = port_options_list.end();
- for ( ; current_str != last_str; ++current_str ) {
- port = parse_port_config( *current_str );
- if ( port.valid_config ) {
- result = config_port( port );
- if ( result ) {
- port_list.push_back( port );
- }
- }
- }
-}
-
-
-char calc_nmea_cksum(char *sentence) {
- unsigned char sum = 0;
- int i, len;
-
- // printf("%s\n", sentence);
-
- len = strlen(sentence);
- sum = sentence[0];
- for ( i = 1; i < len; i++ ) {
- // printf("%c", sentence[i]);
- sum ^= sentence[i];
- }
- // printf("\n");
-
- // printf("sum = %02x\n", sum);
- return sum;
-}
-
-
-static void send_nmea_out( fgIOCHANNEL *p ) {
- char rmc[256], gga[256];
- char rmc_sum[10], gga_sum[10];
- char dir;
- int deg;
- double min;
- FGInterface *f;
- FGTime *t;
-
- f = current_aircraft.fdm_state;
- t = FGTime::cur_time_params;
-
- // run once every two seconds
- if ( p->last_time == t->get_cur_time() ) {
- return;
- }
- p->last_time = t->get_cur_time();
- if ( t->get_cur_time() % 2 != 0 ) {
- return;
- }
-
- char utc[10];
- sprintf( utc, "%02d%02d%02d",
- t->getGmt()->tm_hour, t->getGmt()->tm_min, t->getGmt()->tm_sec );
-
- char lat[20];
- double latd = f->get_Latitude() * RAD_TO_DEG;
- if ( latd < 0.0 ) {
- latd *= -1.0;
- dir = 'S';
- } else {
- dir = 'N';
- }
- deg = (int)(latd);
- min = (latd - (double)deg) * 60.0;
- sprintf( lat, "%02d%06.3f,%c", abs(deg), min, dir);
-
- char lon[20];
- double lond = f->get_Longitude() * RAD_TO_DEG;
- if ( lond < 0.0 ) {
- lond *= -1.0;
- dir = 'W';
- } else {
- dir = 'E';
- }
- deg = (int)(lond);
- min = (lond - (double)deg) * 60.0;
- sprintf( lon, "%03d%06.3f,%c", abs(deg), min, dir);
-
- char speed[10];
- sprintf( speed, "%05.1f", f->get_V_equiv_kts() );
-
- char heading[10];
- sprintf( heading, "%05.1f", f->get_Psi() * RAD_TO_DEG );
-
- char altitude_m[10];
- sprintf( altitude_m, "%02d", (int)(f->get_Altitude() * FEET_TO_METER) );
-
- char altitude_ft[10];
- sprintf( altitude_ft, "%02d", (int)f->get_Altitude() );
-
- char date[10];
- sprintf( date, "%02d%02d%02d", t->getGmt()->tm_mday,
- t->getGmt()->tm_mon+1, t->getGmt()->tm_year );
-
- // $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
- sprintf( rmc, "GPRMC,%s,A,%s,%s,%s,%s,%s,0.000,E",
- utc, lat, lon, speed, heading, date );
- sprintf( rmc_sum, "%02X", calc_nmea_cksum(rmc) );
-
- sprintf( gga, "GPGGA,%s,%s,%s,1,,,%s,F,,,,",
- utc, lat, lon, altitude_ft );
- sprintf( gga_sum, "%02X", calc_nmea_cksum(gga) );
-
-
- FG_LOG( FG_SERIAL, FG_DEBUG, rmc );
- FG_LOG( FG_SERIAL, FG_DEBUG, gga );
-
- // RMC sentence
- string rmc_sentence = "$";
- rmc_sentence += rmc;
- rmc_sentence += "*";
- rmc_sentence += rmc_sum;
- rmc_sentence += "\n";
- p->port.write_port(rmc_sentence);
- // cout << rmc_sentence;
-
- // GGA sentence
- string gga_sentence = "$";
- gga_sentence += gga;
- gga_sentence += "*";
- gga_sentence += gga_sum;
- gga_sentence += "\n";
- p->port.write_port(gga_sentence);
- // cout << gga_sentence;
-}
-
-static void read_nmea_in( fgIOCHANNEL *p ) {
-}
-
-static void send_garmin_out( fgIOCHANNEL *p ) {
- char rmc[256], rmc_sum[256], rmz[256], rmz_sum[256];
- char dir;
- int deg;
- double min;
- FGInterface *f;
- FGTime *t;
-
- f = current_aircraft.fdm_state;
- t = FGTime::cur_time_params;
-
- // run once per second
- if ( p->last_time == t->get_cur_time() ) {
- return;
- }
- p->last_time = t->get_cur_time();
- if ( t->get_cur_time() % 2 != 0 ) {
- return;
- }
-
- char utc[10];
- sprintf( utc, "%02d%02d%02d",
- t->getGmt()->tm_hour, t->getGmt()->tm_min, t->getGmt()->tm_sec );
-
- char lat[20];
- double latd = f->get_Latitude() * RAD_TO_DEG;
- if ( latd < 0.0 ) {
- latd *= -1.0;
- dir = 'S';
- } else {
- dir = 'N';
- }
- deg = (int)(latd);
- min = (latd - (double)deg) * 60.0;
- sprintf( lat, "%02d%06.3f,%c", abs(deg), min, dir);
-
- char lon[20];
- double lond = f->get_Longitude() * RAD_TO_DEG;
- if ( lond < 0.0 ) {
- lond *= -1.0;
- dir = 'W';
- } else {
- dir = 'E';
- }
- deg = (int)(lond);
- min = (lond - (double)deg) * 60.0;
- sprintf( lon, "%03d%06.3f,%c", abs(deg), min, dir);
-
- char speed[10];
- sprintf( speed, "%05.1f", f->get_V_equiv_kts() );
-
- char heading[10];
- sprintf( heading, "%05.1f", f->get_Psi() * RAD_TO_DEG );
-
- char altitude_m[10];
- sprintf( altitude_m, "%02d", (int)(f->get_Altitude() * FEET_TO_METER) );
-
- char altitude_ft[10];
- sprintf( altitude_ft, "%02d", (int)f->get_Altitude() );
-
- char date[10];
- sprintf( date, "%02d%02d%02d", t->getGmt()->tm_mday,
- t->getGmt()->tm_mon+1, t->getGmt()->tm_year );
-
- // $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
- sprintf( rmc, "GPRMC,%s,A,%s,%s,%s,%s,%s,000.0,E",
- utc, lat, lon, speed, heading, date );
- sprintf( rmc_sum, "%02X", calc_nmea_cksum(rmc) );
-
- // sprintf( gga, "$GPGGA,%s,%s,%s,1,04,0.0,%s,M,00.0,M,,*00\r\n",
- // utc, lat, lon, altitude_m );
-
- sprintf( rmz, "PGRMZ,%s,f,3", altitude_ft );
- sprintf( rmz_sum, "%02X", calc_nmea_cksum(rmz) );
-
- FG_LOG( FG_SERIAL, FG_DEBUG, rmc );
- FG_LOG( FG_SERIAL, FG_DEBUG, rmz );
-
- // RMC sentence
- string rmc_sentence = "$";
- rmc_sentence += rmc;
- rmc_sentence += "*";
- rmc_sentence += rmc_sum;
- rmc_sentence += "\n";
- p->port.write_port(rmc_sentence);
- // cout << rmc_sentence;
-
- // RMZ sentence (garmin proprietary)
- string rmz_sentence = "$";
- rmz_sentence += rmz;
- rmz_sentence += "*";
- rmz_sentence += rmz_sum;
- rmz_sentence += "\n";
- p->port.write_port(rmz_sentence);
- // cout << rmz_sentence;
-}
-
-static void read_garmin_in( fgIOCHANNEL *p ) {
-}
-
-static void send_fgfs_out( fgIOCHANNEL *p ) {
-}
-
-static void read_fgfs_in( fgIOCHANNEL *p ) {
-}
-
-
-// "RUL" output format (for some sort of motion platform)
-//
-// The Baud rate is 2400 , one start bit, eight data bits, 1 stop bit,
-// no parity.
-//
-// For position it requires a 3-byte data packet defined as follows:
-//
-// First bite: ascII character "P" ( 0x50 or 80 decimal )
-// Second byte X pos. (1-255) 1 being 0* and 255 being 359*
-// Third byte Y pos.( 1-255) 1 being 0* and 255 359*
-//
-// So sending 80 127 127 to the two axis motors will position on 180*
-// The RS- 232 port is a nine pin connector and the only pins used are
-// 3&5.
-
-static void send_rul_out( fgIOCHANNEL *p ) {
- char rul[256];
-
- FGInterface *f;
- FGTime *t;
-
- f = current_aircraft.fdm_state;
- t = FGTime::cur_time_params;
-
- // run as often as possibleonce per second
-
- // this runs once per second
- // if ( p->last_time == t->get_cur_time() ) {
- // return;
- // }
- // p->last_time = t->get_cur_time();
- // if ( t->get_cur_time() % 2 != 0 ) {
- // return;
- // }
-
- // get roll and pitch, convert to degrees
- double roll_deg = f->get_Phi() * RAD_TO_DEG;
- while ( roll_deg < -180.0 ) {
- roll_deg += 360.0;
- }
- while ( roll_deg > 180.0 ) {
- roll_deg -= 360.0;
- }
-
- double pitch_deg = f->get_Theta() * RAD_TO_DEG;
- while ( pitch_deg < -180.0 ) {
- pitch_deg += 360.0;
- }
- while ( pitch_deg > 180.0 ) {
- pitch_deg -= 360.0;
- }
-
- // scale roll and pitch to output format (1 - 255)
- // straight && level == (128, 128)
-
- int roll = (int)( (roll_deg+180.0) * 255.0 / 360.0) + 1;
- int pitch = (int)( (pitch_deg+180.0) * 255.0 / 360.0) + 1;
-
- sprintf( rul, "p%c%c\n", roll, pitch);
-
- FG_LOG( FG_SERIAL, FG_INFO, "p " << roll << " " << pitch );
-
- string rul_sentence = rul;
- p->port.write_port(rul_sentence);
-}
-
-
-// "PVE" (ProVision Entertainment) output format (for some sort of
-// motion platform)
-//
-// Outputs a 5-byte data packet defined as follows:
-//
-// First bite: ASCII character "P" ( 0x50 or 80 decimal )
-// Second byte: "roll" value (1-255) 1 being 0* and 255 being 359*
-// Third byte: "pitch" value (1-255) 1 being 0* and 255 being 359*
-// Fourth byte: "heave" value (or vertical acceleration?)
-//
-// So sending 80 127 127 to the two axis motors will position on 180*
-// The RS- 232 port is a nine pin connector and the only pins used are
-// 3&5.
-
-static void send_pve_out( fgIOCHANNEL *p ) {
- char pve[256];
-
- FGInterface *f;
- FGTime *t;
-
-
- f = current_aircraft.fdm_state;
- t = FGTime::cur_time_params;
-
- // run as often as possibleonce per second
-
- // this runs once per second
- // if ( p->last_time == t->get_cur_time() ) {
- // return;
- // }
- // p->last_time = t->get_cur_time();
- // if ( t->get_cur_time() % 2 != 0 ) {
- // return;
- // }
-
- // get roll and pitch, convert to degrees
- double roll_deg = f->get_Phi() * RAD_TO_DEG;
- while ( roll_deg <= -180.0 ) {
- roll_deg += 360.0;
- }
- while ( roll_deg > 180.0 ) {
- roll_deg -= 360.0;
- }
-
- double pitch_deg = f->get_Theta() * RAD_TO_DEG;
- while ( pitch_deg <= -180.0 ) {
- pitch_deg += 360.0;
- }
- while ( pitch_deg > 180.0 ) {
- pitch_deg -= 360.0;
- }
-
- short int heave = (int)(f->get_W_body() * 128.0);
-
- // scale roll and pitch to output format (1 - 255)
- // straight && level == (128, 128)
-
- short int roll = (int)(roll_deg * 32768 / 180.0);
- short int pitch = (int)(pitch_deg * 32768 / 180.0);
-
- unsigned char roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2;
- roll_b1 = roll >> 8;
- roll_b2 = roll & 0x00ff;
- pitch_b1 = pitch >> 8;
- pitch_b2 = pitch & 0x00ff;
- heave_b1 = heave >> 8;
- heave_b2 = heave & 0x00ff;
-
- sprintf( pve, "p%c%c%c%c%c%c\n",
- roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
-
- // printf( "p [ %u %u ] [ %u %u ] [ %u %u ]\n",
- // roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
-
- FG_LOG( FG_SERIAL, FG_INFO, "roll=" << roll << " pitch=" << pitch <<
- " heave=" << heave );
-
- string pve_sentence = pve;
- p->port.write_port(pve_sentence);
-}
-
-
-// one more level of indirection ...
-static void process_port( fgIOCHANNEL *p ) {
- if ( p->kind == fgIOCHANNEL::FG_SERIAL_NMEA_OUT ) {
- send_nmea_out(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_NMEA_IN ) {
- read_nmea_in(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_GARMIN_OUT ) {
- send_garmin_out(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_GARMIN_IN ) {
- read_garmin_in(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_FGFS_OUT ) {
- send_fgfs_out(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_FGFS_IN ) {
- read_fgfs_in(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_RUL_OUT ) {
- send_rul_out(p);
- } else if ( p->kind == fgIOCHANNEL::FG_SERIAL_PVE_OUT ) {
- send_pve_out(p);
- }
-}
-
-
-// process any serial port work
-void fgSerialProcess() {
- fgIOCHANNEL *port;
-
- io_iterator current = port_list.begin();
- io_iterator last = port_list.end();
-
- for ( ; current != last; ++current ) {
- port = current;
- if ( port->kind != fgIOCHANNEL::FG_SERIAL_DISABLED ) {
- process_port ( port );
- }
- }
-}
+++ /dev/null
-// fg_serial.hxx -- Higher level serial port managment routines
-//
-// Written by Curtis Olson, started November 1998.
-//
-// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// 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.
-//
-// $Id$
-
-
-#ifndef _FG_SERIAL_HXX
-#define _FG_SERIAL_HXX
-
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#include "Include/compiler.h"
-
-#include <string>
-
-#ifdef FG_HAVE_STD_INCLUDES
-# include <ctime>
-#else
-# include <time.h>
-#endif
-
-#include <Serial/serial.hxx>
-
-
-class fgIOCHANNEL {
-
-public:
-
- // Types of serial port protocols
- enum fgPortKind {
- FG_SERIAL_DISABLED = 0,
- FG_SERIAL_NMEA_OUT = 1,
- FG_SERIAL_NMEA_IN = 2,
- FG_SERIAL_GARMIN_OUT = 3,
- FG_SERIAL_GARMIN_IN = 4,
- FG_SERIAL_FGFS_OUT = 5,
- FG_SERIAL_FGFS_IN = 6,
-
- FG_SERIAL_RUL_OUT = 7, // Raul E Horcasitas <rul@compuserve.com>
- FG_SERIAL_PVE_OUT = 8 // "Jeff Vrachan"
- // <jeffv@provisionentertainment.com>
- };
-
- string device;
- string format;
- string baud;
- string direction;
-
- fgPortKind kind;
- fgSERIAL port;
- time_t last_time;
- bool valid_config;
-
- fgIOCHANNEL();
- ~fgIOCHANNEL();
-};
-
-
-// support up to four serial channels. Each channel can be assigned
-// to an arbitrary port. Bi-directional communication is supported by
-// the underlying layer.
-
-// define the four channels
-// extern fgIOCHANNEL port_a;
-// extern fgIOCHANNEL port_b;
-// extern fgIOCHANNEL port_c;
-// extern fgIOCHANNEL port_d;
-
-
-// initialize serial ports based on command line options (if any)
-void fgSerialInit();
-
-
-// process any serial port work
-void fgSerialProcess();
-
-
-#endif // _FG_SERIAL_HXX
-
-
#endif
#include "fg_init.hxx"
+#include "fg_io.hxx"
#include "keyboard.hxx"
#include "options.hxx"
#include "splash.hxx"
#include "views.hxx"
-#include "fg_serial.hxx"
// -dw- use custom sioux settings so I can see output window
}
#if ! defined( MACOS )
- // Do any serial port work that might need to be done
- fgSerialProcess();
+ // Do any I/O channel work that might need to be done
+ fgIOProcess();
#endif
// see if we need to load any new scenery tiles
#include <Time/fg_time.hxx>
#include "options.hxx"
-#include "fg_serial.hxx"
FG_USING_STD(string);
FG_USING_NAMESPACE(std);
net_id = "Johnney"; // default pilot's name
// initialize port config string list
- port_options_list.erase ( port_options_list.begin(),
- port_options_list.end() );
+ channel_options_list.clear();
}
void
}
-// Parse serial port option --serial=/dev/ttyS1,nmea,4800,out
+// Parse I/O channel option
//
-// Format is "--serial=device,format,baud,direction" where
+// Format is "--protocol=medium,direction,hz,medium_options,..."
+//
+// protocol = { nmea, garmin, fgfs, rul, pve, etc. }
+// medium = { serial, socket, file, etc. }
+// direction = { in, out, bi }
+// hz = number of times to process channel per second (floating
+// point values are ok.
+//
+// Serial example "--nmea=serial,dir,hz,device,baud" where
//
-// device = OS device name to be open()'ed
-// format = {nmea, garmin,fgfs,rul,pve}
+// device = OS device name of serial line to be open()'ed
// baud = {300, 1200, 2400, ..., 230400}
-// direction = {in, out, bi}
+//
+// Socket exacmple "--fgfs=socket,dir,hz,machine,port" where
+//
+// machine = machine name or ip address if client, leave empty if server
+// port = port, leave empty to let system choose
+//
+// File example "--garmin=file,dir,hz,filename" where
+//
+// filename = file system file name
bool
-fgOPTIONS::parse_serial( const string& serial_str ) {
- string::size_type pos;
-
- // cout << "Serial string = " << serial_str << endl;
-
- // a flailing attempt to see if the port config string has a
- // chance at being valid
- pos = serial_str.find(",");
- if ( pos == string::npos ) {
- FG_LOG( FG_GENERAL, FG_ALERT,
- "Malformed serial port configure string" );
- return false;
- }
-
- port_options_list.push_back( serial_str );
+fgOPTIONS::parse_channel( const string& type, const string& channel_str ) {
+ // cout << "Channel string = " << channel_str << endl;
+
+ channel_options_list.push_back( type + "," + channel_str );
return true;
}
tris_or_culled = 0;
} else if ( arg == "--hud-culled" ) {
tris_or_culled = 1;
- } else if ( arg.find( "--serial=" ) != string::npos ) {
- parse_serial( arg.substr(9) );
+ } else if ( arg.find( "--fgfs=" ) != string::npos ) {
+ parse_channel( "fgfs", arg.substr(7) );
+ } else if ( arg.find( "--garmin=" ) != string::npos ) {
+ parse_channel( "garmin", arg.substr(9) );
+ } else if ( arg.find( "--nmea=" ) != string::npos ) {
+ parse_channel( "nmea", arg.substr(7) );
#ifdef FG_NETWORK_OLK
} else if ( arg == "--net-hud" ) {
net_hud_display = 1;
extern bool global_fullscreen;
#endif
+#include <Include/fg_types.hxx>
+
#include STL_STRING
#include <vector>
FG_USING_STD(vector);
FG_USING_STD(string);
-typedef vector < string > str_container;
-typedef str_container::iterator str_iterator;
-typedef str_container::const_iterator const_str_iterator;
-
-
class fgOPTIONS {
public:
int time_offset_type; // Will be set to one of the FG_TIME_* enums,
// To deterine how time_offset should be used
- // Serial Ports, we currently support up to four channels
- // fgSerialPortKind port_a_kind; // Port a kind
- // fgSerialPortKind port_b_kind; // Port b kind
- // fgSerialPortKind port_c_kind; // Port c kind
- // fgSerialPortKind port_d_kind; // Port d kind
-
// Serial port configuration strings
- str_container port_options_list;
+ string_list channel_options_list;
// Network options
string net_id;
inline int get_time_offset() const { return time_offset; }
inline int get_time_offset_type() const { return time_offset_type; };
- inline str_container get_port_options_list() const {
- return port_options_list;
+ inline string_list get_channel_options_list() const {
+ return channel_options_list;
}
inline string get_net_id() const { return net_id; }
int parse_tile_radius( const string& arg );
int parse_fdm( const string& fm );
double parse_fov( const string& arg );
- bool parse_serial( const string& serial_str );
+ bool parse_channel( const string& type, const string& channel_str );
};
noinst_LIBRARIES = libNetwork.a
-libNetwork_a_SOURCES = net_hud.cxx network.cxx network.h
+libNetwork_a_SOURCES = \
+ iochannel.cxx iochannel.hxx \
+ fg_file.cxx fg_file.hxx \
+ fg_serial.cxx fg_serial.hxx \
+ protocol.cxx protocol.hxx \
+ garmin.cxx garmin.hxx \
+ nmea.cxx nmea.hxx \
+ net_hud.cxx network.cxx network.h
INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Simulator
--- /dev/null
+// fg_file.cxx -- File I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Include/compiler.h>
+
+#include STL_STRING
+
+#include <Debug/logstream.hxx>
+#include <Time/fg_time.hxx>
+
+#include "fg_file.hxx"
+
+FG_USING_STD(string);
+
+
+FGFile::FGFile() {
+}
+
+
+FGFile::~FGFile() {
+}
+
+
+// open the file based on specified direction
+bool FGFile::open( FGProtocol::fgProtocolDir dir ) {
+ if ( dir == FGProtocol::out ) {
+ fp = std::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH );
+ } else if ( dir == FGProtocol::in ) {
+ fp = std::open( file_name.c_str(), O_RDONLY );
+ } else {
+ FG_LOG( FG_IO, FG_ALERT,
+ "Error: bidirection mode not available for files." );
+ return false;
+ }
+
+ if ( fp == -1 ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error opening file: " << file_name );
+ return false;
+ }
+
+ return true;
+}
+
+
+// read data from file
+bool FGFile::read( char *buf, int *length ) {
+ // save our current position
+ int pos = lseek( fp, 0, SEEK_CUR );
+
+ // read a chunk
+ int result = std::read( fp, buf, FG_MAX_MSG_SIZE );
+
+ // find the end of line and reset position
+ int i;
+ for ( i = 0; i < result && buf[i] != '\n'; ++i );
+ if ( buf[i] == '\n' ) {
+ *length = i + 1;
+ } else {
+ *length = i;
+ }
+ lseek( fp, pos + *length, SEEK_SET );
+
+ // just in case ...
+ buf[ *length ] = '\0';
+
+ return true;
+}
+
+
+// write data to a file
+bool FGFile::write( char *buf, int length ) {
+ int result = std::write( fp, buf, length );
+ if ( result != length ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << file_name );
+ return false;
+ }
+
+ return true;
+}
+
+
+// close the port
+bool FGFile::close() {
+ if ( std::close( fp ) == -1 ) {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+// fg_file.hxx -- File I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _FG_FILE_HXX
+#define _FG_FILE_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include "Include/compiler.h"
+
+#include <string>
+
+#include <sys/types.h> // for open(), read(), write(), close()
+#include <sys/stat.h> // for open(), read(), write(), close()
+#include <fcntl.h> // for open(), read(), write(), close()
+#include <unistd.h> // for open(), read(), write(), close()
+
+#include "iochannel.hxx"
+#include "protocol.hxx"
+
+FG_USING_STD(string);
+
+
+class FGFile : public FGIOChannel {
+
+ string file_name;
+ int fp;
+
+public:
+
+ FGFile();
+ ~FGFile();
+
+ // open the file based on specified direction
+ bool open( FGProtocol::fgProtocolDir dir );
+
+ // read data from file
+ bool read( char *buf, int *length );
+
+ // write data to a file
+ bool write( char *buf, int length );
+
+ // close file
+ bool close();
+
+ inline string get_file_name() const { return file_name; }
+ inline void set_file_name( const string& fn ) { file_name = fn; }
+};
+
+
+#endif // _FG_FILE_HXX
+
+
--- /dev/null
+// fg_serial.cxx -- Serial I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Include/compiler.h>
+
+// #ifdef FG_HAVE_STD_INCLUDES
+// # include <cmath>
+// # include <cstdlib> // atoi()
+// #else
+// # include <math.h>
+// # include <stdlib.h> // atoi()
+// #endif
+
+#include STL_STRING
+
+#include <Debug/logstream.hxx>
+#include <Aircraft/aircraft.hxx>
+#include <Include/fg_constants.h>
+#include <Serial/serial.hxx>
+#include <Time/fg_time.hxx>
+
+// #include "options.hxx"
+
+#include "fg_serial.hxx"
+
+FG_USING_STD(string);
+
+
+FGSerial::FGSerial() {
+}
+
+
+FGSerial::~FGSerial() {
+}
+
+
+// open the serial port based on specified direction
+bool FGSerial::open( FGProtocol::fgProtocolDir dir ) {
+ if ( ! port.open_port( device ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device );
+ return false;
+ }
+
+ // cout << "fd = " << port.fd << endl;
+
+ if ( ! port.set_baud( atoi( baud.c_str() ) ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error setting baud: " << baud );
+ return false;
+ }
+
+ return true;
+}
+
+
+#if 0
+// "RUL" output format (for some sort of motion platform)
+//
+// The Baud rate is 2400 , one start bit, eight data bits, 1 stop bit,
+// no parity.
+//
+// For position it requires a 3-byte data packet defined as follows:
+//
+// First bite: ascII character "P" ( 0x50 or 80 decimal )
+// Second byte X pos. (1-255) 1 being 0* and 255 being 359*
+// Third byte Y pos.( 1-255) 1 being 0* and 255 359*
+//
+// So sending 80 127 127 to the two axis motors will position on 180*
+// The RS- 232 port is a nine pin connector and the only pins used are
+// 3&5.
+
+static void send_rul_out( fgIOCHANNEL *p ) {
+ char rul[256];
+
+ FGInterface *f;
+ FGTime *t;
+
+ f = current_aircraft.fdm_state;
+ t = FGTime::cur_time_params;
+
+ // run as often as possibleonce per second
+
+ // this runs once per second
+ // if ( p->last_time == t->get_cur_time() ) {
+ // return;
+ // }
+ // p->last_time = t->get_cur_time();
+ // if ( t->get_cur_time() % 2 != 0 ) {
+ // return;
+ // }
+
+ // get roll and pitch, convert to degrees
+ double roll_deg = f->get_Phi() * RAD_TO_DEG;
+ while ( roll_deg < -180.0 ) {
+ roll_deg += 360.0;
+ }
+ while ( roll_deg > 180.0 ) {
+ roll_deg -= 360.0;
+ }
+
+ double pitch_deg = f->get_Theta() * RAD_TO_DEG;
+ while ( pitch_deg < -180.0 ) {
+ pitch_deg += 360.0;
+ }
+ while ( pitch_deg > 180.0 ) {
+ pitch_deg -= 360.0;
+ }
+
+ // scale roll and pitch to output format (1 - 255)
+ // straight && level == (128, 128)
+
+ int roll = (int)( (roll_deg+180.0) * 255.0 / 360.0) + 1;
+ int pitch = (int)( (pitch_deg+180.0) * 255.0 / 360.0) + 1;
+
+ sprintf( rul, "p%c%c\n", roll, pitch);
+
+ FG_LOG( FG_IO, FG_INFO, "p " << roll << " " << pitch );
+
+ string rul_sentence = rul;
+ p->port.write_port(rul_sentence);
+}
+
+
+// "PVE" (ProVision Entertainment) output format (for some sort of
+// motion platform)
+//
+// Outputs a 5-byte data packet defined as follows:
+//
+// First bite: ASCII character "P" ( 0x50 or 80 decimal )
+// Second byte: "roll" value (1-255) 1 being 0* and 255 being 359*
+// Third byte: "pitch" value (1-255) 1 being 0* and 255 being 359*
+// Fourth byte: "heave" value (or vertical acceleration?)
+//
+// So sending 80 127 127 to the two axis motors will position on 180*
+// The RS- 232 port is a nine pin connector and the only pins used are
+// 3&5.
+
+static void send_pve_out( fgIOCHANNEL *p ) {
+ char pve[256];
+
+ FGInterface *f;
+ FGTime *t;
+
+
+ f = current_aircraft.fdm_state;
+ t = FGTime::cur_time_params;
+
+ // run as often as possibleonce per second
+
+ // this runs once per second
+ // if ( p->last_time == t->get_cur_time() ) {
+ // return;
+ // }
+ // p->last_time = t->get_cur_time();
+ // if ( t->get_cur_time() % 2 != 0 ) {
+ // return;
+ // }
+
+ // get roll and pitch, convert to degrees
+ double roll_deg = f->get_Phi() * RAD_TO_DEG;
+ while ( roll_deg <= -180.0 ) {
+ roll_deg += 360.0;
+ }
+ while ( roll_deg > 180.0 ) {
+ roll_deg -= 360.0;
+ }
+
+ double pitch_deg = f->get_Theta() * RAD_TO_DEG;
+ while ( pitch_deg <= -180.0 ) {
+ pitch_deg += 360.0;
+ }
+ while ( pitch_deg > 180.0 ) {
+ pitch_deg -= 360.0;
+ }
+
+ short int heave = (int)(f->get_W_body() * 128.0);
+
+ // scale roll and pitch to output format (1 - 255)
+ // straight && level == (128, 128)
+
+ short int roll = (int)(roll_deg * 32768 / 180.0);
+ short int pitch = (int)(pitch_deg * 32768 / 180.0);
+
+ unsigned char roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2;
+ roll_b1 = roll >> 8;
+ roll_b2 = roll & 0x00ff;
+ pitch_b1 = pitch >> 8;
+ pitch_b2 = pitch & 0x00ff;
+ heave_b1 = heave >> 8;
+ heave_b2 = heave & 0x00ff;
+
+ sprintf( pve, "p%c%c%c%c%c%c\n",
+ roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
+
+ // printf( "p [ %u %u ] [ %u %u ] [ %u %u ]\n",
+ // roll_b1, roll_b2, pitch_b1, pitch_b2, heave_b1, heave_b2 );
+
+ FG_LOG( FG_IO, FG_INFO, "roll=" << roll << " pitch=" << pitch <<
+ " heave=" << heave );
+
+ string pve_sentence = pve;
+ p->port.write_port(pve_sentence);
+}
+
+#endif
+
+
+// read data from port
+bool FGSerial::read( char *buf, int *length ) {
+ // read a chunk
+ *length = port.read_port( buf );
+
+ // just in case ...
+ buf[ *length ] = '\0';
+
+ return true;
+}
+
+// write data to port
+bool FGSerial::write( char *buf, int length ) {
+ int result = port.write_port( buf, length );
+
+ if ( result != length ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << device );
+ return false;
+ }
+
+ return true;
+}
+
+
+// close the port
+bool FGSerial::close() {
+ if ( ! port.close_port() ) {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+// fg_serial.hxx -- Serial I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _FG_SERIAL_HXX
+#define _FG_SERIAL_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include "Include/compiler.h"
+
+#include <string>
+
+// #ifdef FG_HAVE_STD_INCLUDES
+// # include <ctime>
+// #else
+// # include <time.h>
+// #endif
+
+#include <Serial/serial.hxx>
+
+#include "iochannel.hxx"
+#include "protocol.hxx"
+
+FG_USING_STD(string);
+
+
+class FGSerial : public FGIOChannel {
+
+ string device;
+ string baud;
+ FGSerialPort port;
+
+public:
+
+ FGSerial();
+ ~FGSerial();
+
+ // open the serial port based on specified direction
+ bool open( FGProtocol::fgProtocolDir dir );
+
+ // read data from port
+ bool read( char *buf, int *length );
+
+ // write data to port
+ bool write( char *buf, int length );
+
+ // close port
+ bool close();
+
+ inline string get_device() const { return device; }
+ inline void set_device( const string& d ) { device = d; }
+ inline string get_baud() const { return baud; }
+ inline void set_baud( const string& b ) { baud = b; }
+};
+
+
+#endif // _FG_SERIAL_HXX
+
+
--- /dev/null
+// garmin.cxx -- Garmin protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Debug/logstream.hxx>
+#include <FDM/flight.hxx>
+#include <Math/fg_geodesy.hxx>
+#include <Time/fg_time.hxx>
+
+#include "iochannel.hxx"
+#include "garmin.hxx"
+
+
+FGGarmin::FGGarmin() {
+}
+
+FGGarmin::~FGGarmin() {
+}
+
+
+// calculate the garmin check sum
+static char calc_nmea_cksum(char *sentence) {
+ unsigned char sum = 0;
+ int i, len;
+
+ // cout << sentence << endl;
+
+ len = strlen(sentence);
+ sum = sentence[0];
+ for ( i = 1; i < len; i++ ) {
+ // cout << sentence[i];
+ sum ^= sentence[i];
+ }
+ // cout << endl;
+
+ // printf("sum = %02x\n", sum);
+ return sum;
+}
+
+
+// generate Garmin message
+bool FGGarmin::gen_message() {
+ // cout << "generating garmin message" << endl;
+
+ char rmc[256], rmc_sum[256], rmz[256], rmz_sum[256];
+ char dir;
+ int deg;
+ double min;
+
+ FGTime *t = FGTime::cur_time_params;
+
+ char utc[10];
+ sprintf( utc, "%02d%02d%02d",
+ t->getGmt()->tm_hour, t->getGmt()->tm_min, t->getGmt()->tm_sec );
+
+ char lat[20];
+ double latd = cur_fdm_state->get_Latitude() * RAD_TO_DEG;
+ if ( latd < 0.0 ) {
+ latd *= -1.0;
+ dir = 'S';
+ } else {
+ dir = 'N';
+ }
+ deg = (int)(latd);
+ min = (latd - (double)deg) * 60.0;
+ sprintf( lat, "%02d%06.3f,%c", abs(deg), min, dir);
+
+ char lon[20];
+ double lond = cur_fdm_state->get_Longitude() * RAD_TO_DEG;
+ if ( lond < 0.0 ) {
+ lond *= -1.0;
+ dir = 'W';
+ } else {
+ dir = 'E';
+ }
+ deg = (int)(lond);
+ min = (lond - (double)deg) * 60.0;
+ sprintf( lon, "%03d%06.3f,%c", abs(deg), min, dir);
+
+ char speed[10];
+ sprintf( speed, "%05.1f", cur_fdm_state->get_V_equiv_kts() );
+
+ char heading[10];
+ sprintf( heading, "%05.1f", cur_fdm_state->get_Psi() * RAD_TO_DEG );
+
+ char altitude_m[10];
+ sprintf( altitude_m, "%02d",
+ (int)(cur_fdm_state->get_Altitude() * FEET_TO_METER) );
+
+ char altitude_ft[10];
+ sprintf( altitude_ft, "%02d", (int)cur_fdm_state->get_Altitude() );
+
+ char date[10];
+ sprintf( date, "%02d%02d%02d", t->getGmt()->tm_mday,
+ t->getGmt()->tm_mon+1, t->getGmt()->tm_year );
+
+ // $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
+ sprintf( rmc, "GPRMC,%s,A,%s,%s,%s,%s,%s,000.0,E",
+ utc, lat, lon, speed, heading, date );
+ sprintf( rmc_sum, "%02X", calc_nmea_cksum(rmc) );
+
+ // sprintf( gga, "$GPGGA,%s,%s,%s,1,04,0.0,%s,M,00.0,M,,*00\r\n",
+ // utc, lat, lon, altitude_m );
+
+ sprintf( rmz, "PGRMZ,%s,f,3", altitude_ft );
+ sprintf( rmz_sum, "%02X", calc_nmea_cksum(rmz) );
+
+ FG_LOG( FG_IO, FG_DEBUG, rmc );
+ FG_LOG( FG_IO, FG_DEBUG, rmz );
+
+ string garmin_sentence;
+
+ // RMC sentence
+ garmin_sentence = "$";
+ garmin_sentence += rmc;
+ garmin_sentence += "*";
+ garmin_sentence += rmc_sum;
+ garmin_sentence += "\n";
+
+ // RMZ sentence (garmin proprietary)
+ garmin_sentence += "$";
+ garmin_sentence += rmz;
+ garmin_sentence += "*";
+ garmin_sentence += rmz_sum;
+ garmin_sentence += "\n";
+
+ cout << garmin_sentence;
+
+ length = garmin_sentence.length();
+ strncpy( buf, garmin_sentence.c_str(), length );
+
+ return true;
+}
+
+
+// parse Garmin message
+bool FGGarmin::parse_message() {
+ FG_LOG( FG_IO, FG_DEBUG, "parse garmin message" );
+
+ string msg = buf;
+ msg = msg.substr( 0, length );
+ FG_LOG( FG_IO, FG_DEBUG, "entire message = " << msg );
+
+ string::size_type begin_line, end_line, begin, end;
+ begin_line = begin = 0;
+
+ // extract out each line
+ end_line = msg.find("\n", begin_line);
+ while ( end_line != string::npos ) {
+ string line = msg.substr(begin_line, end_line - begin_line);
+ begin_line = end_line + 1;
+ FG_LOG( FG_IO, FG_DEBUG, " input line = " << line );
+
+ // leading character
+ string start = msg.substr(begin, 1);
+ ++begin;
+ FG_LOG( FG_IO, FG_DEBUG, " start = " << start );
+
+ // sentence
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string sentence = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_DEBUG, " sentence = " << sentence );
+
+ double lon_deg, lon_min, lat_deg, lat_min;
+ double lon, lat, speed, heading, altitude;
+
+ if ( sentence == "GPRMC" ) {
+ // time
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string utc = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_DEBUG, " utc = " << utc );
+
+ // junk
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string junk = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_DEBUG, " junk = " << junk );
+
+ // lat val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat_deg = atof( lat_str.substr(0, 2).c_str() );
+ lat_min = atof( lat_str.substr(2).c_str() );
+
+ // lat dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat = lat_deg + ( lat_min / 60.0 );
+ if ( lat_dir == "S" ) {
+ lat *= -1;
+ }
+
+ cur_fdm_state->set_Latitude( lat * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_DEBUG, " lat = " << lat );
+
+ // lon val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon_deg = atof( lon_str.substr(0, 3).c_str() );
+ lon_min = atof( lon_str.substr(3).c_str() );
+
+ // lon dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon = lon_deg + ( lon_min / 60.0 );
+ if ( lon_dir == "W" ) {
+ lon *= -1;
+ }
+
+ cur_fdm_state->set_Longitude( lon * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_DEBUG, " lon = " << lon );
+
+ double sl_radius, lat_geoc;
+ fgGeodToGeoc( cur_fdm_state->get_Latitude(),
+ cur_fdm_state->get_Altitude(),
+ &sl_radius, &lat_geoc );
+ cur_fdm_state->set_Geocentric_Position( lat_geoc,
+ cur_fdm_state->get_Longitude(),
+ sl_radius + cur_fdm_state->get_Altitude() );
+
+ // speed
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string speed_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+ speed = atof( speed_str.c_str() );
+ cur_fdm_state->set_V_equiv_kts( speed );
+ cur_fdm_state->set_V_ground_speed( speed );
+ FG_LOG( FG_IO, FG_DEBUG, " speed = " << speed );
+
+ // heading
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string hdg_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+ heading = atof( hdg_str.c_str() );
+ cur_fdm_state->set_Euler_Angles( cur_fdm_state->get_Phi(),
+ cur_fdm_state->get_Theta(),
+ heading * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_DEBUG, " heading = " << heading );
+ } else if ( sentence == "PGRMZ" ) {
+ // altitude
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string alt_str = msg.substr(begin, end - begin);
+ altitude = atof( alt_str.c_str() );
+ begin = end + 1;
+
+ // altitude units
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string alt_units = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ if ( alt_units != "F" && alt_units != "f" ) {
+ altitude *= METER_TO_FEET;
+ }
+
+ cur_fdm_state->set_Altitude( altitude );
+
+ FG_LOG( FG_IO, FG_DEBUG, " altitude = " << altitude );
+
+ }
+
+ // printf("%.8f %.8f\n", lon, lat);
+
+ begin = begin_line;
+ end_line = msg.find("\n", begin_line);
+ }
+
+ return true;
+}
+
+
+// open hailing frequencies
+bool FGGarmin::open() {
+ if ( is_enabled() ) {
+ FG_LOG( FG_IO, FG_ALERT, "This shouldn't happen, but the channel "
+ << "is already in use, ignoring" );
+ return false;
+ }
+
+ FGIOChannel *io = get_io_channel();
+
+ if ( ! io->open( get_direction() ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error opening channel communication layer." );
+ return false;
+ }
+
+ set_enabled( true );
+
+ return true;
+}
+
+
+// process work for this port
+bool FGGarmin::process() {
+ FGIOChannel *io = get_io_channel();
+
+ if ( get_direction() == out ) {
+ gen_message();
+ if ( ! io->write( buf, length ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error writing data." );
+ return false;
+ }
+ } else if ( get_direction() == in ) {
+ if ( io->read( buf, &length ) ) {
+ parse_message();
+ } else {
+ FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
+ return false;
+ }
+ if ( io->read( buf, &length ) ) {
+ parse_message();
+ } else {
+ FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// close the channel
+bool FGGarmin::close() {
+ FGIOChannel *io = get_io_channel();
+
+ set_enabled( false );
+
+ if ( ! io->close() ) {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+// garmin.hxx -- Garmin protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _FG_GARMIN_HXX
+#define _FG_GARMIN_HXX
+
+
+#include "Include/compiler.h"
+
+#include STL_STRING
+
+#include "protocol.hxx"
+
+FG_USING_STD(string);
+
+
+class FGGarmin : public FGProtocol {
+
+ char buf[ FG_MAX_MSG_SIZE ];
+ int length;
+
+public:
+
+ FGGarmin();
+ ~FGGarmin();
+
+ bool gen_message();
+ bool parse_message();
+
+ // open hailing frequencies
+ bool open();
+
+ // process work for this port
+ bool process();
+
+ // close the channel
+ bool close();
+};
+
+
+#endif // _FG_GARMIN_HXX
+
+
--- /dev/null
+// iochannel.cxx -- High level IO channel class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include "iochannel.hxx"
+#include "garmin.hxx"
+#include "nmea.hxx"
+
+
+// constructor
+FGIOChannel::FGIOChannel()
+{
+}
+
+
+// destructor
+FGIOChannel::~FGIOChannel()
+{
+}
+
+
+// dummy configure routine
+bool FGIOChannel::open( FGProtocol::fgProtocolDir dir ) {
+ return false;
+}
+
+
+// dummy process routine
+bool FGIOChannel::read( char *buf, int *length ) {
+ return false;
+}
+
+
+// dummy process routine
+bool FGIOChannel::write( char *buf, int length ) {
+ return false;
+}
+
+
+// dummy close routine
+bool FGIOChannel::close() {
+ return false;
+}
--- /dev/null
+// iochannel.hxx -- High level IO channel class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _IOCHANNEL_HXX
+#define _IOCHANNEL_HXX
+
+
+#include "Include/compiler.h"
+
+#include "protocol.hxx"
+
+#include STL_STRING
+#include <vector>
+
+FG_USING_STD(vector);
+FG_USING_STD(string);
+
+
+// forward declaration
+class FGProtocol;
+
+
+class FGIOChannel {
+
+public:
+
+ FGIOChannel();
+ virtual ~FGIOChannel();
+
+ virtual bool open( FGProtocol::fgProtocolDir dir );
+ virtual bool read( char *buf, int *length );
+ virtual bool write( char *buf, int length );
+ virtual bool close();
+};
+
+
+#endif // _IOCHANNEL_HXX
+
+
--- /dev/null
+// nmea.cxx -- NMEA protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Debug/logstream.hxx>
+#include <FDM/flight.hxx>
+#include <Math/fg_geodesy.hxx>
+#include <Time/fg_time.hxx>
+
+#include "iochannel.hxx"
+#include "nmea.hxx"
+
+
+FGNMEA::FGNMEA() {
+}
+
+FGNMEA::~FGNMEA() {
+}
+
+
+// calculate the nmea check sum
+static char calc_nmea_cksum(char *sentence) {
+ unsigned char sum = 0;
+ int i, len;
+
+ // cout << sentence << endl;
+
+ len = strlen(sentence);
+ sum = sentence[0];
+ for ( i = 1; i < len; i++ ) {
+ // cout << sentence[i];
+ sum ^= sentence[i];
+ }
+ // cout << endl;
+
+ // printf("sum = %02x\n", sum);
+ return sum;
+}
+
+
+// generate NMEA message
+bool FGNMEA::gen_message() {
+ // cout << "generating nmea message" << endl;
+
+ char rmc[256], gga[256];
+ char rmc_sum[10], gga_sum[10];
+ char dir;
+ int deg;
+ double min;
+
+ FGTime *t = FGTime::cur_time_params;
+
+ char utc[10];
+ sprintf( utc, "%02d%02d%02d",
+ t->getGmt()->tm_hour, t->getGmt()->tm_min, t->getGmt()->tm_sec );
+
+ char lat[20];
+ double latd = cur_fdm_state->get_Latitude() * RAD_TO_DEG;
+ if ( latd < 0.0 ) {
+ latd *= -1.0;
+ dir = 'S';
+ } else {
+ dir = 'N';
+ }
+ deg = (int)(latd);
+ min = (latd - (double)deg) * 60.0;
+ sprintf( lat, "%02d%06.3f,%c", abs(deg), min, dir);
+
+ char lon[20];
+ double lond = cur_fdm_state->get_Longitude() * RAD_TO_DEG;
+ if ( lond < 0.0 ) {
+ lond *= -1.0;
+ dir = 'W';
+ } else {
+ dir = 'E';
+ }
+ deg = (int)(lond);
+ min = (lond - (double)deg) * 60.0;
+ sprintf( lon, "%03d%06.3f,%c", abs(deg), min, dir);
+
+ char speed[10];
+ sprintf( speed, "%05.1f", cur_fdm_state->get_V_equiv_kts() );
+
+ char heading[10];
+ sprintf( heading, "%05.1f", cur_fdm_state->get_Psi() * RAD_TO_DEG );
+
+ char altitude_m[10];
+ sprintf( altitude_m, "%02d",
+ (int)(cur_fdm_state->get_Altitude() * FEET_TO_METER) );
+
+ char altitude_ft[10];
+ sprintf( altitude_ft, "%02d", (int)cur_fdm_state->get_Altitude() );
+
+ char date[10];
+ sprintf( date, "%02d%02d%02d", t->getGmt()->tm_mday,
+ t->getGmt()->tm_mon+1, t->getGmt()->tm_year );
+
+ // $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
+ sprintf( rmc, "GPRMC,%s,A,%s,%s,%s,%s,%s,0.000,E",
+ utc, lat, lon, speed, heading, date );
+ sprintf( rmc_sum, "%02X", calc_nmea_cksum(rmc) );
+
+ sprintf( gga, "GPGGA,%s,%s,%s,1,,,%s,F,,,,",
+ utc, lat, lon, altitude_ft );
+ sprintf( gga_sum, "%02X", calc_nmea_cksum(gga) );
+
+
+ FG_LOG( FG_IO, FG_DEBUG, rmc );
+ FG_LOG( FG_IO, FG_DEBUG, gga );
+
+ string nmea_sentence;
+
+ // RMC sentence
+ nmea_sentence = "$";
+ nmea_sentence += rmc;
+ nmea_sentence += "*";
+ nmea_sentence += rmc_sum;
+ nmea_sentence += "\n";
+
+ // GGA sentence
+ nmea_sentence += "$";
+ nmea_sentence += gga;
+ nmea_sentence += "*";
+ nmea_sentence += gga_sum;
+ nmea_sentence += "\n";
+
+ cout << nmea_sentence;
+
+ length = nmea_sentence.length();
+ strncpy( buf, nmea_sentence.c_str(), length );
+
+ return true;
+}
+
+
+// parse NMEA message. messages will look something like the
+// following:
+//
+// $GPRMC,163227,A,3321.173,N,11039.855,W,000.1,270.0,171199,0.000,E*61
+// $GPGGA,163227,3321.173,N,11039.855,W,1,,,3333,F,,,,*0F
+
+bool FGNMEA::parse_message() {
+ FG_LOG( FG_IO, FG_INFO, "parse nmea message" );
+
+ string msg = buf;
+ msg = msg.substr( 0, length );
+ FG_LOG( FG_IO, FG_INFO, "entire message = " << msg );
+
+ string::size_type begin_line, end_line, begin, end;
+ begin_line = begin = 0;
+
+ // extract out each line
+ end_line = msg.find("\n", begin_line);
+ while ( end_line != string::npos ) {
+ string line = msg.substr(begin_line, end_line - begin_line);
+ begin_line = end_line + 1;
+ FG_LOG( FG_IO, FG_INFO, " input line = " << line );
+
+ // leading character
+ string start = msg.substr(begin, 1);
+ ++begin;
+ FG_LOG( FG_IO, FG_INFO, " start = " << start );
+
+ // sentence
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string sentence = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " sentence = " << sentence );
+
+ double lon_deg, lon_min, lat_deg, lat_min;
+ double lon, lat, speed, heading, altitude;
+
+ if ( sentence == "GPRMC" ) {
+ // time
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string utc = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " utc = " << utc );
+
+ // junk
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string junk = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " junk = " << junk );
+
+ // lat val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat_deg = atof( lat_str.substr(0, 2).c_str() );
+ lat_min = atof( lat_str.substr(2).c_str() );
+
+ // lat dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat = lat_deg + ( lat_min / 60.0 );
+ if ( lat_dir == "S" ) {
+ lat *= -1;
+ }
+
+ cur_fdm_state->set_Latitude( lat * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_INFO, " lat = " << lat );
+
+ // lon val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon_deg = atof( lon_str.substr(0, 3).c_str() );
+ lon_min = atof( lon_str.substr(3).c_str() );
+
+ // lon dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon = lon_deg + ( lon_min / 60.0 );
+ if ( lon_dir == "W" ) {
+ lon *= -1;
+ }
+
+ cur_fdm_state->set_Longitude( lon * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_INFO, " lon = " << lon );
+
+ double sl_radius, lat_geoc;
+ fgGeodToGeoc( cur_fdm_state->get_Latitude(),
+ cur_fdm_state->get_Altitude(),
+ &sl_radius, &lat_geoc );
+ cur_fdm_state->set_Geocentric_Position( lat_geoc,
+ cur_fdm_state->get_Longitude(),
+ sl_radius + cur_fdm_state->get_Altitude() );
+
+ // speed
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string speed_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+ speed = atof( speed_str.c_str() );
+ cur_fdm_state->set_V_equiv_kts( speed );
+ cur_fdm_state->set_V_ground_speed( speed );
+ FG_LOG( FG_IO, FG_INFO, " speed = " << speed );
+
+ // heading
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string hdg_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+ heading = atof( hdg_str.c_str() );
+ cur_fdm_state->set_Euler_Angles( cur_fdm_state->get_Phi(),
+ cur_fdm_state->get_Theta(),
+ heading * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_INFO, " heading = " << heading );
+ } else if ( sentence == "GPGGA" ) {
+ // time
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string utc = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " utc = " << utc );
+
+ // lat val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat_deg = atof( lat_str.substr(0, 2).c_str() );
+ lat_min = atof( lat_str.substr(2).c_str() );
+
+ // lat dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lat_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lat = lat_deg + ( lat_min / 60.0 );
+ if ( lat_dir == "S" ) {
+ lat *= -1;
+ }
+
+ // cur_fdm_state->set_Latitude( lat * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_INFO, " lat = " << lat );
+
+ // lon val
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_str = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon_deg = atof( lon_str.substr(0, 3).c_str() );
+ lon_min = atof( lon_str.substr(3).c_str() );
+
+ // lon dir
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string lon_dir = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ lon = lon_deg + ( lon_min / 60.0 );
+ if ( lon_dir == "W" ) {
+ lon *= -1;
+ }
+
+ // cur_fdm_state->set_Longitude( lon * DEG_TO_RAD );
+ FG_LOG( FG_IO, FG_INFO, " lon = " << lon );
+
+ // junk
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string junk = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " junk = " << junk );
+
+ // junk
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ junk = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " junk = " << junk );
+
+ // junk
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ junk = msg.substr(begin, end - begin);
+ begin = end + 1;
+ FG_LOG( FG_IO, FG_INFO, " junk = " << junk );
+
+ // altitude
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string alt_str = msg.substr(begin, end - begin);
+ altitude = atof( alt_str.c_str() );
+ begin = end + 1;
+
+ // altitude units
+ end = msg.find(",", begin);
+ if ( end == string::npos ) {
+ return false;
+ }
+
+ string alt_units = msg.substr(begin, end - begin);
+ begin = end + 1;
+
+ if ( alt_units != "F" ) {
+ altitude *= METER_TO_FEET;
+ }
+
+ cur_fdm_state->set_Altitude( altitude );
+
+ FG_LOG( FG_IO, FG_INFO, " altitude = " << altitude );
+
+ }
+
+ // printf("%.8f %.8f\n", lon, lat);
+
+ begin = begin_line;
+ end_line = msg.find("\n", begin_line);
+ }
+
+ return true;
+}
+
+
+// open hailing frequencies
+bool FGNMEA::open() {
+ if ( is_enabled() ) {
+ FG_LOG( FG_IO, FG_ALERT, "This shouldn't happen, but the channel "
+ << "is already in use, ignoring" );
+ return false;
+ }
+
+ FGIOChannel *io = get_io_channel();
+
+ if ( ! io->open( get_direction() ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error opening channel communication layer." );
+ return false;
+ }
+
+ set_enabled( true );
+
+ return true;
+}
+
+
+// process work for this port
+bool FGNMEA::process() {
+ FGIOChannel *io = get_io_channel();
+
+ if ( get_direction() == out ) {
+ gen_message();
+ if ( ! io->write( buf, length ) ) {
+ FG_LOG( FG_IO, FG_ALERT, "Error writing data." );
+ return false;
+ }
+ } else if ( get_direction() == in ) {
+ if ( io->read( buf, &length ) ) {
+ parse_message();
+ } else {
+ FG_LOG( FG_IO, FG_ALERT, "Error reading data." );
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// close the channel
+bool FGNMEA::close() {
+ FGIOChannel *io = get_io_channel();
+
+ set_enabled( false );
+
+ if ( ! io->close() ) {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+// nmea.hxx -- NMEA protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _FG_NMEA_HXX
+#define _FG_NMEA_HXX
+
+
+#include "Include/compiler.h"
+
+#include STL_STRING
+
+#include "protocol.hxx"
+
+FG_USING_STD(string);
+
+
+class FGNMEA : public FGProtocol {
+
+ char buf[ FG_MAX_MSG_SIZE ];
+ int length;
+
+public:
+
+ FGNMEA();
+ ~FGNMEA();
+
+ bool gen_message();
+ bool parse_message();
+
+ // open hailing frequencies
+ bool open();
+
+ // process work for this port
+ bool process();
+
+ // close the channel
+ bool close();
+};
+
+
+#endif // _FG_NMEA_HXX
+
+
--- /dev/null
+// protocol.cxx -- High level protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#include <Debug/logstream.hxx>
+
+#include "protocol.hxx"
+
+
+FGProtocol::FGProtocol() :
+ hz(0.0),
+ count_down(0),
+ enabled(false)
+{
+}
+
+
+FGProtocol::~FGProtocol() {
+}
+
+
+// dummy open routine
+bool FGProtocol::open() {
+ FG_LOG( FG_IO, FG_INFO, "dummy FGProtocol::open()" );
+ enabled = false;
+ return false;
+}
+
+
+// dummy process routine
+bool FGProtocol::process() {
+ FG_LOG( FG_IO, FG_INFO, "dummy FGProtocol::process()" );
+ return false;
+}
+
+
+// dummy close routine
+bool FGProtocol::close() {
+ FG_LOG( FG_IO, FG_INFO, "dummy FGProtocol::close()" );
+ return false;
+}
+
+
+// dummy close routine
+bool FGProtocol::gen_message() {
+ FG_LOG( FG_IO, FG_INFO, "dummy FGProtocol::gen_message()" );
+ return false;
+}
+
+
+// dummy close routine
+bool FGProtocol::parse_message() {
+ FG_LOG( FG_IO, FG_INFO, "dummy FGProtocol::close()" );
+ return false;
+}
+
+
--- /dev/null
+// protocol.hxx -- High level protocal class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// 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.
+//
+// $Id$
+
+
+#ifndef _PROTOCOL_HXX
+#define _PROTOCOL_HXX
+
+
+#include "Include/compiler.h"
+
+#include STL_STRING
+#include <vector>
+
+FG_USING_STD(string);
+FG_USING_STD(vector);
+
+
+#define FG_MAX_MSG_SIZE 16384
+
+// forward declaration
+class FGIOChannel;
+
+
+class FGProtocol {
+
+public:
+
+ enum fgProtocolDir {
+ none = 0,
+ in = 1,
+ out = 2,
+ bi = 3
+ };
+
+private:
+
+ double hz;
+ int count_down;
+
+ fgProtocolDir dir;
+
+ // string protocol_str;
+
+ // char buf[FG_MAX_MSG_SIZE];
+ // int length;
+
+ bool enabled;
+
+ FGIOChannel *io;
+
+public:
+
+ FGProtocol();
+ virtual ~FGProtocol();
+
+ virtual bool open();
+ virtual bool process();
+ virtual bool close();
+
+ inline fgProtocolDir get_direction() const { return dir; }
+ inline void set_direction( const string& d ) {
+ if ( d == "in" ) {
+ dir = in;
+ } else if ( d == "out" ) {
+ dir = out;
+ } else if ( d == "bi" ) {
+ dir = bi;
+ } else {
+ dir = none;
+ }
+ }
+
+ inline double get_hz() const { return hz; }
+ inline void set_hz( double t ) { hz = t; }
+ inline int get_count_down() const { return count_down; }
+ inline void set_count_down( int c ) { count_down = c; }
+ inline void dec_count_down( int c ) { count_down -= c; }
+
+ virtual bool gen_message();
+ virtual bool parse_message();
+
+ // inline string get_protocol() const { return protocol_str; }
+ // inline void set_protocol( const string& str ) { protocol_str = str; }
+
+ // inline char *get_buf() { return buf; }
+ // inline int get_length() const { return length; }
+ // inline void set_length( int l ) { length = l; }
+
+ inline bool is_enabled() const { return enabled; }
+ inline void set_enabled( const bool b ) { enabled = b; }
+
+ inline FGIOChannel *get_io_channel() const { return io; }
+ inline void set_io_channel( FGIOChannel *c ) { io = c; }
+};
+
+
+typedef vector < FGProtocol * > io_container;
+typedef io_container::iterator io_iterator;
+typedef io_container::const_iterator const_io_iterator;
+
+
+#endif // _PROTOCOL_HXX
+
+