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 <string>
#include <vector>
#include "Include/fg_stl_config.h"
#ifdef NEEDNAMESPACESTD
using namespace std;
#endif
#include <Aircraft/aircraft.hxx>
#include <Debug/logstream.hxx>
@ -36,27 +43,34 @@
#include "fg_serial.hxx"
// support up to four serial channels. Each channel can be assigned
// to an arbitrary port. Bi-directional communication is supported by
// the underlying layer.
// 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
fgSERIAL port_a;
fgSERIAL port_b;
fgSERIAL port_c;
fgSERIAL port_d;
io_container port_list;
// the type of each channel
fgSerialPortKind port_a_kind = FG_SERIAL_DISABLED;
fgSerialPortKind port_b_kind = FG_SERIAL_DISABLED;
fgSerialPortKind port_c_kind = FG_SERIAL_DISABLED;
fgSerialPortKind port_d_kind = FG_SERIAL_DISABLED;
fgIOCHANNEL::fgIOCHANNEL() :
kind( FG_SERIAL_DISABLED )
{
}
fgIOCHANNEL::~fgIOCHANNEL() {
}
// configure a port based on the config string
static bool config_port(fgSERIAL& s, fgSerialPortKind& kind,
const string& config)
static fgIOCHANNEL config_port( const string& config )
{
fgIOCHANNEL p;
string::size_type begin, end;
string device;
@ -64,108 +78,106 @@ static bool config_port(fgSERIAL& s, fgSerialPortKind& kind,
string baud;
string direction;
begin = 0;;
begin = 0;
FG_LOG( FG_SERIAL, FG_INFO, "Configuring serial port: " << config );
// device name
end = config.find(",", begin);
if ( end == string::npos ) {
return false;
return p;
}
device = config.substr(begin, end - begin);
begin = end + 1;
cout << " device = " << device << endl;
FG_LOG( FG_SERIAL, FG_INFO, " device = " << device );
// format
end = config.find(",", begin);
if ( end == string::npos ) {
return false;
return p;
}
format = config.substr(begin, end - begin);
begin = end + 1;
cout << " format = " << format << endl;
FG_LOG( FG_SERIAL, FG_INFO, " format = " << format );
// baud
end = config.find(",", begin);
if ( end == string::npos ) {
return false;
return p;
}
baud = config.substr(begin, end - begin);
begin = end + 1;
cout << " baud = " << baud << endl;
FG_LOG( FG_SERIAL, FG_INFO, " baud = " << baud );
// direction
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 "
<< "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 );
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 );
return p;
}
if ( format == "nmea" ) {
if ( direction == "out" ) {
kind = FG_SERIAL_NMEA_OUT;
p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_OUT;
} else if ( direction == "in" ) {
kind = FG_SERIAL_NMEA_IN;
p.kind = fgIOCHANNEL::FG_SERIAL_NMEA_IN;
} else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
}
} else if ( format == "garman" ) {
if ( direction == "out" ) {
kind = FG_SERIAL_GARMAN_OUT;
p.kind = fgIOCHANNEL::FG_SERIAL_GARMAN_OUT;
} else if ( direction == "in" ) {
kind = FG_SERIAL_GARMAN_IN;
p.kind = fgIOCHANNEL::FG_SERIAL_GARMAN_IN;
} else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
}
} else if ( format == "fgfs" ) {
if ( direction == "out" ) {
kind = FG_SERIAL_FGFS_OUT;
p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_OUT;
} else if ( direction == "in" ) {
kind = FG_SERIAL_FGFS_IN;
p.kind = fgIOCHANNEL::FG_SERIAL_FGFS_IN;
} else {
FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
return false;
}
} else {
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() {
if ( current_options.get_port_a_config() != "" ) {
config_port(port_a, port_a_kind, current_options.get_port_a_config() );
}
fgIOCHANNEL port;
str_container port_options_list = current_options.get_port_options_list();
if ( current_options.get_port_b_config() != "" ) {
config_port(port_b, port_b_kind, current_options.get_port_b_config() );
}
const_str_iterator current = port_options_list.begin();
const_str_iterator last = port_options_list.end();
if ( current_options.get_port_c_config() != "" ) {
config_port(port_c, port_c_kind, current_options.get_port_c_config() );
}
if ( current_options.get_port_d_config() != "" ) {
config_port(port_d, port_d_kind, current_options.get_port_d_config() );
for ( ; current != last; ++current ) {
port = config_port( *current );
if ( port.kind != fgIOCHANNEL::FG_SERIAL_DISABLED ) {
port_list.push_back( port );
}
}
}
@ -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_sum[10], gga_sum[10];
char dir;
@ -198,6 +210,12 @@ static void send_nmea_out( fgSERIAL& s ) {
fgFLIGHT *f;
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;
t = &cur_time_params;
@ -266,7 +284,7 @@ static void send_nmea_out( fgSERIAL& s ) {
rmc_sentence += "*";
rmc_sentence += rmc_sum;
rmc_sentence += "\r\n";
s.write_port(rmc_sentence);
p.port.write_port(rmc_sentence);
} else {
// gga on odd seconds
string gga_sentence = "$";
@ -274,14 +292,14 @@ static void send_nmea_out( fgSERIAL& s ) {
gga_sentence += "*";
gga_sentence += gga_sum;
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 dir;
int deg;
@ -289,6 +307,12 @@ static void send_garman_out( fgSERIAL& s ) {
fgFLIGHT *f;
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;
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
if ( cur_time_params.cur_time % 2 == 0 ) {
// rmc on even seconds
s.write_port(rmc);
p.port.write_port(rmc);
} else {
// gga on odd seconds
s.write_port(rmz);
// rmz on odd seconds
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 ...
static void process_port( fgSERIAL& s, const fgSerialPortKind kind ) {
static long last_time;
if ( kind == FG_SERIAL_NMEA_OUT ) {
if (cur_time_params.cur_time > last_time ) {
send_nmea_out(s);
}
last_time = cur_time_params.cur_time;
} else if ( kind == FG_SERIAL_NMEA_IN ) {
read_nmea_in(s);
} else if ( kind == FG_SERIAL_GARMAN_OUT ) {
if (cur_time_params.cur_time > last_time ) {
send_garman_out(s);
}
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);
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_GARMAN_OUT ) {
send_garman_out(p);
} else if ( p.kind == fgIOCHANNEL::FG_SERIAL_GARMAN_IN ) {
read_garman_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);
}
}
// process any serial port work
void fgSerialProcess() {
if ( port_a_kind != FG_SERIAL_DISABLED ) {
process_port(port_a, port_a_kind);
}
fgIOCHANNEL port;
const_io_iterator current = port_list.begin();
const_io_iterator last = port_list.end();
if ( port_b_kind != FG_SERIAL_DISABLED ) {
process_port(port_b, port_b_kind);
}
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);
for ( ; current != last; ++current ) {
port = *current;
if ( port.kind != fgIOCHANNEL::FG_SERIAL_DISABLED ) {
process_port ( port );
}
}
}
// $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
// Tweaking serial stuff.
//

View file

@ -34,15 +34,27 @@
#include <Serial/serial.hxx>
// Types of serial port protocols
enum fgSerialPortKind {
FG_SERIAL_DISABLED = 0,
FG_SERIAL_NMEA_OUT = 1,
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
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_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.
// define the four channels
extern fgSERIAL port_a;
extern fgSERIAL port_b;
extern fgSERIAL port_c;
extern fgSERIAL port_d;
// 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)
@ -69,6 +81,9 @@ void fgSerialProcess();
// $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
// Added a "Garman" mode.
//

View file

@ -150,18 +150,7 @@ fgOPTIONS::fgOPTIONS() :
tris_or_culled(0),
// Time options
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("")
time_offset(0)
{
// set initial values/defaults
@ -184,6 +173,10 @@ fgOPTIONS::fgOPTIONS() :
}
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
// format = {nmea, fgfs}
// baud = {300, 1200, 2400, ..., 230400}
// direction = {in, out, bi}
//
bool
fgOPTIONS::parse_serial( const string& serial_str ) {
string::size_type pos;
string port;
string config;
// 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(",");
if ( pos == string::npos ) {
FG_LOG( FG_GENERAL, FG_ALERT,
@ -370,22 +361,7 @@ fgOPTIONS::parse_serial( const string& serial_str ) {
return false;
}
port = serial_str.substr(0, pos);
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;
}
port_options_list.push_back( serial_str );
return true;
}
@ -642,6 +618,9 @@ fgOPTIONS::~fgOPTIONS( void ) {
// $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
// Borland portability tweaks.
//

View file

@ -45,9 +45,21 @@
#include <Include/compiler.h>
FG_USING_STD(string);
#include <vector>
#include "Include/fg_stl_config.h"
#ifdef NEEDNAMESPACESTD
using namespace std;
#endif
#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 {
public:
@ -139,10 +151,7 @@ private:
// fgSerialPortKind port_d_kind; // Port d kind
// Serial port configuration strings
string port_a_config;
string port_b_config;
string port_c_config;
string port_d_config;
str_container port_options_list;
public:
@ -197,15 +206,9 @@ public:
inline int get_time_offset() const { return time_offset; }
// inline fgSerialPortKind get_port_a_kind() const { return port_a_kind; }
// inline fgSerialPortKind get_port_b_kind() const { return port_b_kind; }
// 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; }
inline str_container get_port_options_list() const {
return port_options_list;
}
// Update functions
inline void set_hud_status( bool status ) { hud_status = status; }
@ -244,6 +247,9 @@ extern fgOPTIONS current_options;
// $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
// Borland portability tweaks.
//