File indexing completed on 2024-06-16 08:27:19

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 }