FlightGear next
flipflop.cxx
Go to the documentation of this file.
1// flipflop.hxx - implementation of multiple flip flop types
2//
3// Written by Torsten Dreyer
4//
5// Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de
6//
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.
11//
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.
16//
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.
20//
21
22#include "flipflop.hxx"
23#include "functor.hxx"
24#include <simgear/misc/inputvalue.hxx>
25#include <Main/fg_props.hxx>
26
27using std::map;
28using std::string;
29using std::endl;
30using std::cout;
31
32namespace FGXMLAutopilot {
33
65protected:
67public:
68 RSFlipFlopImplementation( bool rIsDominant = true ) : _rIsDominant( rIsDominant ) {}
69 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
70};
71
106
119private:
123 bool _clock;
124protected:
125
133 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) = 0;
134public:
135
140 ClockedFlipFlopImplementation( bool rIsDominant = true ) : RSFlipFlopImplementation( rIsDominant ), _clock(false) {}
141
150 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
151};
152
195public:
200 JKFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
201
208 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q );
209};
210
216public:
221 DFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
222
229 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
230 q = input.get_value("D");
231 return true;
232 }
233};
234
240public:
245 TFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
246
253 virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
254 q = !q;
255 return true;
256 }
257};
258
266protected:
267 virtual bool configure( SGPropertyNode& cfg_node,
268 const std::string& cfg_name,
269 SGPropertyNode& prop_root );
270 simgear::ValueList _time;
271 double _t;
272
273 bool isConfigProperty(const std::string& cfg_name) const override
274 {
275 return cfg_name == "time";
276 }
277
278public:
283 MonoFlopImplementation( bool rIsDominant = true ) : JKFlipFlopImplementation( rIsDominant ), _t(0.0) {}
292 virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
293};
294
295} // namespace
296
297using namespace FGXMLAutopilot;
298
299//------------------------------------------------------------------------------
300bool MonoFlopImplementation::configure( SGPropertyNode& cfg_node,
301 const std::string& cfg_name,
302 SGPropertyNode& prop_root )
303{
304 if( JKFlipFlopImplementation::configure(cfg_node, cfg_name, prop_root) )
305 return true;
306
307 if (cfg_name == "time") {
308 _time.push_back(new simgear::Value(prop_root, cfg_node));
309 return true;
310 }
311
312 return false;
313}
314
316{
317 if( JKFlipFlopImplementation::getState( dt, input, q ) ) {
318 _t = q ? _time.get_value() : 0;
319 return true;
320 }
321
322 _t -= dt;
323 if( _t <= 0.0 ) {
324 q = 0;
325 return true;
326 }
327
328 return false;
329}
330
331
333{
334 bool s = input.get_value("S");
335 bool r = input.get_value("R");
336
337 // s == false && q == false: no change, keep state
338 if( s || r ) {
339 if( _rIsDominant ) { // RS: reset is dominant
340 if( s ) q = true; // set
341 if( r ) q = false; // reset
342 } else { // SR: set is dominant
343 if( r ) q = false; // reset
344 if( s ) q = true; // set
345 }
346 return true; // signal state changed
347 }
348 return false; // signal state unchagned
349}
350
352{
353 bool c = input.get_value("clock");
354 bool raisingEdge = c && !_clock;
355
356 _clock = c;
357
358 if( RSFlipFlopImplementation::getState( dt, input, q ) )
359 return true;
360
361
362 if( !raisingEdge ) return false; //signal no change
363 return onRaisingEdge( input, q );
364}
365
367{
368 bool j = input.get_value("J");
369 bool k = input.get_value("K");
370
371 // j == false && k == false: no change, keep state
372 if( (j || k) ) {
373 if( j && k ) {
374 q = !q; // toggle
375 } else {
376 if( j ) q = true; // set
377 if( k ) q = false; // reset
378 }
379 return true; // signal state changed
380 }
381
382 return false; // signal no change
383}
384
385//------------------------------------------------------------------------------
386bool FlipFlopImplementation::configure( SGPropertyNode& prop_root,
387 SGPropertyNode& cfg )
388{
389 for( int i = 0; i < cfg.nChildren(); ++i )
390 {
391 SGPropertyNode_ptr child = cfg.getChild(i);
392 string cname(child->getNameString());
393
394 if( configure(*child, cname, prop_root) )
395 continue;
396 }
397
398 return true;
399}
400
401
402static map<string,FunctorBase<FlipFlopImplementation> *> componentForge;
403
404//------------------------------------------------------------------------------
405bool FlipFlop::configure( SGPropertyNode& cfg_node,
406 const std::string& cfg_name,
407 SGPropertyNode& prop_root )
408{
409 if( componentForge.empty() ) {
416 }
417
418 if( DigitalComponent::configure(cfg_node, cfg_name, prop_root) )
419 return true;
420
421 if( cfg_name == "type" ) {
422 string type(cfg_node.getStringValue());
423 if( componentForge.count(type) == 0 ) {
424 SG_LOG
425 (
426 SG_AUTOPILOT,
427 SG_BULK,
428 "unhandled flip-flop type <" << type << ">"
429 );
430 return true;
431 }
432 _implementation = (*componentForge[type])(prop_root, *cfg_node.getParent());
433 return true;
434 }
435
436 if (cfg_name == "set"||cfg_name == "S") {
437 _input["S"] = sgReadCondition(&prop_root, &cfg_node);
438 return true;
439 }
440
441 if (cfg_name == "reset" || cfg_name == "R" ) {
442 _input["R"] = sgReadCondition(&prop_root, &cfg_node);
443 return true;
444 }
445
446 if (cfg_name == "J") {
447 _input["J"] = sgReadCondition(&prop_root, &cfg_node);
448 return true;
449 }
450
451 if (cfg_name == "K") {
452 _input["K"] = sgReadCondition(&prop_root, &cfg_node);
453 return true;
454 }
455
456 if (cfg_name == "D") {
457 _input["D"] = sgReadCondition(&prop_root, &cfg_node);
458 return true;
459 }
460
461 if (cfg_name == "clock") {
462 _input["clock"] = sgReadCondition(&prop_root, &cfg_node);
463 return true;
464 }
465
466 if (_implementation && _implementation->isConfigProperty(cfg_name)) {
467 // componentForge CreateAndConfigureFunctor<> already called configure with all the nodes
468 // on our implementation, but we need to ensure we don't return false here for such nodes
469 return true;
470 }
471
472 return false;
473}
474
475void FlipFlop::update( bool firstTime, double dt )
476{
477 if( _implementation == NULL ) {
478 SG_LOG( SG_AUTOPILOT, SG_ALERT, "No flip-flop implementation for " << subsystemId() << endl );
479 return;
480 }
481
482 bool q0, q;
483
484 q0 = q = get_output();
485
486 if( _implementation->getState( dt, _input, q ) && q0 != q ) {
487 set_output( q );
488
489 if(_debug) {
490 cout << "updating flip-flop \"" << subsystemId() << "\"" << endl;
491 cout << "prev. Output:" << q0 << endl;
492 for( InputMap::const_iterator it = _input.begin(); it != _input.end(); ++it )
493 cout << "Input \"" << (*it).first << "\":" << (*it).second->test() << endl;
494 cout << "new Output:" << q << endl;
495 }
496 }
497}
498
499
500// Register the subsystem.
501SGSubsystemMgr::Registrant<FlipFlop> registrantFlipFlop;
#define i(x)
static ComponentForge componentForge
ClockedFlipFlopImplementation(bool rIsDominant=true)
constructor for a ClockedFlipFlopImplementation
Definition flipflop.cxx:140
virtual bool getState(double dt, DigitalComponent::InputMap input, bool &q)
evaluates the output state from the input lines.
Definition flipflop.cxx:351
virtual bool onRaisingEdge(DigitalComponent::InputMap input, bool &q)=0
pure virtual function to be implemented from the implementing class, gets called from the update meth...
bool _debug
debug flag, true if this component should generate some useful output on every iteration
Definition component.hxx:66
DFlipFlopImplementation(bool rIsDominant=true)
constructor for a DFlipFlopImplementation
Definition flipflop.cxx:221
virtual bool onRaisingEdge(DigitalComponent::InputMap input, bool &q)
compute the output state according to the logic table on the raising edge of the clock
Definition flipflop.cxx:229
bool get_value(const std::string &name) const
InputMap _input
Named input "pins".
virtual bool configure(SGPropertyNode &cfg_node, const std::string &cfg_name, SGPropertyNode &prop_root)
Over-rideable hook method to allow derived classes to refine top-level node parsing.
Interface for a flip flop implementation.
Definition flipflop.hxx:32
virtual bool configure(SGPropertyNode &cfg_node, const std::string &cfg_name, SGPropertyNode &prop_root)
configure this component from a property node.
Definition flipflop.hxx:39
virtual bool configure(SGPropertyNode &cfg_node, const std::string &cfg_name, SGPropertyNode &prop_root)
Over-rideable hook method to allow derived classes to refine top-level node parsing.
Definition flipflop.cxx:405
void update(bool firstTime, double dt)
Implementation of the pure virtual function of the Component class.
Definition flipflop.cxx:475
virtual bool onRaisingEdge(DigitalComponent::InputMap input, bool &q)
compute the output state according to the logic table on the raising edge of the clock
Definition flipflop.cxx:366
JKFlipFlopImplementation(bool rIsDominant=true)
constructor for a JKFlipFlopImplementation
Definition flipflop.cxx:200
void set_output(bool value)
Definition logic.cxx:41
bool get_output() const
Definition logic.cxx:51
virtual bool configure(SGPropertyNode &cfg_node, const std::string &cfg_name, SGPropertyNode &prop_root)
configure this component from a property node.
Definition flipflop.cxx:300
bool isConfigProperty(const std::string &cfg_name) const override
Definition flipflop.cxx:273
MonoFlopImplementation(bool rIsDominant=true)
constructor for a MonoFlopImplementation
Definition flipflop.cxx:283
virtual bool getState(double dt, DigitalComponent::InputMap input, bool &q)
evaluates the output state from the input lines and returns to the stable state after expiry of the i...
Definition flipflop.cxx:315
virtual bool getState(double dt, DigitalComponent::InputMap input, bool &q)
evaluates the output state from the input lines
Definition flipflop.cxx:332
RSFlipFlopImplementation(bool rIsDominant=true)
Definition flipflop.cxx:68
TFlipFlopImplementation(bool rIsDominant=true)
constructor for a TFlipFlopImplementation
Definition flipflop.cxx:245
virtual bool onRaisingEdge(DigitalComponent::InputMap input, bool &q)
compute the output state according to the logic table on the raising edge of the clock
Definition flipflop.cxx:253
SGSubsystemMgr::Registrant< FlipFlop > registrantFlipFlop
Definition flipflop.cxx:501