1
0
Fork 0

Support for an arbitrary number of serial ports.

This commit is contained in:
curt 1998-11-25 01:33:58 +00:00
parent be02039e9c
commit d25ab417c5
4 changed files with 171 additions and 155 deletions

View file

@ -23,7 +23,14 @@
#include <stdlib.h> // atoi() #include <stdlib.h> // atoi()
#include <string> #include <string>
#include <vector>
#include "Include/fg_stl_config.h"
#ifdef NEEDNAMESPACESTD
using namespace std;
#endif
#include <Aircraft/aircraft.hxx> #include <Aircraft/aircraft.hxx>
#include <Debug/logstream.hxx> #include <Debug/logstream.hxx>
@ -36,27 +43,34 @@
#include "fg_serial.hxx" #include "fg_serial.hxx"
// support up to four serial channels. Each channel can be assigned // support an arbitrary number of serial channels. Each channel can
// to an arbitrary port. Bi-directional communication is supported by // be assigned to an arbitrary port. Bi-directional communication is
// the underlying layer. // 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 // define the four channels
fgSERIAL port_a; io_container port_list;
fgSERIAL port_b;
fgSERIAL port_c;
fgSERIAL port_d;
// the type of each channel
fgSerialPortKind port_a_kind = FG_SERIAL_DISABLED; fgIOCHANNEL::fgIOCHANNEL() :
fgSerialPortKind port_b_kind = FG_SERIAL_DISABLED; kind( FG_SERIAL_DISABLED )
fgSerialPortKind port_c_kind = FG_SERIAL_DISABLED; {
fgSerialPortKind port_d_kind = FG_SERIAL_DISABLED; }
fgIOCHANNEL::~fgIOCHANNEL() {
}
// configure a port based on the config string // configure a port based on the config string
static bool config_port(fgSERIAL& s, fgSerialPortKind& kind, static fgIOCHANNEL config_port( const string& config )
const string& config)
{ {
fgIOCHANNEL p;
string::size_type begin, end; string::size_type begin, end;
string device; string device;
@ -64,108 +78,106 @@ static bool config_port(fgSERIAL& s, fgSerialPortKind& kind,
string baud; string baud;
string direction; string direction;
begin = 0;; begin = 0;
FG_LOG( FG_SERIAL, FG_INFO, "Configuring serial port: " << config );
// device name // device name
end = config.find(",", begin); end = config.find(",", begin);
if ( end == string::npos ) { if ( end == string::npos ) {
return false; return p;
} }
device = config.substr(begin, end - begin); device = config.substr(begin, end - begin);
begin = end + 1; begin = end + 1;
cout << " device = " << device << endl; FG_LOG( FG_SERIAL, FG_INFO, " device = " << device );
// format // format
end = config.find(",", begin); end = config.find(",", begin);
if ( end == string::npos ) { if ( end == string::npos ) {
return false; return p;
} }
format = config.substr(begin, end - begin); format = config.substr(begin, end - begin);
begin = end + 1; begin = end + 1;
cout << " format = " << format << endl; FG_LOG( FG_SERIAL, FG_INFO, " format = " << format );
// baud // baud
end = config.find(",", begin); end = config.find(",", begin);
if ( end == string::npos ) { if ( end == string::npos ) {
return false; return p;
} }
baud = config.substr(begin, end - begin); baud = config.substr(begin, end - begin);
begin = end + 1; begin = end + 1;
cout << " baud = " << baud << endl; FG_LOG( FG_SERIAL, FG_INFO, " baud = " << baud );
// direction // direction
direction = config.substr(begin); direction = config.substr(begin);
cout << " direction = " << direction << endl; FG_LOG( FG_SERIAL, FG_INFO, " direction = " << direction );
if ( s.is_enabled() ) { if ( p.port.is_enabled() ) {
FG_LOG( FG_SERIAL, FG_ALERT, "This shouldn't happen, but the port " FG_LOG( FG_SERIAL, FG_ALERT, "This shouldn't happen, but the port "
<< "is already in use, ignoring" ); << "is already in use, ignoring" );
return false; return p;
} }
if ( ! s.open_port( device ) ) { if ( ! p.port.open_port( device ) ) {
FG_LOG( FG_SERIAL, FG_ALERT, "Error opening device: " << device ); FG_LOG( FG_SERIAL, FG_ALERT, "Error opening device: " << device );
return p;
} }
if ( ! s.set_baud( atoi( baud.c_str() ) ) ) { if ( ! p.port.set_baud( atoi( baud.c_str() ) ) ) {
FG_LOG( FG_SERIAL, FG_ALERT, "Error setting baud: " << baud ); FG_LOG( FG_SERIAL, FG_ALERT, "Error setting baud: " << baud );
return p;
} }
if ( format == "nmea" ) { if ( format == "nmea" ) {
if ( direction == "out" ) { if ( direction == "out" ) {
kind = FG_SERIAL_NMEA_OUT; p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_OUT;
} else if ( direction == "in" ) { } else if ( direction == "in" ) {
kind = FG_SERIAL_NMEA_IN; p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_IN;
} else { } else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" ); FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
} }
} else if ( format == "garman" ) { } else if ( format == "garman" ) {
if ( direction == "out" ) { if ( direction == "out" ) {
kind = FG_SERIAL_GARMAN_OUT; p.kind = fgIOCHANNEL::FG_SERIAL_GARMAN_OUT;
} else if ( direction == "in" ) { } else if ( direction == "in" ) {
kind = FG_SERIAL_GARMAN_IN; p.kind = fgIOCHANNEL::FG_SERIAL_GARMAN_IN;
} else { } else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" ); FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
} }
} else if ( format == "fgfs" ) { } else if ( format == "fgfs" ) {
if ( direction == "out" ) { if ( direction == "out" ) {
kind = FG_SERIAL_FGFS_OUT; p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_OUT;
} else if ( direction == "in" ) { } else if ( direction == "in" ) {
kind = FG_SERIAL_FGFS_IN; p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_IN;
} else { } else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" ); FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
} }
} else { } else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown format" ); FG_LOG( FG_SERIAL, FG_ALERT, "Unknown format" );
return false;
} }
return true; return p;
} }
// initialize serial ports based on command line options (if any) // step through the port config streams (from fgOPTIONS) and setup
// serial port channels for each
void fgSerialInit() { void fgSerialInit() {
if ( current_options.get_port_a_config() != "" ) { fgIOCHANNEL port;
config_port(port_a, port_a_kind, current_options.get_port_a_config() ); str_container port_options_list = current_options.get_port_options_list();
}
if ( current_options.get_port_b_config() != "" ) { const_str_iterator current = port_options_list.begin();
config_port(port_b, port_b_kind, current_options.get_port_b_config() ); const_str_iterator last = port_options_list.end();
}
if ( current_options.get_port_c_config() != "" ) { for ( ; current != last; ++current ) {
config_port(port_c, port_c_kind, current_options.get_port_c_config() ); port = config_port( *current );
} if ( port.kind != fgIOCHANNEL::FG_SERIAL_DISABLED ) {
port_list.push_back( port );
if ( current_options.get_port_d_config() != "" ) { }
config_port(port_d, port_d_kind, current_options.get_port_d_config() );
} }
} }
@ -189,7 +201,7 @@ char calc_nmea_cksum(char *sentence) {
} }
static void send_nmea_out( fgSERIAL& s ) { static void send_nmea_out( fgIOCHANNEL& p ) {
char rmc[256], gga[256]; char rmc[256], gga[256];
char rmc_sum[10], gga_sum[10]; char rmc_sum[10], gga_sum[10];
char dir; char dir;
@ -198,6 +210,12 @@ static void send_nmea_out( fgSERIAL& s ) {
fgFLIGHT *f; fgFLIGHT *f;
fgTIME *t; fgTIME *t;
// run once per second
if ( p.last_time == cur_time_params.cur_time ) {
return;
}
p.last_time = cur_time_params.cur_time;
f = current_aircraft.flight; f = current_aircraft.flight;
t = &cur_time_params; t = &cur_time_params;
@ -266,7 +284,7 @@ static void send_nmea_out( fgSERIAL& s ) {
rmc_sentence += "*"; rmc_sentence += "*";
rmc_sentence += rmc_sum; rmc_sentence += rmc_sum;
rmc_sentence += "\r\n"; rmc_sentence += "\r\n";
s.write_port(rmc_sentence); p.port.write_port(rmc_sentence);
} else { } else {
// gga on odd seconds // gga on odd seconds
string gga_sentence = "$"; string gga_sentence = "$";
@ -274,14 +292,14 @@ static void send_nmea_out( fgSERIAL& s ) {
gga_sentence += "*"; gga_sentence += "*";
gga_sentence += gga_sum; gga_sentence += gga_sum;
gga_sentence += "\n"; gga_sentence += "\n";
// s.write_port(gga_sentence); // p.port.write_port(gga_sentence);
} }
} }
static void read_nmea_in( fgSERIAL& s ) { static void read_nmea_in( fgIOCHANNEL& p ) {
} }
static void send_garman_out( fgSERIAL& s ) { static void send_garman_out( fgIOCHANNEL& p ) {
char rmc[256], rmz[256]; char rmc[256], rmz[256];
char dir; char dir;
int deg; int deg;
@ -289,6 +307,12 @@ static void send_garman_out( fgSERIAL& s ) {
fgFLIGHT *f; fgFLIGHT *f;
fgTIME *t; fgTIME *t;
// run once per second
if ( p.last_time == cur_time_params.cur_time ) {
return;
}
p.last_time = cur_time_params.cur_time;
f = current_aircraft.flight; f = current_aircraft.flight;
t = &cur_time_params; t = &cur_time_params;
@ -352,69 +376,61 @@ static void send_garman_out( fgSERIAL& s ) {
// one full frame every 2 seconds according to the standard // one full frame every 2 seconds according to the standard
if ( cur_time_params.cur_time % 2 == 0 ) { if ( cur_time_params.cur_time % 2 == 0 ) {
// rmc on even seconds // rmc on even seconds
s.write_port(rmc); p.port.write_port(rmc);
} else { } else {
// gga on odd seconds // rmz on odd seconds
s.write_port(rmz); p.port.write_port(rmz);
} }
} }
static void read_garman_in( fgSERIAL& s ) { static void read_garman_in( fgIOCHANNEL& p ) {
} }
static void send_fgfs_out( fgSERIAL& s ) { static void send_fgfs_out( fgIOCHANNEL& p ) {
} }
static void read_fgfs_in( fgSERIAL& s ) { static void read_fgfs_in( fgIOCHANNEL& p ) {
} }
// one more level of indirection ... // one more level of indirection ...
static void process_port( fgSERIAL& s, const fgSerialPortKind kind ) { static void process_port( fgIOCHANNEL& p ) {
static long last_time; if ( p.kind == fgIOCHANNEL::FG_SERIAL_NMEA_OUT ) {
if ( kind == FG_SERIAL_NMEA_OUT ) { send_nmea_out(p);
if (cur_time_params.cur_time > last_time ) { } else if ( p.kind == fgIOCHANNEL::FG_SERIAL_NMEA_IN ) {
send_nmea_out(s); read_nmea_in(p);
} } else if ( p.kind == fgIOCHANNEL::FG_SERIAL_GARMAN_OUT ) {
last_time = cur_time_params.cur_time; send_garman_out(p);
} else if ( kind == FG_SERIAL_NMEA_IN ) { } else if ( p.kind == fgIOCHANNEL::FG_SERIAL_GARMAN_IN ) {
read_nmea_in(s); read_garman_in(p);
} else if ( kind == FG_SERIAL_GARMAN_OUT ) { } else if ( p.kind == fgIOCHANNEL::FG_SERIAL_FGFS_OUT ) {
if (cur_time_params.cur_time > last_time ) { send_fgfs_out(p);
send_garman_out(s); } else if ( p.kind == fgIOCHANNEL::FG_SERIAL_FGFS_IN ) {
} read_fgfs_in(p);
last_time = cur_time_params.cur_time;
} else if ( kind == FG_SERIAL_GARMAN_IN ) {
read_garman_in(s);
} else if ( kind == FG_SERIAL_FGFS_OUT ) {
send_fgfs_out(s);
} else if ( kind == FG_SERIAL_FGFS_IN ) {
read_fgfs_in(s);
} }
} }
// process any serial port work // process any serial port work
void fgSerialProcess() { void fgSerialProcess() {
if ( port_a_kind != FG_SERIAL_DISABLED ) { fgIOCHANNEL port;
process_port(port_a, port_a_kind);
} const_io_iterator current = port_list.begin();
const_io_iterator last = port_list.end();
if ( port_b_kind != FG_SERIAL_DISABLED ) { for ( ; current != last; ++current ) {
process_port(port_b, port_b_kind); port = *current;
} if ( port.kind != fgIOCHANNEL::FG_SERIAL_DISABLED ) {
process_port ( port );
if ( port_c_kind != FG_SERIAL_DISABLED ) { }
process_port(port_c, port_c_kind);
}
if ( port_d_kind != FG_SERIAL_DISABLED ) {
process_port(port_d, port_d_kind);
} }
} }
// $Log$ // $Log$
// Revision 1.4 1998/11/25 01:33:58 curt
// Support for an arbitrary number of serial ports.
//
// Revision 1.3 1998/11/23 20:51:51 curt // Revision 1.3 1998/11/23 20:51:51 curt
// Tweaking serial stuff. // Tweaking serial stuff.
// //

View file

@ -34,15 +34,27 @@
#include <Serial/serial.hxx> #include <Serial/serial.hxx>
// Types of serial port protocols class fgIOCHANNEL {
enum fgSerialPortKind {
FG_SERIAL_DISABLED = 0, public:
FG_SERIAL_NMEA_OUT = 1,
FG_SERIAL_NMEA_IN = 2, // Types of serial port protocols
FG_SERIAL_GARMAN_OUT = 3, enum fgPortKind {
FG_SERIAL_GARMAN_IN = 4, FG_SERIAL_DISABLED = 0,
FG_SERIAL_FGFS_OUT = 5, FG_SERIAL_NMEA_OUT = 1,
FG_SERIAL_FGFS_IN = 6 FG_SERIAL_NMEA_IN = 2,
FG_SERIAL_GARMAN_OUT = 3,
FG_SERIAL_GARMAN_IN = 4,
FG_SERIAL_FGFS_OUT = 5,
FG_SERIAL_FGFS_IN = 6
};
fgPortKind kind;
fgSERIAL port;
long last_time;
fgIOCHANNEL();
~fgIOCHANNEL();
}; };
@ -51,10 +63,10 @@ enum fgSerialPortKind {
// the underlying layer. // the underlying layer.
// define the four channels // define the four channels
extern fgSERIAL port_a; // extern fgIOCHANNEL port_a;
extern fgSERIAL port_b; // extern fgIOCHANNEL port_b;
extern fgSERIAL port_c; // extern fgIOCHANNEL port_c;
extern fgSERIAL port_d; // extern fgIOCHANNEL port_d;
// initialize serial ports based on command line options (if any) // initialize serial ports based on command line options (if any)
@ -69,6 +81,9 @@ void fgSerialProcess();
// $Log$ // $Log$
// Revision 1.3 1998/11/25 01:33:59 curt
// Support for an arbitrary number of serial ports.
//
// Revision 1.2 1998/11/19 13:53:27 curt // Revision 1.2 1998/11/19 13:53:27 curt
// Added a "Garman" mode. // Added a "Garman" mode.
// //

View file

@ -150,18 +150,7 @@ fgOPTIONS::fgOPTIONS() :
tris_or_culled(0), tris_or_culled(0),
// Time options // Time options
time_offset(0), time_offset(0)
// Serial port options
// port_a(FG_SERIAL_DISABLED),
// port_b(FG_SERIAL_DISABLED),
// port_c(FG_SERIAL_DISABLED),
// port_d(FG_SERIAL_DISABLED),
port_a_config(""),
port_b_config(""),
port_c_config(""),
port_d_config("")
{ {
// set initial values/defaults // set initial values/defaults
@ -184,6 +173,10 @@ fgOPTIONS::fgOPTIONS() :
} }
airport_id = ""; // default airport id airport_id = ""; // default airport id
// initialize port config string list
port_options_list.erase ( port_options_list.begin(),
port_options_list.end() );
} }
@ -344,25 +337,23 @@ fgOPTIONS::parse_fov( const string& arg ) {
} }
// Parse serial port option --serial=a,/dev/ttyS1,nmea,4800,out // Parse serial port option --serial=/dev/ttyS1,nmea,4800,out
// //
// Format is "--serial=port_id,device,format,baud,direction" where // Format is "--serial=device,format,baud,direction" where
// //
// port_id = {a, b, c, d}
// device = OS device name to be open()'ed // device = OS device name to be open()'ed
// format = {nmea, fgfs} // format = {nmea, fgfs}
// baud = {300, 1200, 2400, ..., 230400} // baud = {300, 1200, 2400, ..., 230400}
// direction = {in, out, bi} // direction = {in, out, bi}
//
bool bool
fgOPTIONS::parse_serial( const string& serial_str ) { fgOPTIONS::parse_serial( const string& serial_str ) {
string::size_type pos; string::size_type pos;
string port;
string config;
// cout << "Serial string = " << serial_str << endl; // cout << "Serial string = " << serial_str << endl;
// port // a flailing attempt to see if the port config string has a
// chance at being valid
pos = serial_str.find(","); pos = serial_str.find(",");
if ( pos == string::npos ) { if ( pos == string::npos ) {
FG_LOG( FG_GENERAL, FG_ALERT, FG_LOG( FG_GENERAL, FG_ALERT,
@ -370,22 +361,7 @@ fgOPTIONS::parse_serial( const string& serial_str ) {
return false; return false;
} }
port = serial_str.substr(0, pos); port_options_list.push_back( serial_str );
config = serial_str.substr(++pos);
if ( port == "a" ) {
port_a_config = config;
} else if ( port == "b" ) {
port_b_config = config;
} else if ( port == "c" ) {
port_c_config = config;
} else if ( port == "d" ) {
port_d_config = config;
} else {
FG_LOG( FG_GENERAL, FG_ALERT, "Valid ports are a - d, config for port "
<< port << " ignored" );
return false;
}
return true; return true;
} }
@ -642,6 +618,9 @@ fgOPTIONS::~fgOPTIONS( void ) {
// $Log$ // $Log$
// Revision 1.32 1998/11/25 01:34:00 curt
// Support for an arbitrary number of serial ports.
//
// Revision 1.31 1998/11/23 21:49:04 curt // Revision 1.31 1998/11/23 21:49:04 curt
// Borland portability tweaks. // Borland portability tweaks.
// //

View file

@ -45,9 +45,21 @@
#include <Include/compiler.h> #include <Include/compiler.h>
FG_USING_STD(string); FG_USING_STD(string);
#include <vector>
#include "Include/fg_stl_config.h"
#ifdef NEEDNAMESPACESTD
using namespace std;
#endif
#include "fg_serial.hxx" #include "fg_serial.hxx"
typedef vector < string > str_container;
typedef str_container::iterator str_iterator;
typedef str_container::const_iterator const_str_iterator;
class fgOPTIONS { class fgOPTIONS {
public: public:
@ -139,10 +151,7 @@ private:
// fgSerialPortKind port_d_kind; // Port d kind // fgSerialPortKind port_d_kind; // Port d kind
// Serial port configuration strings // Serial port configuration strings
string port_a_config; str_container port_options_list;
string port_b_config;
string port_c_config;
string port_d_config;
public: public:
@ -197,15 +206,9 @@ public:
inline int get_time_offset() const { return time_offset; } inline int get_time_offset() const { return time_offset; }
// inline fgSerialPortKind get_port_a_kind() const { return port_a_kind; } inline str_container get_port_options_list() const {
// inline fgSerialPortKind get_port_b_kind() const { return port_b_kind; } return port_options_list;
// inline fgSerialPortKind get_port_c_kind() const { return port_c_kind; } }
// inline fgSerialPortKind get_port_d_kind() const { return port_d_kind; }
inline string get_port_a_config() const { return port_a_config; }
inline string get_port_b_config() const { return port_b_config; }
inline string get_port_c_config() const { return port_c_config; }
inline string get_port_d_config() const { return port_d_config; }
// Update functions // Update functions
inline void set_hud_status( bool status ) { hud_status = status; } inline void set_hud_status( bool status ) { hud_status = status; }
@ -244,6 +247,9 @@ extern fgOPTIONS current_options;
// $Log$ // $Log$
// Revision 1.24 1998/11/25 01:34:01 curt
// Support for an arbitrary number of serial ports.
//
// Revision 1.23 1998/11/23 21:49:05 curt // Revision 1.23 1998/11/23 21:49:05 curt
// Borland portability tweaks. // Borland portability tweaks.
// //