File indexing completed on 2025-04-20 11:09:33
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "wire.h" 0012 #include "pin.h" 0013 0014 #include <cassert> 0015 0016 #include <ktechlab_debug.h> 0017 0018 Wire::Wire(Pin *startPin, Pin *endPin) 0019 { 0020 assert(startPin); 0021 assert(endPin); 0022 0023 m_pStartPin = startPin; 0024 m_pEndPin = endPin; 0025 m_current = 0.; 0026 m_bCurrentIsKnown = false; 0027 0028 m_pStartPin->addOutputWire(this); 0029 m_pEndPin->addInputWire(this); 0030 } 0031 0032 Wire::~Wire() 0033 { 0034 } 0035 0036 bool Wire::calculateCurrent() 0037 { 0038 if (m_pStartPin->currentIsKnown() && m_pStartPin->numWires() < 2) { 0039 m_current = m_pStartPin->current(); 0040 m_bCurrentIsKnown = true; 0041 return true; 0042 } 0043 0044 if (m_pEndPin->currentIsKnown() && m_pEndPin->numWires() < 2) { 0045 m_current = -m_pEndPin->current(); 0046 m_bCurrentIsKnown = true; 0047 return true; 0048 } 0049 0050 if (m_pStartPin->currentIsKnown()) { 0051 double i = m_pStartPin->current(); 0052 bool ok = true; 0053 0054 const WireList outlist = m_pStartPin->outputWireList(); 0055 WireList::const_iterator end = outlist.end(); 0056 for (WireList::const_iterator it = outlist.begin(); it != end && ok; ++it) { 0057 if (*it && static_cast<Wire *>(*it) != this) { 0058 if ((*it)->currentIsKnown()) 0059 i -= (*it)->current(); 0060 else 0061 ok = false; 0062 } 0063 } 0064 0065 const WireList inlist = m_pStartPin->inputWireList(); 0066 end = inlist.end(); 0067 for (WireList::const_iterator it = inlist.begin(); it != end && ok; ++it) { 0068 if (*it && static_cast<Wire *>(*it) != this) { 0069 if ((*it)->currentIsKnown()) 0070 i += (*it)->current(); 0071 else 0072 ok = false; 0073 } 0074 } 0075 0076 if (ok) { 0077 m_current = i; 0078 m_bCurrentIsKnown = true; 0079 return true; 0080 } 0081 } 0082 0083 if (m_pEndPin->currentIsKnown()) { 0084 double i = -m_pEndPin->current(); 0085 bool ok = true; 0086 const WireList outlist = m_pEndPin->outputWireList(); 0087 0088 WireList::const_iterator end = outlist.end(); 0089 for (WireList::const_iterator it = outlist.begin(); it != end && ok; ++it) { 0090 if (*it && static_cast<Wire *>(*it) != this) { 0091 if ((*it)->currentIsKnown()) 0092 i += (*it)->current(); 0093 else 0094 ok = false; 0095 } 0096 } 0097 0098 const WireList inlist = m_pEndPin->inputWireList(); 0099 end = inlist.end(); 0100 for (WireList::const_iterator it = inlist.begin(); it != end && ok; ++it) { 0101 if (*it && static_cast<Wire *>(*it) != this) { 0102 if ((*it)->currentIsKnown()) 0103 i -= (*it)->current(); 0104 else 0105 ok = false; 0106 } 0107 } 0108 0109 if (ok) { 0110 m_current = i; 0111 m_bCurrentIsKnown = true; 0112 return true; 0113 } 0114 } 0115 0116 m_bCurrentIsKnown = false; 0117 return false; 0118 } 0119 0120 double Wire::voltage() const 0121 { 0122 double temp; 0123 0124 // TODO: the external connections trigger this, need to figure out how 0125 // the Probe classes manage to get away with unknown voltages. 0126 if ((temp = m_pStartPin->voltage() - m_pEndPin->voltage())) { 0127 qCWarning(KTL_LOG) << "Wire voltage error: " << temp << m_pStartPin->voltage() << m_pEndPin->voltage(); 0128 } 0129 0130 return m_pStartPin->voltage(); 0131 } 0132 0133 void Wire::setCurrentKnown(bool known) 0134 { 0135 m_bCurrentIsKnown = known; 0136 if (!known) 0137 m_current = 0.; 0138 }