#include <simgear/io/iochannel.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/misc/props.hxx>
+#include <simgear/misc/sg_path.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
}
+void FGATC610x::init_config() {
+#if defined( unix ) || defined( __CYGWIN__ )
+ // Next check home directory for .fgfsrc.hostname file
+ char *envp = ::getenv( "HOME" );
+ if ( envp != NULL ) {
+ SGPath atc610x_config( envp );
+ atc610x_config.append( ".fgfs-atc610x.xml" );
+ readProperties( atc610x_config.str(), globals->get_props() );
+ }
+#endif
+}
+
+
// Open and initialize ATC 610x hardware
bool FGATC610x::open() {
if ( is_enabled() ) {
return false;
}
+ // This loads the config parameters generated by "simcal"
+ init_config();
+
SG_LOG( SG_IO, SG_ALERT,
"Initializing ATC 610x hardware, please wait ..." );
nav2_stby_freq
= fgGetNode( "/radios/nav[1]/frequencies/standby-mhz", true );
- adf_on_off_vol = fgGetNode( "/radios/kr-87/inputs/on-off-volume", true );
+ adf_power = fgGetNode( "/radios/kr-87/inputs/power-btn", true );
+ adf_vol = fgGetNode( "/radios/kr-87/inputs/volume", true );
adf_adf_btn = fgGetNode( "/radios/kr-87/inputs/adf-btn", true );
adf_bfo_btn = fgGetNode( "/radios/kr-87/inputs/bfo-btn", true );
adf_freq = fgGetNode( "/radios/kr-87/outputs/selected-khz", true );
xpdr_sby_ann = fgGetNode( "/radios/kt-70/annunciators/sby", true );
xpdr_reply_ann = fgGetNode( "/radios/kt-70/annunciators/reply", true );
+ elevator_center = fgGetNode( "/input/atc610x/elevator/center", 0 );
+ elevator_min = fgGetNode( "/input/atc610x/elevator/min", 0 );
+ elevator_max = fgGetNode( "/input/atc610x/elevator/max", 0 );
+
+ ailerons_center = fgGetNode( "/input/atc610x/ailerons/center", 0 );
+ ailerons_min = fgGetNode( "/input/atc610x/ailerons/min", 0 );
+ ailerons_max = fgGetNode( "/input/atc610x/ailerons/max", 0 );
+
+ rudder_center = fgGetNode( "/input/atc610x/rudder/center", 0 );
+ rudder_min = fgGetNode( "/input/atc610x/rudder/min", 0 );
+ rudder_max = fgGetNode( "/input/atc610x/rudder/max", 0 );
+
+ throttle_min = fgGetNode( "/input/atc610x/throttle/min", 0 );
+ throttle_max = fgGetNode( "/input/atc610x/throttle/max", 0 );
+
+ mixture_min = fgGetNode( "/input/atc610x/mixture/min", 0 );
+ mixture_max = fgGetNode( "/input/atc610x/mixture/max", 0 );
+
+ trim_center = fgGetNode( "/input/atc610x/trim/center", 0 );
+ trim_min = fgGetNode( "/input/atc610x/trim/min", 0 );
+ trim_max = fgGetNode( "/input/atc610x/trim/max", 0 );
+
+ nav1vol_min = fgGetNode( "/input/atc610x/nav1vol/min", 0 );
+ nav1vol_max = fgGetNode( "/input/atc610x/nav1vol/max", 0 );
+
+ nav2vol_min = fgGetNode( "/input/atc610x/nav2vol/min", 0 );
+ nav2vol_max = fgGetNode( "/input/atc610x/nav2vol/max", 0 );
+
return true;
}
#define ATC_AILERON_CENTER 535
#define ATC_ELEVATOR_TRIM_CENTER 512
#define ATC_ELEVATOR_CENTER 543
+#define ATC_RUDDER_CENTER 519
+
+// 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 ) {
+ // cout << center << " " << min << " " << max << " " << value << " ";
+ double result;
+ double range;
+
+ if ( value <= center ) {
+ range = center - min;
+ result = (value - center) / range;
+ } else {
+ range = max - center;
+ result = (value - center) / range;
+ }
+
+ if ( result < -1.0 ) result = -1.0;
+ if ( result > 1.0 ) result = 1.0;
+
+ // cout << result << endl;
+
+ return result;
+}
+
+
+// scale a number between min and max to a scale from 0.0 to 1.0
+static double scale( int min, int max, int value ) {
+ // cout << center << " " << min << " " << max << " " << value << " ";
+ double result;
+ double range;
+
+ range = max - min;
+ result = (value - min) / range;
+
+ if ( result < 0.0 ) result = 0.0;
+ if ( result > 1.0 ) result = 1.0;
+
+ // cout << result << endl;
+
+ return result;
+}
+
bool FGATC610x::do_analog_in() {
// Read raw data in byte form
float tmp, tmp1, tmp2;
// aileron
- tmp = (float)(analog_in_data[0] - ATC_AILERON_CENTER) / 256.0f;
+ tmp = scale( ailerons_center->getIntValue(), ailerons_min->getIntValue(),
+ ailerons_max->getIntValue(), analog_in_data[0] );
fgSetFloat( "/controls/aileron", tmp );
// cout << "aileron = " << analog_in_data[0] << " = " << tmp;
// elevator
- tmp = (float)(analog_in_data[4] - ATC_ELEVATOR_TRIM_CENTER) / 512.0f;
- fgSetFloat( "/controls/elevator-trim", tmp );
+ tmp = -scale( elevator_center->getIntValue(), elevator_min->getIntValue(),
+ elevator_max->getIntValue(), analog_in_data[5] );
+ fgSetFloat( "/controls/elevator", tmp );
// cout << "trim = " << analog_in_data[4] << " = " << tmp;
- // trim
- tmp = (float)(ATC_ELEVATOR_CENTER - analog_in_data[5]) / 100.0f;
- fgSetFloat( "/controls/elevator", tmp );
+ // elevator trim
+ tmp = scale( trim_center->getIntValue(), trim_min->getIntValue(),
+ trim_max->getIntValue(), analog_in_data[4] );
+ fgSetFloat( "/controls/elevator-trim", tmp );
// cout << " elev = " << analog_in_data[5] << " = " << tmp << endl;
// mixture
- tmp = (float)analog_in_data[7] / 680.0f;
+ tmp = scale( mixture_min->getIntValue(), mixture_max->getIntValue(),
+ analog_in_data[7] );
fgSetFloat( "/controls/mixture[0]", tmp );
+ fgSetFloat( "/controls/mixture[1]", tmp );
// throttle
- tmp = (float)analog_in_data[8] / 690.0f;
+ tmp = scale( mixture_min->getIntValue(), mixture_max->getIntValue(),
+ analog_in_data[8] );
fgSetFloat( "/controls/throttle[0]", tmp );
+ fgSetFloat( "/controls/throttle[1]", tmp );
+
+#if 0
+ // rudder
+ tmp = scale( rudder_center->getIntValue(), rudder_min->getIntValue(),
+ rudder_max->getIntValue(), analog_in_data[10] );
+ fgSetFloat( "/controls/rudder", tmp );
+#endif
// nav1 volume
tmp = (float)analog_in_data[25] / 1024.0f;
// adf volume
tmp = (float)analog_in_data[26] / 1024.0f;
- fgSetFloat( "/radios/kr-87/inputs/on-off-volume", tmp );
+ fgSetFloat( "/radios/kr-87/inputs/volume", tmp );
// nav2 obs tuner
tmp = (float)analog_in_data[29] * 360.0f / 1024.0f;
fgSetInt( "/radios/dme/switch-position", 3 );
}
+ // Com1 Power
+ fgSetBool( "/radios/comm[0]/inputs/power-btn",
+ radio_switch_data[7] & 0x01 );
+
// Com1 Swap
int com1_swap = !((radio_switch_data[7] >> 1) & 0x01);
static int last_com1_swap;
}
last_com1_swap = com1_swap;
+ // Com2 Power
+ fgSetBool( "/radios/comm[1]/inputs/power-btn",
+ radio_switch_data[15] & 0x01 );
+
// Com2 Swap
int com2_swap = !((radio_switch_data[15] >> 1) & 0x01);
static int last_com2_swap;
static int last_adf_tuner_fine = adf_tuner_fine;
static int last_adf_tuner_coarse = adf_tuner_coarse;
+ // cout << "adf_stby_mode = " << adf_stby_mode->getIntValue() << endl;
if ( adf_count_mode->getIntValue() == 2 ) {
// tune count down timer
value = adf_elapsed_timer->getDoubleValue();
fgSetInt( "/radios/kr-87/inputs/bfo-btn",
!(radio_switch_data[23] >> 1 & 0x01) );
fgSetInt( "/radios/kr-87/inputs/frq-btn",
- !(radio_switch_data[23] >> 2 & 0x01) );
+ (radio_switch_data[23] >> 2 & 0x01) );
fgSetInt( "/radios/kr-87/inputs/flt-et-btn",
- !(radio_switch_data[23] >> 3 & 0x01) );
+ !(radio_switch_data[23] >> 3 & 0x01) );
fgSetInt( "/radios/kr-87/inputs/set-rst-btn",
!(radio_switch_data[23] >> 4 & 0x01) );
+ fgSetInt( "/radios/kr-87/inputs/power-btn",
+ radio_switch_data[23] >> 5 & 0x01 );
/* cout << "adf = " << !(radio_switch_data[23] & 0x01)
<< " bfo = " << !(radio_switch_data[23] >> 1 & 0x01)
<< " stby = " << !(radio_switch_data[23] >> 2 & 0x01)
if ( minutes > 999 ) {
minutes = 999.0;
}
- sprintf(digits, "%03.0f", minutes);
+ snprintf(digits, 7, "%03.0f", minutes);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( knots > 999 ) {
knots = 999.0;
}
- sprintf(digits, "%03.0f", knots);
+ snprintf(digits, 7, "%03.0f", knots);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( nm > 99 ) {
nm = 99.0;
}
- sprintf(digits, "%04.1f", nm);
+ snprintf(digits, 7, "%04.1f", nm);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(com1_stby) > 999.99 ) {
com1_stby = 0.0;
}
- sprintf(digits, "%06.3f", com1_stby);
+ snprintf(digits, 7, "%06.3f", com1_stby);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(com1) > 999.99 ) {
com1 = 0.0;
}
- sprintf(digits, "%06.3f", com1);
+ snprintf(digits, 7, "%06.3f", com1);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(com2_stby) > 999.99 ) {
com2_stby = 0.0;
}
- sprintf(digits, "%06.3f", com2_stby);
+ snprintf(digits, 7, "%06.3f", com2_stby);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(com2) > 999.99 ) {
com2 = 0.0;
}
- sprintf(digits, "%06.3f", com2);
+ snprintf(digits, 7, "%06.3f", com2);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(nav1_stby) > 999.99 ) {
nav1_stby = 0.0;
}
- sprintf(digits, "%06.2f", nav1_stby);
+ snprintf(digits, 7, "%06.2f", nav1_stby);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(nav1) > 999.99 ) {
nav1 = 0.0;
}
- sprintf(digits, "%06.2f", nav1);
+ snprintf(digits, 7, "%06.2f", nav1);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(nav2_stby) > 999.99 ) {
nav2_stby = 0.0;
}
- sprintf(digits, "%06.2f", nav2_stby);
+ snprintf(digits, 7, "%06.2f", nav2_stby);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(nav2) > 999.99 ) {
nav2 = 0.0;
}
- sprintf(digits, "%06.2f", nav2);
+ snprintf(digits, 7, "%06.2f", nav2);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
// turns on the decimal point
// ADF standby frequency / timer
- if ( adf_on_off_vol->getDoubleValue() >= 0.01 ) {
+ if ( adf_power->getBoolValue() ) {
if ( adf_stby_mode->getIntValue() == 0 ) {
// frequency
float adf_stby = adf_stby_freq->getFloatValue();
if ( fabs(adf_stby) > 1799 ) {
adf_stby = 1799;
}
- sprintf(digits, "%04.0f", adf_stby);
+ snprintf(digits, 7, "%04.0f", adf_stby);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
big = 99;
}
// cout << big << ":" << little << endl;
- sprintf(digits, "%02d%02d", big, little);
+ snprintf(digits, 7, "%02d%02d", big, little);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
if ( fabs(adf) > 1799 ) {
adf = 1799;
}
- sprintf(digits, "%04.0f", adf);
+ snprintf(digits, 7, "%04.0f", adf);
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
xpdr_func_knob->getIntValue() == 5 )
{
// do flight level display
- sprintf(digits, "%03d", xpdr_flight_level->getIntValue() );
+ snprintf(digits, 7, "%03d", xpdr_flight_level->getIntValue() );
for ( i = 0; i < 6; ++i ) {
digits[i] -= '0';
}
starter = false;
}
- // flaps
- float flaps = 0.0;
- if ( switch_matrix[board][6][3] == 1 ) {
- flaps = 1.0;
- } else if ( switch_matrix[board][5][3] == 1 ) {
- flaps = 2.0 / 3.0;
- } else if ( switch_matrix[board][4][3] == 1 ) {
- flaps = 1.0 / 3.0;
- } else if ( switch_matrix[board][4][3] == 0 ) {
- flaps = 0.0;
- }
-
// do a bit of filtering on the magneto/starter switch and the
// flap lever because these are not well debounced in hardware
static int mag1, mag2, mag3;
if ( mag1 == mag2 && mag2 == mag3 ) {
fgSetInt( "/controls/magnetos[0]", magnetos );
}
-
static bool start1, start2, start3;
start3 = start2;
start2 = start1;
fgSetBool( "/controls/starter[0]", starter );
}
+ // flaps
+ float flaps = 0.0;
+ if ( switch_matrix[board][6][3] ) {
+ flaps = 1.0;
+ } else if ( switch_matrix[board][5][3] ) {
+ flaps = 2.0 / 3.0;
+ } else if ( switch_matrix[board][4][3] ) {
+ flaps = 1.0 / 3.0;
+ } else if ( !switch_matrix[board][4][3] ) {
+ flaps = 0.0;
+ }
+
+ // do a bit of filtering on the magneto/starter switch and the
+ // flap lever because these are not well debounced in hardware
static float flap1, flap2, flap3;
flap3 = flap2;
flap2 = flap1;
fgSetFloat( "/controls/flaps", flaps );
}
+ // fuel selector (also filtered)
+ int fuel = 0;
+ if ( switch_matrix[board][2][3] ) {
+ // both
+ fuel = 3;
+ } else if ( switch_matrix[board][1][3] ) {
+ // left
+ fuel = 1;
+ } else if ( switch_matrix[board][3][3] ) {
+ // right
+ fuel = 2;
+ } else {
+ // fuel cutoff
+ fuel = 0;
+ }
+
+ static int fuel1, fuel2, fuel3;
+ fuel3 = fuel2;
+ fuel2 = fuel1;
+ fuel1 = fuel;
+ if ( fuel1 == fuel2 && fuel2 == fuel3 ) {
+ fgSetBool( "/controls/fuel-selector[0]", (fuel & 0x01) > 0 );
+ fgSetBool( "/controls/fuel-selector[1]", (fuel & 0x02) > 0 );
+ }
+
return true;
}