Code cleanup, inherit JK, D and T from RS and a bugfix for the logic element
- reuse code - undeclared inputs default to false where applicable - remove unused tInput - JK, D and T FF now inherit from RS with dominant R input, so they all have a R and a S input to preset the output - fix the nonfunctional <inverted> element of the logic element
This commit is contained in:
parent
54c964aed5
commit
253b14a1cb
2 changed files with 54 additions and 111 deletions
|
@ -910,87 +910,59 @@ void FGXMLAutoLogic::update(double dt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool i = input->test();
|
bool q = input->test();
|
||||||
|
if( inverted ) q = !q;
|
||||||
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ": " << (inverted ? !i : i) << endl;
|
if ( debug ) cout << "Updating " << get_name() << ": " << q << endl;
|
||||||
|
|
||||||
set_output_value( i );
|
set_output_value( q );
|
||||||
}
|
}
|
||||||
|
|
||||||
class FGXMLAutoRSFlipFlop : public FGXMLAutoFlipFlop {
|
class FGXMLAutoRSFlipFlop : public FGXMLAutoFlipFlop {
|
||||||
private:
|
private:
|
||||||
bool _rs;
|
bool _rIsDominant;
|
||||||
public:
|
public:
|
||||||
FGXMLAutoRSFlipFlop( SGPropertyNode * node ) :
|
FGXMLAutoRSFlipFlop( SGPropertyNode * node, bool rIsDominant = true ) :
|
||||||
FGXMLAutoFlipFlop( node ) {
|
FGXMLAutoFlipFlop( node ) {}
|
||||||
// type exists here, otherwise we were not constructed
|
|
||||||
string val = node->getNode( "type" )->getStringValue();
|
|
||||||
_rs = (val == "RS");
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateState( double dt ) {
|
bool getState( bool & q ) {
|
||||||
|
|
||||||
if( sInput == NULL ) {
|
bool s = sInput ? sInput->test() : false;
|
||||||
if ( debug ) cout << "No set (S) input for " << get_name() << endl;
|
bool r = rInput ? rInput->test() : false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rInput == NULL ) {
|
|
||||||
if ( debug ) cout << "No reset (R) input for " << get_name() << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool s = sInput->test();
|
|
||||||
bool r = rInput->test();
|
|
||||||
|
|
||||||
// s == false && q == false: no change, keep state
|
// s == false && q == false: no change, keep state
|
||||||
if( s || r ) {
|
if( s || r ) {
|
||||||
bool q = false;
|
if( _rIsDominant ) { // RS: reset is dominant
|
||||||
if( _rs ) { // RS: reset is dominant
|
|
||||||
if( s ) q = true; // set
|
if( s ) q = true; // set
|
||||||
if( r ) q = false; // reset
|
if( r ) q = false; // reset
|
||||||
} else { // SR: set is dominant
|
} else { // SR: set is dominant
|
||||||
if( r ) q = false; // reset
|
if( r ) q = false; // reset
|
||||||
if( s ) q = true; // set
|
if( s ) q = true; // set
|
||||||
}
|
}
|
||||||
if( inverted ) q = !q;
|
return true; // signal state changed
|
||||||
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " s=" << s
|
|
||||||
<< ",r=" << r
|
|
||||||
<< ",q=" << q << endl;
|
|
||||||
set_output_value( q );
|
|
||||||
} else {
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " s=" << s
|
|
||||||
<< ",r=" << r
|
|
||||||
<< ",q=unchanged" << endl;
|
|
||||||
}
|
}
|
||||||
|
return false; // signal state unchagned
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGXMLAutoJKFlipFlop : public FGXMLAutoFlipFlop {
|
/*
|
||||||
|
JK flip-flop with set and reset input
|
||||||
|
*/
|
||||||
|
class FGXMLAutoJKFlipFlop : public FGXMLAutoRSFlipFlop {
|
||||||
private:
|
private:
|
||||||
bool clock;
|
bool clock;
|
||||||
public:
|
public:
|
||||||
FGXMLAutoJKFlipFlop( SGPropertyNode * node ) :
|
FGXMLAutoJKFlipFlop( SGPropertyNode * node ) :
|
||||||
FGXMLAutoFlipFlop( node ),
|
FGXMLAutoRSFlipFlop( node ),
|
||||||
clock(false) {}
|
clock(false) {}
|
||||||
|
|
||||||
void updateState( double dt ) {
|
bool getState( bool & q ) {
|
||||||
|
|
||||||
if( jInput == NULL ) {
|
if( FGXMLAutoRSFlipFlop::getState(q ) )
|
||||||
if ( debug ) cout << "No set (j) input for " << get_name() << endl;
|
return true;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( kInput == NULL ) {
|
bool j = jInput ? jInput->test() : false;
|
||||||
if ( debug ) cout << "No reset (k) input for " << get_name() << endl;
|
bool k = kInput ? kInput->test() : false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool j = jInput->test();
|
|
||||||
bool k = kInput->test();
|
|
||||||
/*
|
/*
|
||||||
if the user provided a clock input, use it.
|
if the user provided a clock input, use it.
|
||||||
Otherwise use framerate as clock
|
Otherwise use framerate as clock
|
||||||
|
@ -1000,9 +972,8 @@ public:
|
||||||
bool raisingEdge = clockInput ? (c && !clock) : true;
|
bool raisingEdge = clockInput ? (c && !clock) : true;
|
||||||
clock = c;
|
clock = c;
|
||||||
|
|
||||||
if( !raisingEdge ) return;
|
if( !raisingEdge ) return false; //signal no change
|
||||||
|
|
||||||
bool q = get_bool_output_value();
|
|
||||||
// j == false && k == false: no change, keep state
|
// j == false && k == false: no change, keep state
|
||||||
if( (j || k) ) {
|
if( (j || k) ) {
|
||||||
if( j && k ) {
|
if( j && k ) {
|
||||||
|
@ -1011,78 +982,56 @@ public:
|
||||||
if( j ) q = true; // set
|
if( j ) q = true; // set
|
||||||
if( k ) q = false; // reset
|
if( k ) q = false; // reset
|
||||||
}
|
}
|
||||||
if( inverted ) q = !q;
|
|
||||||
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " j=" << j
|
|
||||||
<< ",k=" << k
|
|
||||||
<< ",q=" << q << endl;
|
|
||||||
set_output_value( q );
|
|
||||||
} else {
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " j=" << j
|
|
||||||
<< ",k=" << k
|
|
||||||
<< ",q=unchanged" << endl;
|
|
||||||
}
|
}
|
||||||
|
return true; // signal state changed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGXMLAutoDFlipFlop : public FGXMLAutoFlipFlop {
|
class FGXMLAutoDFlipFlop : public FGXMLAutoRSFlipFlop {
|
||||||
private:
|
private:
|
||||||
bool clock;
|
bool clock;
|
||||||
public:
|
public:
|
||||||
FGXMLAutoDFlipFlop( SGPropertyNode * node ) :
|
FGXMLAutoDFlipFlop( SGPropertyNode * node ) :
|
||||||
FGXMLAutoFlipFlop( node ),
|
FGXMLAutoRSFlipFlop( node ),
|
||||||
clock(false) {}
|
clock(false) {}
|
||||||
|
|
||||||
void updateState( double dt ) {
|
bool getState( bool & q ) {
|
||||||
|
|
||||||
|
if( FGXMLAutoRSFlipFlop::getState(q ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
if( clockInput == NULL ) {
|
if( clockInput == NULL ) {
|
||||||
if ( debug ) cout << "No (clock) input for " << get_name() << endl;
|
if ( debug ) cout << "No (clock) input for " << get_name() << endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dInput == NULL ) {
|
|
||||||
if ( debug ) cout << "No (D) input for " << get_name() << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool d = dInput->test();
|
|
||||||
|
|
||||||
// check the clock - raising edge
|
// check the clock - raising edge
|
||||||
bool c = clockInput->test();
|
bool c = clockInput->test();
|
||||||
bool raisingEdge = c && !clock;
|
bool raisingEdge = c && !clock;
|
||||||
clock = c;
|
clock = c;
|
||||||
|
|
||||||
if( raisingEdge ) {
|
if( !raisingEdge ) return false; // signal state unchanged
|
||||||
bool q = d;
|
q = dInput ? dInput->test() : false;
|
||||||
if( inverted ) q = !q;
|
return true;
|
||||||
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " d=" << d
|
|
||||||
<< ",q=" << q << endl;
|
|
||||||
set_output_value( q );
|
|
||||||
} else {
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< " d=" << d
|
|
||||||
<< ",q=unchanged" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGXMLAutoTFlipFlop : public FGXMLAutoFlipFlop {
|
class FGXMLAutoTFlipFlop : public FGXMLAutoRSFlipFlop {
|
||||||
private:
|
private:
|
||||||
bool clock;
|
bool clock;
|
||||||
public:
|
public:
|
||||||
FGXMLAutoTFlipFlop( SGPropertyNode * node ) :
|
FGXMLAutoTFlipFlop( SGPropertyNode * node ) :
|
||||||
FGXMLAutoFlipFlop( node ),
|
FGXMLAutoRSFlipFlop( node ),
|
||||||
clock(false) {}
|
clock(false) {}
|
||||||
|
|
||||||
void updateState( double dt ) {
|
bool getState( bool & q ) {
|
||||||
|
|
||||||
|
if( FGXMLAutoRSFlipFlop::getState(q ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
if( clockInput == NULL ) {
|
if( clockInput == NULL ) {
|
||||||
if ( debug ) cout << "No (clock) input for " << get_name() << endl;
|
if ( debug ) cout << "No (clock) input for " << get_name() << endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the clock - raising edge
|
// check the clock - raising edge
|
||||||
|
@ -1090,17 +1039,9 @@ public:
|
||||||
bool raisingEdge = c && !clock;
|
bool raisingEdge = c && !clock;
|
||||||
clock = c;
|
clock = c;
|
||||||
|
|
||||||
if( raisingEdge ) {
|
if( !raisingEdge ) return false; // signal state unchanged;
|
||||||
bool q = !get_bool_output_value(); // toggle
|
q = !q; // toggle
|
||||||
if( inverted ) q = !q; // doesnt really make sense for a T-FF
|
return true;
|
||||||
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< ",q=" << q << endl;
|
|
||||||
set_output_value( q );
|
|
||||||
} else {
|
|
||||||
if ( debug ) cout << "Updating " << get_name() << ":"
|
|
||||||
<< ",q=unchanged" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1121,8 +1062,6 @@ bool FGXMLAutoFlipFlop::parseNodeHook(const std::string& aName, SGPropertyNode*
|
||||||
jInput = sgReadCondition( fgGetNode("/"), aNode );
|
jInput = sgReadCondition( fgGetNode("/"), aNode );
|
||||||
} else if (aName == "K") {
|
} else if (aName == "K") {
|
||||||
kInput = sgReadCondition( fgGetNode("/"), aNode );
|
kInput = sgReadCondition( fgGetNode("/"), aNode );
|
||||||
} else if (aName == "T") {
|
|
||||||
tInput = sgReadCondition( fgGetNode("/"), aNode );
|
|
||||||
} else if (aName == "D") {
|
} else if (aName == "D") {
|
||||||
dInput = sgReadCondition( fgGetNode("/"), aNode );
|
dInput = sgReadCondition( fgGetNode("/"), aNode );
|
||||||
} else if (aName == "clock") {
|
} else if (aName == "clock") {
|
||||||
|
@ -1140,11 +1079,13 @@ bool FGXMLAutoFlipFlop::parseNodeHook(const std::string& aName, SGPropertyNode*
|
||||||
|
|
||||||
void FGXMLAutoFlipFlop::update(double dt)
|
void FGXMLAutoFlipFlop::update(double dt)
|
||||||
{
|
{
|
||||||
|
bool q = get_bool_output_value();
|
||||||
|
|
||||||
if ( isPropertyEnabled() ) {
|
if ( isPropertyEnabled() ) {
|
||||||
if ( !enabled ) {
|
if ( !enabled ) {
|
||||||
// we have just been enabled
|
// we have just been enabled
|
||||||
// initialize to a bool property
|
// initialize to a bool property
|
||||||
set_output_value( get_bool_output_value() );
|
set_output_value( q );
|
||||||
}
|
}
|
||||||
enabled = true;
|
enabled = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1155,7 +1096,9 @@ void FGXMLAutoFlipFlop::update(double dt)
|
||||||
if ( !enabled || dt < SGLimitsd::min() )
|
if ( !enabled || dt < SGLimitsd::min() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
updateState( dt );
|
if( getState( q ) ) {
|
||||||
|
set_output_value( inverted ? !q : q );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1384,7 +1327,8 @@ bool FGXMLAutopilot::build( SGPropertyNode_ptr config_props ) {
|
||||||
string val;
|
string val;
|
||||||
if( typeNode != NULL ) val = typeNode->getStringValue();
|
if( typeNode != NULL ) val = typeNode->getStringValue();
|
||||||
val = simgear::strutils::strip(val);
|
val = simgear::strutils::strip(val);
|
||||||
if( val == "RS" || val =="SR" ) flipFlop = new FGXMLAutoRSFlipFlop( node );
|
if( val == "RS" ) flipFlop = new FGXMLAutoRSFlipFlop( node );
|
||||||
|
else if( val == "SR" ) flipFlop = new FGXMLAutoRSFlipFlop( node, false );
|
||||||
else if( val == "JK" ) flipFlop = new FGXMLAutoJKFlipFlop( node );
|
else if( val == "JK" ) flipFlop = new FGXMLAutoJKFlipFlop( node );
|
||||||
else if( val == "T" ) flipFlop = new FGXMLAutoTFlipFlop( node );
|
else if( val == "T" ) flipFlop = new FGXMLAutoTFlipFlop( node );
|
||||||
else if( val == "D" ) flipFlop = new FGXMLAutoDFlipFlop( node );
|
else if( val == "D" ) flipFlop = new FGXMLAutoDFlipFlop( node );
|
||||||
|
|
|
@ -430,17 +430,16 @@ protected:
|
||||||
SGSharedPtr<SGCondition> clockInput;
|
SGSharedPtr<SGCondition> clockInput;
|
||||||
SGSharedPtr<SGCondition> jInput;
|
SGSharedPtr<SGCondition> jInput;
|
||||||
SGSharedPtr<SGCondition> kInput;
|
SGSharedPtr<SGCondition> kInput;
|
||||||
SGSharedPtr<SGCondition> tInput;
|
|
||||||
SGSharedPtr<SGCondition> dInput;
|
SGSharedPtr<SGCondition> dInput;
|
||||||
bool inverted;
|
bool inverted;
|
||||||
FGXMLAutoFlipFlop( SGPropertyNode * node );
|
FGXMLAutoFlipFlop( SGPropertyNode * node );
|
||||||
bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
|
bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
|
||||||
|
|
||||||
void update( double dt );
|
void update( double dt );
|
||||||
virtual void updateState( double dt ) = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~FGXMLAutoFlipFlop() {};
|
~FGXMLAutoFlipFlop() {};
|
||||||
|
virtual bool getState( bool & result ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue