1
0
Fork 0

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:
Torsten Dreyer 2010-06-01 22:08:42 +02:00
parent 54c964aed5
commit 253b14a1cb
2 changed files with 54 additions and 111 deletions

View file

@ -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 );

View file

@ -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;
}; };
/** /**