00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "circuitdocument.h"
00012 #include "component.h"
00013 #include "ecnode.h"
00014 #include "pin.h"
00015 #include "resistance.h"
00016 #include "simulator.h"
00017 #include "switch.h"
00018
00019 #include <kdebug.h>
00020 #include <qtimer.h>
00021
00022 #include <cmath>
00023 #include <stdlib.h>
00024 #include <time.h>
00025
00026 Switch::Switch( Component * parent, Pin * p1, Pin * p2, State state )
00027 {
00028 m_bouncePeriod_ms = 5;
00029 m_bBounce = false;
00030 m_bounceStart = 0;
00031 m_pBounceResistance = 0;
00032 m_pP1 = p1;
00033 m_pP2 = p2;
00034 m_pComponent = parent;
00035 m_pStopBouncingTimer = new QTimer( this );
00036 connect( m_pStopBouncingTimer, SIGNAL(timeout()), this, SLOT(stopBouncing()) );
00037
00038
00039 m_state = (state == Open) ? Closed : Open;
00040 setState(state);
00041 }
00042
00043
00044 Switch::~ Switch( )
00045 {
00046 if (m_pP1)
00047 m_pP1->setSwitchConnected( m_pP2, false );
00048
00049 if (m_pP2)
00050 m_pP2->setSwitchConnected( m_pP1, false );
00051 }
00052
00053
00054 void Switch::setState( State state )
00055 {
00056 if ( m_state == state )
00057 return;
00058
00059 m_state = state;
00060
00061 if ( m_bBounce )
00062 startBouncing();
00063 else
00064 {
00065
00066 stopBouncing();
00067 }
00068 }
00069
00070
00071 void Switch::setBounce( bool bounce, int msec )
00072 {
00073 m_bBounce = bounce;
00074 m_bouncePeriod_ms = msec;
00075 }
00076
00077
00078 void Switch::startBouncing()
00079 {
00080 if ( m_pBounceResistance )
00081 {
00082
00083 return;
00084 }
00085
00086 CircuitDocument * cd = m_pComponent->circuitDocument();
00087 if ( !cd )
00088 return;
00089
00090
00091
00092 m_pBounceResistance = m_pComponent->createResistance( m_pP1, m_pP2, 10000 );
00093 m_bounceStart = Simulator::self()->time();
00094 Simulator::self()->attachSwitch(this);
00095
00096
00097
00098 srand ( time(NULL) );
00099
00100
00101 bounce();
00102 }
00103
00104
00105 void Switch::bounce()
00106 {
00107 int bounced_ms = (( Simulator::self()->time() - m_bounceStart ) * 1000) / LOGIC_UPDATE_RATE;
00108 if ( bounced_ms >= m_bouncePeriod_ms )
00109 {
00110 if ( !m_pStopBouncingTimer->isActive() )
00111 m_pStopBouncingTimer->start( 0, true );
00112 return;
00113 }
00114
00115 double g = double(rand())/double(RAND_MAX);
00116
00117
00118 g = g * g * g * g;
00119
00120 m_pBounceResistance->setConductance( g );
00121 }
00122
00123
00124 void Switch::stopBouncing()
00125 {
00126 Simulator::self()->detachSwitch(this );
00127 m_pComponent->removeElement( m_pBounceResistance, true );
00128 m_pBounceResistance = 0;
00129
00130 bool connected = (m_state == Closed);
00131
00132 if ( m_pP1 && m_pP2 )
00133 {
00134 m_pP1->setSwitchConnected( m_pP2, connected );
00135 m_pP2->setSwitchConnected( m_pP1, connected );
00136 }
00137
00138 if ( CircuitDocument * cd = m_pComponent->circuitDocument() )
00139 cd->requestAssignCircuits();
00140 }
00141
00142
00143 bool Switch::calculateCurrent()
00144 {
00145 if ( !m_pP1 || !m_pP2 )
00146 return false;
00147
00148 if ( state() == Open )
00149 {
00150 m_pP1->setSwitchCurrentKnown( this );
00151 m_pP2->setSwitchCurrentKnown( this );
00152 return true;
00153 }
00154
00155 Pin * pins[2] = { m_pP1, m_pP2 };
00156
00157 double current = 0.0;
00158 bool currentKnown = false;
00159
00160 int pol;
00161 for ( unsigned i = 0; i < 2; ++i )
00162 {
00163 pol = (i == 0) ? 1 : -1;
00164
00165 const WireList inputs = pins[i]->inputWireList();
00166 const WireList outputs = pins[i]->outputWireList();
00167
00168 currentKnown = true;
00169 current = 0.0;
00170
00171 WireList::const_iterator end = inputs.end();
00172 for ( WireList::const_iterator it = inputs.begin(); it != end; ++it )
00173 {
00174 if ( !(*it) )
00175 continue;
00176
00177 if ( !(*it)->currentIsKnown() )
00178 {
00179 currentKnown = false;
00180 break;
00181 }
00182
00183 current += (*it)->current();
00184 }
00185
00186 if ( !currentKnown )
00187 continue;
00188
00189 end = outputs.end();
00190 for ( WireList::const_iterator it = outputs.begin(); it != end; ++it )
00191 {
00192 if ( !(*it) )
00193 continue;
00194
00195 if ( !(*it)->currentIsKnown() )
00196 {
00197 currentKnown = false;
00198 break;
00199 }
00200
00201 current -= (*it)->current();
00202 }
00203
00204 if ( currentKnown )
00205 break;
00206 }
00207
00208 if ( !currentKnown )
00209 return false;
00210
00211 m_pP1->setSwitchCurrentKnown( this );
00212 m_pP2->setSwitchCurrentKnown( this );
00213 m_pP1->mergeCurrent( -current * pol );
00214 m_pP2->mergeCurrent( current * pol );
00215
00216 return true;
00217 }
00218
00219 #include "switch.moc"
00220
00221