1 // ATC-Main.cxx -- FGFS interface to ATC hardware
3 // Written by Curtis Olson, started January 2002
5 // Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 #include <simgear/compiler.h>
30 #include <stdlib.h> // atoi() atof() abs()
31 #include <sys/types.h>
34 #include <stdio.h> //snprintf
35 #if defined( _MSC_VER ) || defined(__MINGW32__)
36 # include <io.h> //lseek, read, write
43 #include <simgear/debug/logstream.hxx>
44 #include <simgear/props/props_io.hxx>
45 #include <simgear/io/iochannel.hxx>
46 #include <simgear/math/sg_types.hxx>
47 #include <simgear/misc/sg_path.hxx>
48 #include <simgear/props/props.hxx>
50 #include <Scripting/NasalSys.hxx>
51 #include <Main/fg_props.hxx>
52 #include <Main/globals.hxx>
54 #include "ATC-Main.hxx"
59 // Lock the ATC hardware
60 static int fgATCMainLock( int fd ) {
62 lseek( fd, 0, SEEK_SET );
65 int result = read( fd, tmp, 1 );
67 SG_LOG( SG_IO, SG_DEBUG, "Lock failed" );
74 // Write a radios command
75 static int fgATCMainRelease( int fd ) {
77 lseek( fd, 0, SEEK_SET );
81 int result = write( fd, tmp, 1 );
84 SG_LOG( SG_IO, SG_DEBUG, "Release failed" );
91 void FGATCMain::init_config() {
92 #if defined( unix ) || defined( __CYGWIN__ )
93 // Next check home directory for .fgfsrc.hostname file
94 char *envp = ::getenv( "HOME" );
96 SGPath atcsim_config( envp );
97 atcsim_config.append( ".fgfs-atc610x.xml" );
99 SG_LOG(SG_GENERAL, SG_ALERT,
100 "Warning: loading deprecated config file: " <<
101 atcsim_config.str() );
102 readProperties( atcsim_config.str(), globals->get_props() );
103 } catch (const sg_exception &e) {
104 // fail silently, this is an old style config file I want to continue
105 // to support if it exists.
112 // Open and initialize ATC hardware
113 bool FGATCMain::open() {
114 if ( is_enabled() ) {
115 SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
116 << "is already in use, ignoring" );
120 SG_LOG( SG_IO, SG_ALERT,
121 "Initializing ATC hardware, please wait ..." );
123 // This loads the config parameters generated by "simcal"
126 /////////////////////////////////////////////////////////////////////
127 // Open the /proc files
128 /////////////////////////////////////////////////////////////////////
130 string lock0_file = "/proc/atcflightsim/board0/lock";
131 string lock1_file = "/proc/atcflightsim/board1/lock";
133 lock0_fd = ::open( lock0_file.c_str(), O_RDWR );
134 if ( lock0_fd == -1 ) {
135 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
137 snprintf( msg, 256, "Error opening %s", lock0_file.c_str() );
142 lock1_fd = ::open( lock1_file.c_str(), O_RDWR );
143 if ( lock1_fd == -1 ) {
144 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
146 snprintf( msg, 256, "Error opening %s", lock1_file.c_str() );
151 if ( input0_path.str().length() ) {
152 input0 = new FGATCInput( 0, input0_path );
155 if ( input1_path.str().length() ) {
156 input1 = new FGATCInput( 1, input1_path );
159 if ( output0_path.str().length() ) {
160 output0 = new FGATCOutput( 0, output0_path );
161 output0->open( lock0_fd );
163 if ( output1_path.str().length() ) {
164 output1 = new FGATCOutput( 1, output1_path );
165 output1->open( lock1_fd );
168 set_hz( 30 ); // default to processing requests @ 30Hz
171 /////////////////////////////////////////////////////////////////////
172 // Finished initing hardware
173 /////////////////////////////////////////////////////////////////////
175 SG_LOG( SG_IO, SG_ALERT,
176 "Done initializing ATC hardware." );
182 bool FGATCMain::process() {
183 // cout << "Main::process()\n";
185 bool board0_locked = false;
186 bool board1_locked = false;
188 if ( input0 != NULL || output0 != NULL ) {
189 // Lock board0 if we have a configuration for it
190 if ( fgATCMainLock( lock0_fd ) > 0 ) {
191 board0_locked = true;
195 if ( input1 != NULL || output1 != NULL ) {
196 // Lock board1 if we have a configuration for it
197 if ( fgATCMainLock( lock1_fd ) > 0 ) {
198 board1_locked = true;
202 // cout << " locks: ";
203 // if ( board0_locked ) { cout << "board0 "; }
204 // if ( board1_locked ) { cout << "board1 "; }
207 // process the ATC inputs
208 if ( input0 != NULL && board0_locked ) {
211 if ( input1 != NULL && board1_locked ) {
215 // run our custom nasal script. This is a layer above the raw
216 // hardware inputs. It handles situations where there isn't a
217 // direct 1-1 linear mapping between ATC functionality and FG
218 // functionality, and handles situations where FG expects more
219 // functionality from the interface than the ATC hardware can
222 FGNasalSys *n = (FGNasalSys*)globals->get_subsystem("nasal");
223 bool result = n->parseAndRun( "atcsim.update()" );
225 SG_LOG( SG_GENERAL, SG_ALERT, "Nasal: atcsim.update() failed!" );
228 // process the ATC outputs
229 if ( output0 != NULL && board0_locked ) {
232 if ( output1 != NULL && board1_locked ) {
236 if ( board0_locked ) {
237 fgATCMainRelease( lock0_fd );
239 if ( board1_locked ) {
240 fgATCMainRelease( lock1_fd );
247 bool FGATCMain::close() {
248 cout << "FGATCMain::close()" << endl;
252 if ( input0 != NULL ) {
255 if ( input1 != NULL ) {
258 if ( output0 != NULL ) {
261 if ( output1 != NULL ) {
265 result = ::close( lock0_fd );
266 if ( result == -1 ) {
267 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
269 snprintf( msg, 256, "Error closing lock0_fd" );
274 result = ::close( lock1_fd );
275 if ( result == -1 ) {
276 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
278 snprintf( msg, 256, "Error closing lock1_fd" );