]> git.mxchange.org Git - flightgear.git/blob - src/Autopilot/flipflop.cxx
New autopilot subsystem implementation.
[flightgear.git] / src / Autopilot / flipflop.cxx
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 "inputvalue.hxx"
25 #include <Main/fg_props.hxx>
26
27 using namespace FGXMLAutopilot;
28
29 class RSFlipFlopImplementation : public FlipFlopImplementation {
30 protected:
31   bool _rIsDominant;
32 public:
33   RSFlipFlopImplementation( bool rIsDominant = true ) : _rIsDominant( rIsDominant ) {}
34   virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
35 };
36
37 class SRFlipFlopImplementation : public RSFlipFlopImplementation {
38 public:
39   SRFlipFlopImplementation() : RSFlipFlopImplementation( false ) {}
40 };
41
42 class ClockedFlipFlopImplementation : public RSFlipFlopImplementation {
43 protected:
44   bool _clock;
45   virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) = 0;
46 public:
47   ClockedFlipFlopImplementation( bool rIsDominant = true ) : RSFlipFlopImplementation( rIsDominant ), _clock(false) {}
48   virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
49 };
50
51 class JKFlipFlopImplementation : public ClockedFlipFlopImplementation {
52 public:
53   JKFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
54   virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q );
55 };
56
57 class DFlipFlopImplementation : public ClockedFlipFlopImplementation {
58 public:
59   DFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
60   virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
61     q = input.get_value("D");
62     return true;
63   }
64 };
65
66 class TFlipFlopImplementation : public ClockedFlipFlopImplementation {
67 public:
68   TFlipFlopImplementation( bool rIsDominant = true ) : ClockedFlipFlopImplementation ( rIsDominant ) {}
69   virtual bool onRaisingEdge( DigitalComponent::InputMap input, bool & q ) {
70     q = !q;
71     return true;
72   }
73 };
74
75 class MonoFlopImplementation : public JKFlipFlopImplementation {
76 protected:
77   virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode );
78   InputValueList _time;
79   double _t;
80 public:
81   MonoFlopImplementation( bool rIsDominant = true ) : JKFlipFlopImplementation( rIsDominant ) {}
82   virtual bool getState( double dt, DigitalComponent::InputMap input, bool & q );
83 };
84
85 bool MonoFlopImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode )
86 {
87   if( JKFlipFlopImplementation::configure( nodeName, configNode ) )
88     return true;
89
90   if (nodeName == "time") {
91     _time.push_back( new InputValue( configNode ) );
92     return true;
93   } 
94
95   return false;
96 }
97
98 bool MonoFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
99 {
100   if( JKFlipFlopImplementation::getState( dt, input, q ) ) {
101     _t = q ? _time.get_value() : 0;
102     return true;
103   }
104
105   _t -= dt;
106   if( _t <= 0.0 ) {
107     q = 0;
108     return true;
109   }
110
111   return false;
112 }
113
114
115 bool RSFlipFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
116 {
117   bool s = input.get_value("S");
118   bool r = input.get_value("R");
119
120   // s == false && q == false: no change, keep state
121   if( s || r ) {
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
128     }
129     return true; // signal state changed
130   }
131   return false; // signal state unchagned
132 }
133
134 bool ClockedFlipFlopImplementation::getState( double dt, DigitalComponent::InputMap input, bool & q )
135 {
136   if( RSFlipFlopImplementation::getState( dt, input, q ) )
137     return true;
138
139   bool c = input.get_value("clock");
140   bool raisingEdge = c && !_clock;
141     
142   _clock = c;
143
144   if( !raisingEdge ) return false; //signal no change
145   return onRaisingEdge( input, q );
146 }
147
148 bool JKFlipFlopImplementation::onRaisingEdge( DigitalComponent::InputMap input, bool & q )
149 {
150   bool j = input.get_value("J");
151   bool k = input.get_value("K");
152     
153   // j == false && k == false: no change, keep state
154   if( (j || k) ) {
155     if( j && k ) {
156       q = !q; // toggle
157     } else {
158       if( j ) q = true;  // set
159       if( k ) q = false; // reset
160     }
161     return true; // signal state changed
162   }
163
164   return false; // signal no change
165 }
166
167 bool FlipFlopImplementation::configure( SGPropertyNode_ptr configNode )
168 {
169   for (int i = 0; i < configNode->nChildren(); ++i ) {
170     SGPropertyNode_ptr prop;
171
172     SGPropertyNode_ptr child = configNode->getChild(i);
173     string cname(child->getName());
174
175     if( configure( cname, child ) )
176       continue;
177
178   } // for configNode->nChildren()
179
180   return true;
181 }
182
183
184 static map<string,FunctorBase<FlipFlopImplementation> *> componentForge;
185
186 bool FlipFlop::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) 
187
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>();
195   }
196
197   if( DigitalComponent::configure( nodeName, configNode ) )
198     return true;
199
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 );
204       return true;
205     }
206     _implementation = (*componentForge[type])( configNode->getParent() );
207     return true;
208   }
209
210   if (nodeName == "set"||nodeName == "S") {
211     _input["S"] = sgReadCondition( fgGetNode("/"), configNode );
212     return true;
213   }
214
215   if (nodeName == "reset" || nodeName == "R" ) {
216     _input["R"] = sgReadCondition( fgGetNode("/"), configNode );
217     return true;
218   } 
219
220   if (nodeName == "J") {
221     _input["J"] = sgReadCondition( fgGetNode("/"), configNode );
222     return true;
223   } 
224
225   if (nodeName == "K") {
226     _input["K"] = sgReadCondition( fgGetNode("/"), configNode );
227     return true;
228   } 
229
230   if (nodeName == "D") {
231     _input["D"] = sgReadCondition( fgGetNode("/"), configNode );
232     return true;
233   } 
234
235   if (nodeName == "clock") {
236     _input["clock"] = sgReadCondition( fgGetNode("/"), configNode );
237     return true;
238   }
239
240   return false; 
241 }
242
243 void FlipFlop::update( bool firstTime, double dt )
244 {
245   if( _implementation == NULL ) {
246     SG_LOG( SG_AUTOPILOT, SG_ALERT, "No flip-flop implementation for " << get_name() << endl );
247     return;
248   }
249
250   bool q0, q;
251
252   q0 = q = get_output();
253
254   if( _implementation->getState( dt, _input, q ) ) {
255     set_output( q );
256
257     if(_debug) {
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;
263     }
264   }
265 }
266
267