1 // flipflop.hxx - implementation of multiple flip flop types
3 // Written by Torsten Dreyer
5 // Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "flipflop.hxx"
23 #include "functor.hxx"
24 #include "inputvalue.hxx"
25 #include <Main/fg_props.hxx>
27 using namespace FGXMLAutopilot;
29 class RSFlipFlopImplementation : public FlipFlopImplementation {
33 RSFlipFlopImplementation( bool rIsDominant = true ) : _rIsDominant( rIsDominant ) {}
34 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
37 class SRFlipFlopImplementation : public RSFlipFlopImplementation {
39 SRFlipFlopImplementation() : RSFlipFlopImplementation( false ) {}
42 class ClockedFlipFlopImplementation : public RSFlipFlopImplementation {
45 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) = 0;
47 ClockedFlipFlopImplementation( bool rIsDominant = true ) : RSFlipFlopImplementation( rIsDominant ), _clock(false) {}
48 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
51 class JKFlipFlopImplementation : public ClockedFlipFlopImplementation {
53 JKFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
54 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q );
57 class DFlipFlopImplementation : public ClockedFlipFlopImplementation {
59 DFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
60 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
61 q = input.get_value("D");
66 class TFlipFlopImplementation : public ClockedFlipFlopImplementation {
68 TFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
69 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
75 class MonoFlopImplementation : public JKFlipFlopImplementation {
77 virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode );
81 MonoFlopImplementation( bool rIsDominant = true ) : JKFlipFlopImplementation( rIsDominant ) {}
82 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
85 bool MonoFlopImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode )
87 if( JKFlipFlopImplementation::configure( nodeName, configNode ) )
90 if (nodeName == "time") {
91 _time.push_back( new InputValue( configNode ) );
98 bool MonoFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
100 if( JKFlipFlopImplementation::getState( dt, input, q ) ) {
101 _t = q ? _time.get_value() : 0;
115 bool RSFlipFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
117 bool s = input.get_value("S");
118 bool r = input.get_value("R");
120 // s == false && q == false: no change, keep state
122 if( _rIsDominant ) { // RS: reset is dominant
123 if( s ) q = true; // set
124 if( r ) q = false; // reset
125 } else { // SR: set is dominant
126 if( r ) q = false; // reset
127 if( s ) q = true; // set
129 return true; // signal state changed
131 return false; // signal state unchagned
134 bool ClockedFlipFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
136 if( RSFlipFlopImplementation::getState( dt, input, q ) )
139 bool c = input.get_value("clock");
140 bool raisingEdge = c && !_clock;
144 if( !raisingEdge ) return false; //signal no change
145 return onRaisingEdge( input, q );
148 bool JKFlipFlopImplementation::onRaisingEdge( DigitalComponent::InputMap input, bool & q )
150 bool j = input.get_value("J");
151 bool k = input.get_value("K");
153 // j == false && k == false: no change, keep state
158 if( j ) q = true; // set
159 if( k ) q = false; // reset
161 return true; // signal state changed
164 return false; // signal no change
167 bool FlipFlopImplementation::configure( SGPropertyNode_ptr configNode )
169 for (int i = 0; i < configNode->nChildren(); ++i ) {
170 SGPropertyNode_ptr prop;
172 SGPropertyNode_ptr child = configNode->getChild(i);
173 string cname(child->getName());
175 if( configure( cname, child ) )
178 } // for configNode->nChildren()
184 static map<string,FunctorBase<FlipFlopImplementation> *> componentForge;
186 bool FlipFlop::configure( const std::string & nodeName, SGPropertyNode_ptr configNode )
188 if( componentForge.empty() ) {
189 componentForge["RS"] = new CreateAndConfigureFunctor<RSFlipFlopImplementation,FlipFlopImplementation>();
190 componentForge["SR"] = new CreateAndConfigureFunctor<SRFlipFlopImplementation,FlipFlopImplementation>();
191 componentForge["JK"] = new CreateAndConfigureFunctor<JKFlipFlopImplementation,FlipFlopImplementation>();
192 componentForge["D"] = new CreateAndConfigureFunctor<DFlipFlopImplementation, FlipFlopImplementation>();
193 componentForge["T"] = new CreateAndConfigureFunctor<TFlipFlopImplementation, FlipFlopImplementation>();
194 componentForge["monostable"] = new CreateAndConfigureFunctor<MonoFlopImplementation, FlipFlopImplementation>();
197 if( DigitalComponent::configure( nodeName, configNode ) )
200 if( nodeName == "type" ) {
201 string type(configNode->getStringValue());
202 if( componentForge.count(type) == 0 ) {
203 SG_LOG( SG_AUTOPILOT, SG_BULK, "unhandled flip-flop type <" << type << ">" << endl );
206 _implementation = (*componentForge[type])( configNode->getParent() );
210 if (nodeName == "set"||nodeName == "S") {
211 _input["S"] = sgReadCondition( fgGetNode("/"), configNode );
215 if (nodeName == "reset" || nodeName == "R" ) {
216 _input["R"] = sgReadCondition( fgGetNode("/"), configNode );
220 if (nodeName == "J") {
221 _input["J"] = sgReadCondition( fgGetNode("/"), configNode );
225 if (nodeName == "K") {
226 _input["K"] = sgReadCondition( fgGetNode("/"), configNode );
230 if (nodeName == "D") {
231 _input["D"] = sgReadCondition( fgGetNode("/"), configNode );
235 if (nodeName == "clock") {
236 _input["clock"] = sgReadCondition( fgGetNode("/"), configNode );
243 void FlipFlop::update( bool firstTime, double dt )
245 if( _implementation == NULL ) {
246 SG_LOG( SG_AUTOPILOT, SG_ALERT, "No flip-flop implementation for " << get_name() << endl );
252 q0 = q = get_output();
254 if( _implementation->getState( dt, _input, q ) ) {
258 cout << "updating flip-flop \"" << get_name() << "\"" << endl;
259 cout << "prev. Output:" << q0 << endl;
260 for( InputMap::const_iterator it = _input.begin(); it != _input.end(); it++ )
261 cout << "Input \"" << (*it).first << "\":" << (*it).second->test() << endl;
262 cout << "new Output:" << q << endl;