]> git.mxchange.org Git - flightgear.git/blob - Main/fg_serial.cxx
Initial revision.
[flightgear.git] / Main / fg_serial.cxx
1 // fg_serial.cxx -- higher level serial port management routines
2 //
3 // Written by Curtis Olson, started November 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22 // (Log is kept at end of this file)
23
24
25 #include <stdlib.h>   // atoi()
26 #include <string>
27
28 #include <Aircraft/aircraft.hxx>
29 #include <Debug/logstream.hxx>
30 #include <Include/fg_constants.h>
31 #include <Serial/serial.hxx>
32 #include <Time/fg_time.hxx>
33
34 #include "options.hxx"
35
36 #include "fg_serial.hxx"
37
38
39 // support up to four serial channels.  Each channel can be assigned
40 // to an arbitrary port.  Bi-directional communication is supported by
41 // the underlying layer.
42
43 // define the four channels
44 fgSERIAL port_a;
45 fgSERIAL port_b;
46 fgSERIAL port_c;
47 fgSERIAL port_d;
48
49 // the type of each channel
50 fgSerialPortKind port_a_kind = FG_SERIAL_DISABLED;
51 fgSerialPortKind port_b_kind = FG_SERIAL_DISABLED;
52 fgSerialPortKind port_c_kind = FG_SERIAL_DISABLED;
53 fgSerialPortKind port_d_kind = FG_SERIAL_DISABLED;
54
55
56 // configure a port based on the config string
57 static bool config_port(fgSERIAL& s, fgSerialPortKind& kind,
58                                     const string& config)
59 {
60     string::size_type begin, end;
61
62     string device;
63     string format;
64     string baud;
65     string direction;
66
67     begin = 0;;
68
69     // device name
70     end = config.find(",", begin);
71     if ( end == string::npos ) {
72         return false;
73     }
74     
75     device = config.substr(begin, end - begin);
76     begin = end + 1;
77     cout << "  device = " << device << endl;
78
79     // format
80     end = config.find(",", begin);
81     if ( end == string::npos ) {
82         return false;
83     }
84     
85     format = config.substr(begin, end - begin);
86     begin = end + 1;
87     cout << "  format = " << format << endl;
88
89     // baud
90     end = config.find(",", begin);
91     if ( end == string::npos ) {
92         return false;
93     }
94     
95     baud = config.substr(begin, end - begin);
96     begin = end + 1;
97     cout << "  baud = " << baud << endl;
98
99     // direction
100     direction = config.substr(begin);
101     cout << "  direction = " << direction << endl;
102
103     if ( s.is_enabled() ) {
104         FG_LOG( FG_SERIAL, FG_ALERT, "This shouldn't happen, but the port " 
105                 << "is already in use, ignoring" );
106         return false;
107     }
108
109     if ( ! s.open_port( device ) ) {
110         FG_LOG( FG_SERIAL, FG_ALERT, "Error opening device: " << device );
111     }
112
113     if ( ! s.set_baud( atoi( baud.c_str() ) ) ) {
114         FG_LOG( FG_SERIAL, FG_ALERT, "Error setting baud: " << baud );
115     }
116
117     if ( format == "nmea" ) {
118         if ( direction == "out" ) {
119             kind = FG_SERIAL_NMEA_OUT;
120         } else if ( direction == "in" ) {
121             kind = FG_SERIAL_NMEA_IN;
122         } else {
123             FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
124             return false;
125         }
126     } else if ( format == "fgfs" ) {
127         if ( direction == "out" ) {
128             kind = FG_SERIAL_FGFS_OUT;
129         } else if ( direction == "in" ) {
130             kind = FG_SERIAL_FGFS_IN;
131         } else {
132             FG_LOG( FG_SERIAL, FG_ALERT, "Unknown direction" );
133             return false;
134         }
135     } else {
136         FG_LOG( FG_SERIAL, FG_ALERT, "Unknown format" );
137         return false;
138     }
139
140     return true;
141 }
142
143
144 // initialize serial ports based on command line options (if any)
145 void fgSerialInit() {
146     if ( current_options.get_port_a_config() != "" ) {
147         config_port(port_a, port_a_kind, current_options.get_port_a_config() );
148     }
149
150     if ( current_options.get_port_b_config() != "" ) {
151         config_port(port_b, port_b_kind, current_options.get_port_b_config() );
152     }
153
154     if ( current_options.get_port_c_config() != "" ) {
155         config_port(port_c, port_c_kind, current_options.get_port_c_config() );
156     }
157
158     if ( current_options.get_port_d_config() != "" ) {
159         config_port(port_d, port_d_kind, current_options.get_port_d_config() );
160     }
161 }
162
163
164 static void send_nmea_out( fgSERIAL& s ) {
165     char nmea[256];
166     char dir;
167     int deg;
168     double min;
169     fgFLIGHT *f;
170     fgTIME *t;
171
172     f = current_aircraft.flight;
173     t = &cur_time_params;
174
175     char utc[10];
176     sprintf( utc, "%02d%02d%02d", 
177              t->gmt->tm_hour, t->gmt->tm_min, t->gmt->tm_sec );
178
179     char lat[20];
180     double latd = FG_Latitude * RAD_TO_DEG;
181     if ( latd < 0.0 ) {
182         latd *= -1.0;
183         dir = 'S';
184     } else {
185         dir = 'N';
186     }
187     deg = (int)(latd);
188     min = (latd - (double)deg) * 60.0;
189     sprintf( lat, "%02d%06.3f,%c", abs(deg), min, dir);
190
191     char lon[20];
192     double lond = FG_Longitude * RAD_TO_DEG;
193     if ( lond < 0.0 ) {
194         lond *= -1.0;
195         dir = 'W';
196     } else {
197         dir = 'E';
198     }
199     deg = (int)(lond);
200     min = (lond - (double)deg) * 60.0;
201     sprintf( lon, "%02d%06.3f,%c", abs(deg), min, dir);
202
203     char speed[10];
204     sprintf( speed, "%05.1f", FG_V_equiv_kts );
205
206     char heading[10];
207     sprintf( heading, "%05.1f", FG_Psi * RAD_TO_DEG );
208
209     char date[10];
210     sprintf( date, "%02d%02d%02d", 
211              t->gmt->tm_mday, t->gmt->tm_mon+1, t->gmt->tm_year );
212
213     // $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
214     sprintf( nmea, "$GPRMC,%s,A,%s,%s,%s,%s,%s,000.0,E*00\n",
215              utc, lat, lon, speed, heading, date );
216
217     FG_LOG( FG_SERIAL, FG_DEBUG, nmea << endl );
218     s.write_port(nmea);
219 }
220
221 static void read_nmea_in( fgSERIAL& s ) {
222 }
223
224 static void send_fgfs_out( fgSERIAL& s ) {
225 }
226
227 static void read_fgfs_in( fgSERIAL& s ) {
228 }
229
230
231 // one more level of indirection ...
232 static void process_port( fgSERIAL& s, const fgSerialPortKind kind ) {
233     if ( kind == FG_SERIAL_NMEA_OUT ) {
234         send_nmea_out(s);
235     } else if ( kind == FG_SERIAL_NMEA_IN ) {
236         read_nmea_in(s);
237     } else if ( kind == FG_SERIAL_FGFS_OUT ) {
238         send_fgfs_out(s);
239     } else if ( kind == FG_SERIAL_FGFS_IN ) {
240         read_fgfs_in(s);
241     }
242 }
243
244
245 // process any serial port work
246 void fgSerialProcess() {
247     if ( port_a_kind != FG_SERIAL_DISABLED ) {
248         process_port(port_a, port_a_kind);
249     }
250
251     if ( port_b_kind != FG_SERIAL_DISABLED ) {
252         process_port(port_b, port_b_kind);
253     }
254
255     if ( port_c_kind != FG_SERIAL_DISABLED ) {
256         process_port(port_c, port_c_kind);
257     }
258
259     if ( port_d_kind != FG_SERIAL_DISABLED ) {
260         process_port(port_d, port_d_kind);
261     }
262 }
263
264
265 // $Log$
266 // Revision 1.1  1998/11/16 13:57:42  curt
267 // Initial revision.
268 //