//
// 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.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#include <simgear/compiler.h>
-#include STL_STRING
+#if defined( unix ) || defined( __CYGWIN__ )
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <istream>
+#endif
+
+#include <errno.h>
+#include <math.h>
+
+#include <string>
#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props_io.hxx>
#include <Main/fg_props.hxx>
#include "ATC-Inputs.hxx"
-SG_USING_STD(string);
+using std::string;
// Read analog inputs
static void ATCReadAnalogInputs( int fd, unsigned char *analog_in_bytes ) {
+#if defined( unix ) || defined( __CYGWIN__ )
// rewind
lseek( fd, 0, SEEK_SET );
SG_LOG( SG_IO, SG_ALERT, "Read failed" );
exit( -1 );
}
+#endif
}
// Read status of radio switches and knobs
static void ATCReadRadios( int fd, unsigned char *switch_data ) {
+#if defined( unix ) || defined( __CYGWIN__ )
// rewind
lseek( fd, 0, SEEK_SET );
SG_LOG( SG_IO, SG_ALERT, "Read failed" );
exit( -1 );
}
+#endif
}
// Read switch inputs
static void ATCReadSwitches( int fd, unsigned char *switch_bytes ) {
+#if defined( unix ) || defined( __CYGWIN__ )
// rewind
lseek( fd, 0, SEEK_SET );
SG_LOG( SG_IO, SG_ALERT, "Read failed" );
exit( -1 );
}
+#endif
}
init_config();
SG_LOG( SG_IO, SG_ALERT,
- "Initializing ATC 610x hardware, please wait ..." );
+ "Initializing ATC input hardware, please wait ..." );
- snprintf( lock_file, 256, "/proc/atc610x/board%d/lock", board );
- snprintf( analog_in_file, 256, "/proc/atc610x/board%d/analog_in", board );
- snprintf( radios_file, 256, "/proc/atc610x/board%d/radios", board );
- snprintf( switches_file, 256, "/proc/atc610x/board%d/switches", board );
+ snprintf( analog_in_file, 256,
+ "/proc/atcflightsim/board%d/analog_in", board );
+ snprintf( radios_file, 256,
+ "/proc/atcflightsim/board%d/radios", board );
+ snprintf( switches_file, 256,
+ "/proc/atcflightsim/board%d/switches", board );
+
+#if defined( unix ) || defined( __CYGWIN__ )
/////////////////////////////////////////////////////////////////////
// Open the /proc files
/////////////////////////////////////////////////////////////////////
- lock_fd = ::open( lock_file, O_RDWR );
- if ( lock_fd == -1 ) {
- SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
- char msg[256];
- snprintf( msg, 256, "Error opening %s", lock_file );
- perror( msg );
- exit( -1 );
- }
-
analog_in_fd = ::open( analog_in_file, O_RDONLY );
if ( analog_in_fd == -1 ) {
SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
exit( -1 );
}
+#endif
+
/////////////////////////////////////////////////////////////////////
// Finished initing hardware
/////////////////////////////////////////////////////////////////////
SG_LOG( SG_IO, SG_ALERT,
- "Done initializing ATC 610x hardware." );
+ "Done initializing ATC input hardware." );
is_open = true;
/////////////////////////////////////////////////////////////////////
// scale a number between min and max (with center defined) to a scale
-// from -1.0 to 1.0
-static double scale( int center, int min, int max, int value ) {
+// from -1.0 to 1.0. The deadband value is symmetric, so specifying
+// '1' will give you a deadband of +/-1
+static double scale( int center, int deadband, int min, int max, int value ) {
// cout << center << " " << min << " " << max << " " << value << " ";
double result;
double range;
- if ( value <= center ) {
- range = center - min;
- result = (value - center) / range;
+ if ( value <= (center - deadband) ) {
+ range = (center - deadband) - min;
+ result = (value - (center - deadband)) / range;
+ } else if ( value >= (center + deadband) ) {
+ range = max - (center + deadband);
+ result = (value - (center + deadband)) / range;
} else {
- range = max - center;
- result = (value - center) / range;
+ result = 0.0;
}
if ( result < -1.0 ) result = -1.0;
}
+static double clamp( double min, double max, double value ) {
+ double result = value;
+
+ if ( result < min ) result = min;
+ if ( result > max ) result = max;
+
+ // cout << result << endl;
+
+ return result;
+}
+
+
static int tony_magic( int raw, int obs[3] ) {
int result = 0;
string name = "";
string type = "";
string subtype = "";
- vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+ vector <SGPropertyNode *> output_nodes;
int center = -1;
int min = 0;
int max = 1023;
+ int deadband = 0;
+ int hysteresis = 0;
+ float offset = 0.0;
float factor = 1.0;
if ( cname == "channel" ) {
SGPropertyNode *prop;
if ( prop != NULL ) {
max = prop->getIntValue();
}
+ prop = child->getChild( "deadband" );
+ if ( prop != NULL ) {
+ deadband = prop->getIntValue();
+ }
+ prop = child->getChild( "hysteresis" );
+ if ( prop != NULL ) {
+ hysteresis = prop->getIntValue();
+ }
+ prop = child->getChild( "offset" );
+ if ( prop != NULL ) {
+ offset = prop->getFloatValue();
+ }
prop = child->getChild( "factor" );
if ( prop != NULL ) {
factor = prop->getFloatValue();
{
// "Cook" the raw value
float scaled_value = 0.0f;
+
+ if ( hysteresis > 0 ) {
+ int last_raw_value = 0;
+ prop = child->getChild( "last-raw-value", 0, true );
+ last_raw_value = prop->getIntValue();
+
+ if ( abs(raw_value - last_raw_value) < hysteresis )
+ {
+ // not enough movement stay put
+ raw_value = last_raw_value;
+ } else {
+ // update last raw value
+ prop->setIntValue( raw_value );
+ }
+ }
+
if ( center >= 0 ) {
- scaled_value = scale( center, min, max, raw_value );
+ scaled_value = scale( center, deadband,
+ min, max, raw_value );
} else {
scaled_value = scale( min, max, raw_value );
}
scaled_value *= factor;
+ scaled_value += offset;
+
+ // final sanity clamp
+ if ( center >= 0 ) {
+ scaled_value = clamp( -1.0, 1.0, scaled_value );
+ } else {
+ scaled_value = clamp( 0.0, 1.0, scaled_value );
+ }
// update the property tree values
for ( j = 0; j < (int)output_nodes.size(); ++j ) {
// "Cook" the raw value
float scaled_value = 0.0f;
if ( center >= 0 ) {
- scaled_value = scale( center, min, max, raw_value );
+ scaled_value = scale( center, deadband,
+ min, max, raw_value );
} else {
scaled_value = scale( min, max, raw_value );
}
scaled_value *= factor;
+ scaled_value += offset;
+
+ // final sanity clamp
+ if ( center >= 0 ) {
+ scaled_value = clamp( -1.0, 1.0, scaled_value );
+ } else {
+ scaled_value = clamp( 0.0, 1.0, scaled_value );
+ }
// update the property tree values
for ( j = 0; j < (int)output_nodes.size(); ++j ) {
if ( value > max ) { value = max; }
}
- prop = child\0->getChild( "compass-heading" );
+ prop = child->getChild( "compass-heading" );
if ( prop != NULL ) {
bool compass = prop->getBoolValue();
if ( compass ) {
unsigned char switches = switch_data[row];
for( int column = 0; column < ATC_NUM_COLS; ++column ) {
- switch_matrix[board][column][row] = switches & 1;
- switches = switches >> 1;
- }
+ if ( row < 8 ) {
+ switch_matrix[board][column][row] = switches & 1;
+ } else {
+ switch_matrix[board][row-8][8+column] = switches & 1;
+ }
+ switches = switches >> 1;
+ }
}
}
string cname = child->getName();
string name = "";
string type = "";
- vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+ vector <SGPropertyNode *> output_nodes;
int row = -1;
int col = -1;
float factor = 1.0;
int filter = -1;
float scaled_value = 0.0f;
+ bool invert = false;
// get common options
if ( prop != NULL ) {
factor = prop->getFloatValue();
}
+ prop = child->getChild( "invert" );
+ if ( prop != NULL ) {
+ invert = prop->getBoolValue();
+ }
prop = child->getChild( "steady-state-filter" );
if ( prop != NULL ) {
filter = prop->getIntValue();
// Fetch the raw value
int raw_value = switch_matrix[board][row][col];
+ // Invert
+ if ( invert ) {
+ raw_value = !raw_value;
+ }
+
// Cook the value
scaled_value = (float)raw_value * factor;
// Cook the value
scaled_value *= factor;
+ } else if ( cname == "additive-switch" ) {
+ float additive_value = 0.0f;
+ float increment = 0.0f;
+
+ SGPropertyNode *pos;
+ int k = 0;
+ while ( (pos = child->getChild("position", k++)) != NULL ) {
+ // read the combo position entries from the property tree
+
+ prop = pos->getChild( "row" );
+ if ( prop != NULL ) {
+ row = prop->getIntValue();
+ }
+ prop = pos->getChild( "col" );
+ if ( prop != NULL ) {
+ col = prop->getIntValue();
+ }
+ prop = pos->getChild( "value" );
+ if ( prop != NULL ) {
+ increment = prop->getFloatValue();
+ }
+
+ // Fetch the raw value
+ int raw_value = switch_matrix[board][row][col];
+ // cout << "sm[" << board << "][" << row << "][" << col
+ // << "] = " << raw_value << endl;
+
+ if ( raw_value ) {
+ // set scaled_value to the first combo_value
+ // that matches and jump out of loop.
+ additive_value += increment;
+ }
+ }
+
+ // Cook the value
+ scaled_value = additive_value * factor;
}
// handle filter request. The value of the switch must be
if ( cname == "switch" ) {
string name = "";
string type = "";
- vector <SGPropertyNode *> output_nodes; output_nodes.clear();
+ vector <SGPropertyNode *> output_nodes;
int byte_num = -1;
- int right_shift = -1;
+ int right_shift = 0;
int mask = 0xff;
int factor = 1;
int offset = 0;
+ bool invert = false;
int scaled_value = 0;
-
// get common options
SGPropertyNode *prop;
if ( prop != NULL ) {
offset = prop->getIntValue();
}
+ prop = child->getChild( "invert" );
+ if ( prop != NULL ) {
+ invert = prop->getBoolValue();
+ }
// Fetch the raw value
int raw_value
= (radio_switch_data[byte_num] >> right_shift) & mask;
// Cook the value
+ if ( invert ) {
+ raw_value = !raw_value;
+ }
scaled_value = raw_value * factor + offset;
// update the property tree values
bool FGATCInput::close() {
- int result;
- result = ::close( lock_fd );
- if ( result == -1 ) {
- SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
- char msg[256];
- snprintf( msg, 256, "Error closing %s", lock_file );
- perror( msg );
- exit( -1 );
+#if defined( unix ) || defined( __CYGWIN__ )
+
+ if ( !is_open ) {
+ return true;
}
+ int result;
+
result = ::close( analog_in_fd );
if ( result == -1 ) {
SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
exit( -1 );
}
+#endif
+
return true;
}