1
0
Fork 0

Transponder instrument replaces KT-70.

Generic transponder can emulate KT-70 props. These emulated props
will likely die in the future, based on feedback from aircraft devs.

See (upcoming) Wiki docs on the transponder for more info.
This commit is contained in:
James Turner 2013-05-11 16:15:36 +01:00
parent 977cfb77b5
commit 06dd219a83
6 changed files with 115 additions and 372 deletions

View file

@ -17,7 +17,6 @@ set(SOURCES
inst_vertical_speed_indicator.cxx
instrument_mgr.cxx
kr_87.cxx
kt_70.cxx
mag_compass.cxx
marker_beacon.cxx
mk_viii.cxx
@ -78,7 +77,6 @@ set(HEADERS
inst_vertical_speed_indicator.hxx
instrument_mgr.hxx
kr_87.hxx
kt_70.hxx
mag_compass.hxx
marker_beacon.hxx
mk_viii.hxx

View file

@ -33,7 +33,6 @@
#include "heading_indicator_fg.hxx"
#include "heading_indicator_dg.hxx"
#include "kr_87.hxx"
#include "kt_70.hxx"
#include "mag_compass.hxx"
#include "marker_beacon.hxx"
#include "newnavradio.hxx"
@ -160,9 +159,6 @@ bool FGInstrumentMgr::build (SGPropertyNode* config_props)
} else if ( name == "KR-87" ) {
set_subsystem( id, new FGKR_87( node ) );
} else if ( name == "KT-70" ) {
set_subsystem( id, new FGKT_70( node ) );
} else if ( name == "magnetic-compass" ) {
set_subsystem( id, new MagCompass( node ) );
@ -175,7 +171,13 @@ bool FGInstrumentMgr::build (SGPropertyNode* config_props)
} else if ( name == "slip-skid-ball" ) {
set_subsystem( id, new SlipSkidBall( node ), 0.03 );
} else if ( name == "transponder" ) {
} else if (( name == "transponder" ) || ( name == "KT-70" )) {
if (name == "KT-70") {
SG_LOG(SG_INSTR, SG_WARN, "KT-70 legacy instrument compatability. "
"Please update aircraft to use transponder directly");
// force configuration into compatability mode
node->setBoolValue("kt70-compatability", true);
}
set_subsystem( id, new Transponder( node ), 0.2 );
} else if ( name == "turn-indicator" ) {

View file

@ -1,227 +0,0 @@
// kt-70.cxx -- class to impliment the King KT 70 panel-m transponder
//
// Written by Curtis Olson, started July 2002.
//
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <iostream>
#include <string>
#include <sstream>
#include <simgear/compiler.h>
#include <simgear/math/sg_random.h>
#include "kt_70.hxx"
// Constructor
FGKT_70::FGKT_70(SGPropertyNode *node) :
r_flash_time(0.0),
ident_mode(false),
ident_btn(false),
last_ident_btn(false),
digit1(1), digit2(2), digit3(0), digit4(0),
func_knob(4),
id_code(1200),
flight_level(0),
fl_ann(0),
alt_ann(0),
gnd_ann(0),
on_ann(0),
sby_ann(0),
reply_ann(0),
name("kt-70"),
num(0)
{
int i;
for ( i = 0; i < node->nChildren(); ++i ) {
SGPropertyNode *child = node->getChild(i);
string cname = child->getName();
string cval = child->getStringValue();
if ( cname == "name" ) {
name = cval;
} else if ( cname == "number" ) {
num = child->getIntValue();
} else {
SG_LOG( SG_INSTR, SG_WARN,
"Error in kt-70 config logic" );
if ( name.length() ) {
SG_LOG( SG_INSTR, SG_WARN, "Section = " << name );
}
}
}
}
// Destructor
FGKT_70::~FGKT_70() { }
void FGKT_70::init ()
{
string branch;
branch = "/instrumentation/" + name;
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
// Inputs
lon_node = fgGetNode("/position/longitude-deg", true);
lat_node = fgGetNode("/position/latitude-deg", true);
alt_node = fgGetNode("/position/altitude-ft", true);
bus_power = fgGetNode("/systems/electrical/outputs/transponder", true);
serviceable_node = (node->getChild("inputs", 0, true))
->getChild("serviceable", 0, true);
serviceable_node->setBoolValue(true);
}
void FGKT_70::bind ()
{
std::ostringstream temp;
string branch;
temp << num;
branch = "/instrumentation/" + name + "[" + temp.str() + "]";
_tiedProperties.setRoot(fgGetNode(branch, true));
// internal values
// modes
// input and buttons
_tiedProperties.Tie("inputs/ident-btn", this,
&FGKT_70::get_ident_btn, &FGKT_70::set_ident_btn);
fgSetArchivable((branch + "/inputs/rotation-deg").c_str());
_tiedProperties.Tie("inputs/digit1", this,
&FGKT_70::get_digit1, &FGKT_70::set_digit1);
fgSetArchivable((branch + "/inputs/digit1").c_str());
_tiedProperties.Tie("inputs/digit2", this,
&FGKT_70::get_digit2, &FGKT_70::set_digit2);
fgSetArchivable((branch + "/inputs/digit2").c_str());
_tiedProperties.Tie("inputs/digit3", this,
&FGKT_70::get_digit3, &FGKT_70::set_digit3);
fgSetArchivable((branch + "/inputs/digit3").c_str());
_tiedProperties.Tie("inputs/digit4", this,
&FGKT_70::get_digit4, &FGKT_70::set_digit4);
fgSetArchivable((branch + "/inputs/digit4").c_str());
_tiedProperties.Tie("inputs/func-knob", this,
&FGKT_70::get_func_knob, &FGKT_70::set_func_knob);
fgSetArchivable((branch + "/inputs/func-knob").c_str());
// outputs
_tiedProperties.Tie("outputs/id-code", this,
&FGKT_70::get_id_code, &FGKT_70::set_id_code);
fgSetArchivable((branch + "/outputs/id-code").c_str());
_tiedProperties.Tie("outputs/flight-level", this,
&FGKT_70::get_flight_level);
// annunciators
_tiedProperties.Tie("annunciators/fl", this,
&FGKT_70::get_fl_ann );
_tiedProperties.Tie("annunciators/alt", this,
&FGKT_70::get_alt_ann );
_tiedProperties.Tie("annunciators/gnd", this,
&FGKT_70::get_gnd_ann );
_tiedProperties.Tie("annunciators/on", this,
&FGKT_70::get_on_ann );
_tiedProperties.Tie("annunciators/sby", this,
&FGKT_70::get_sby_ann );
_tiedProperties.Tie("annunciators/reply", this,
&FGKT_70::get_reply_ann );
}
void FGKT_70::unbind () {
_tiedProperties.Untie();
}
// Update the various nav values based on position and valid tuned in navs
void FGKT_70::update( double dt ) {
// start with all annunciators off (reply ann is handled
// separately) and then turn on the ones we want
fl_ann = false;
alt_ann = false;
gnd_ann = false;
on_ann = false;
sby_ann = false;
reply_ann = false;
if ( has_power() && serviceable_node->getBoolValue() ) {
// sanity checks
if ( digit1 < 0 ) { digit1 = 0; }
if ( digit1 > 7 ) { digit1 = 7; }
if ( digit2 < 0 ) { digit2 = 0; }
if ( digit2 > 7 ) { digit2 = 7; }
if ( digit3 < 0 ) { digit3 = 0; }
if ( digit3 > 7 ) { digit3 = 7; }
if ( digit4 < 0 ) { digit4 = 0; }
if ( digit4 > 7 ) { digit4 = 7; }
id_code = digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4;
// flight level computation
// FIXME!!!! This needs to be computed relative to 29.92 inHg,
// but for the moment, until I figure out how to do that, I'll
// just use true altitude.
flight_level = (int)( (alt_node->getDoubleValue() + 50.0) / 100.0);
// ident button
if ( ident_btn && !last_ident_btn ) {
// ident button depressed
r_flash_time = 0.0;
ident_mode = true;
}
r_flash_time += dt;
if ( r_flash_time > 18.0 ) {
ident_mode = false;
}
if ( ident_mode ) {
reply_ann = true;
} else {
reply_ann = false;
}
if ( func_knob == 1 ) {
sby_ann = true;
} else if ( func_knob == 2 ) { // selftest
fl_ann = true;
alt_ann = true;
gnd_ann = true;
on_ann = true;
sby_ann = true;
reply_ann = true;
id_code = 8888;
flight_level = 888;
} else if ( func_knob == 3 ) {
fl_ann = true;
gnd_ann = true;
} else if ( func_knob == 4 ) {
on_ann = true;
} else if ( func_knob == 5 ) {
fl_ann = true;
alt_ann = true;
}
}
}

View file

@ -1,124 +0,0 @@
// kt-70.hxx -- class to impliment the King KT 70 panel-m transponder
//
// Written by Curtis Olson, started July 2002.
//
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifndef _FG_KT_70_HXX
#define _FG_KT_70_HXX
#include <Main/fg_props.hxx>
#include <simgear/compiler.h>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/tiedpropertylist.hxx>
#include <simgear/math/interpolater.hxx>
#include <simgear/timing/timestamp.hxx>
#include <Navaids/navlist.hxx>
#include <Sound/beacon.hxx>
#include <Sound/morse.hxx>
class FGKT_70 : public SGSubsystem
{
private:
SGPropertyNode_ptr lon_node;
SGPropertyNode_ptr lat_node;
SGPropertyNode_ptr alt_node;
SGPropertyNode_ptr bus_power;
SGPropertyNode_ptr serviceable_node;
// internal values
double r_flash_time;
// modes
bool ident_mode; // false = normal, true = ident/squawk
// input and buttons
bool ident_btn;
bool last_ident_btn;
int digit1, digit2, digit3, digit4;
int func_knob; // 0 = OFF, 1 = SBY, 2 = TST, 3 = GND, 4 = ON,
// 5 = ALT
// outputs
int id_code;
int flight_level;
// annunciators
bool fl_ann; // flight level
bool alt_ann; // altitude
bool gnd_ann; // ground
bool on_ann; // on
bool sby_ann; // standby
bool reply_ann; // reply
string name;
int num;
simgear::TiedPropertyList _tiedProperties;
public:
FGKT_70(SGPropertyNode *node);
~FGKT_70();
void init ();
void bind ();
void unbind ();
void update (double dt);
void search () { /* empty placeholder */ }
// internal values
inline bool has_power() const {
return (func_knob > 0) && (bus_power->getDoubleValue() > 1.0);
}
// input and buttons
inline bool get_ident_btn() const { return ident_btn; }
inline void set_ident_btn( bool val ) { ident_btn = val; }
inline int get_digit1() const { return digit1; }
inline void set_digit1( int val ) { digit1 = val; }
inline int get_digit2() const { return digit2; }
inline void set_digit2( int val ) { digit2 = val; }
inline int get_digit3() const { return digit3; }
inline void set_digit3( int val ) { digit3 = val; }
inline int get_digit4() const { return digit4; }
inline void set_digit4( int val ) { digit4 = val; }
inline int get_func_knob() const { return func_knob; }
inline void set_func_knob( int val ) { func_knob = val; }
// outputs
inline int get_id_code () const { return id_code; }
inline void set_id_code( int c ) { id_code = c; }
inline int get_flight_level () const { return flight_level; }
// annunciators
inline bool get_fl_ann() const { return fl_ann; }
inline bool get_alt_ann() const { return alt_ann; }
inline bool get_gnd_ann() const { return gnd_ann; }
inline bool get_on_ann() const { return on_ann; }
inline bool get_sby_ann() const { return sby_ann; }
inline bool get_reply_ann() const { return reply_ann; }
};
#endif // _FG_KT_70_HXX

View file

@ -55,6 +55,7 @@ Transponder::Transponder(SGPropertyNode *node)
{
_requiredBusVolts = node->getDoubleValue("bus-volts", 8.0);
_altitudeSourcePath = node->getStringValue("encoder-path", "/instrumentation/altimeter");
_kt70Compat = node->getBoolValue("kt70-compatability", false);
}
@ -65,10 +66,7 @@ Transponder::~Transponder()
void Transponder::init()
{
string branch;
branch = "/instrumentation/" + _name;
SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
SGPropertyNode *node = fgGetNode("/instrumentation/" + _name, _num, true );
// Inputs
_busPower_node = fgGetNode("/systems/electrical/outputs/transponder", true);
@ -80,11 +78,18 @@ void Transponder::init()
_digit_node[i]->addChangeListener(this);
}
_knob_node = in_node->getChild("knob-mode", 0, true); // 0=OFF, 1=SBY, 2=ON, 3=ALT, 4=TST
if (!_knob_node->hasValue()) {
_knob_node->setIntValue(0);
_knob_node = in_node->getChild("knob-mode", 0, true);
if (!_knob_node->hasValue()) {
_knob = KNOB_ON;
// default to, if aircraft wants to start dark, it can do this
// in its -set.xml
_knob_node->setIntValue(_knob);
} else {
_knob = static_cast<KnobPosition>(_knob_node->getIntValue());
}
_knob_node->addChangeListener(this);
_mode_node = in_node->getChild("mode", 0, true);
_mode_node->setIntValue(_mode);
_mode_node->addChangeListener(this);
@ -108,6 +113,40 @@ void Transponder::init()
_altitudeValid_node = node->getChild("altitude-valid", 0, true);
_ident_node = node->getChild("ident", 0, true);
_transmittedId_node = node->getChild("transmitted-id", 0, true);
if (_kt70Compat) {
// alias the properties through
SGPropertyNode_ptr output = node->getChild("outputs", 0, true);
output->getChild("flight-level", 0, true)->alias(_altitude_node);
output->getChild("id-code", 0, true)->alias(_idCode_node);
in_node->getChild("func-knob", 0, true)->alias(_knob_node);
}
}
void Transponder::bind()
{
if (_kt70Compat) {
SGPropertyNode *node = fgGetNode("/instrumentation/" + _name, _num, true );
_tiedProperties.setRoot(node);
_tiedProperties.Tie("annunciators/fl", this,
&Transponder::getFLAnnunciator );
_tiedProperties.Tie("annunciators/alt", this,
&Transponder::getAltAnnunciator );
_tiedProperties.Tie("annunciators/gnd", this,
&Transponder::getGroundAnnuciator );
_tiedProperties.Tie("annunciators/on", this,
&Transponder::getOnAnnunciator );
_tiedProperties.Tie("annunciators/sby", this,
&Transponder::getStandbyAnnunciator );
_tiedProperties.Tie("annunciators/reply", this,
&Transponder::getReplyAnnunciator );
} // of kt70 backwards compatability
}
void Transponder::unbind()
{
_tiedProperties.Untie();
}
@ -116,7 +155,7 @@ void Transponder::update(double dt)
if (has_power() && _serviceable_node->getBoolValue())
{
// Mode C & S send also altitude
Mode effectiveMode = (_knob_node->getIntValue() == KNOB_ALT) ? _mode : MODE_A;
Mode effectiveMode = (_knob == KNOB_ALT) ? _mode : MODE_A;
SGPropertyNode* altitudeSource = NULL;
switch (effectiveMode) {
@ -152,7 +191,11 @@ void Transponder::update(double dt)
}
}
_transmittedId_node->setIntValue(_idCode_node->getIntValue());
if (_knob > KNOB_ON) {
_transmittedId_node->setIntValue(_idCode_node->getIntValue());
} else {
_transmittedId_node->setIntValue(INVALID_ID);
}
}
else
{
@ -193,6 +236,11 @@ void Transponder::valueChanged(SGPropertyNode *prop)
return;
}
if (prop == _knob_node) {
_knob = static_cast<KnobPosition>(prop->getIntValue());
return;
}
if (_listener_active)
return;
@ -219,3 +267,34 @@ bool Transponder::has_power() const
{
return (_knob_node->getIntValue() > KNOB_STANDBY) && (_busPower_node->getDoubleValue() > _requiredBusVolts);
}
bool Transponder::getFLAnnunciator() const
{
return (_knob == KNOB_ALT) || (_knob == KNOB_GROUND) || (_knob == KNOB_TEST);
}
bool Transponder::getAltAnnunciator() const
{
return (_knob == KNOB_ALT) || (_knob == KNOB_TEST);
}
bool Transponder::getGroundAnnuciator() const
{
return (_knob == KNOB_GROUND) || (_knob == KNOB_TEST);
}
bool Transponder::getOnAnnunciator() const
{
return (_knob == KNOB_ON) || (_knob == KNOB_TEST);
}
bool Transponder::getStandbyAnnunciator() const
{
return (_knob == KNOB_STANDBY) || (_knob == KNOB_TEST);
}
bool Transponder::getReplyAnnunciator() const
{
return _identMode || (_knob == KNOB_TEST);
}

View file

@ -29,7 +29,7 @@
#include <Main/fg_props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/tiedpropertylist.hxx>
class Transponder : public SGSubsystem, public SGPropertyChangeListener
{
@ -39,7 +39,9 @@ public:
virtual void init ();
virtual void update (double dt);
virtual void bind();
virtual void unbind();
private:
enum Mode
{
@ -52,11 +54,21 @@ private:
{
KNOB_OFF = 0,
KNOB_STANDBY,
KNOB_TEST,
KNOB_GROUND,
KNOB_ON,
KNOB_ALT,
KNOB_TEST
KNOB_ALT
};
// annunciators, for KT-70 compatability only
// these should be replaced with conditionals in the instrument
bool getFLAnnunciator() const;
bool getAltAnnunciator() const;
bool getGroundAnnuciator() const;
bool getOnAnnunciator() const;
bool getStandbyAnnunciator() const;
bool getReplyAnnunciator() const;
// Inputs
SGPropertyNode_ptr _pressureAltitude_node;
SGPropertyNode_ptr _busPower_node;
@ -67,10 +79,12 @@ private:
SGPropertyNode_ptr _idCode_node;
SGPropertyNode_ptr _digit_node[4];
simgear::TiedPropertyList _tiedProperties;
SGPropertyNode_ptr _identBtn_node;
bool _identMode;
bool _kt70Compat;
// Outputs
SGPropertyNode_ptr _altitude_node;
SGPropertyNode_ptr _altitudeValid_node;
@ -81,6 +95,7 @@ private:
std::string _name;
int _num;
Mode _mode;
KnobPosition _knob;
double _identTime;
int _listener_active;
double _requiredBusVolts;