component.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2004-2005 by David Saxton                               *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "canvasitemparts.h"
00012 #include "circuitdocument.h"
00013 #include "component.h"
00014 #include "src/core/ktlconfig.h"
00015 #include "ecnode.h"
00016 #include "itemdocumentdata.h"
00017 #include "node.h"
00018 #include "pin.h"
00019 #include "simulator.h"
00020 
00021 #include "bjt.h"
00022 #include "capacitance.h"
00023 #include "cccs.h"
00024 #include "ccvs.h"
00025 #include "currentsignal.h"
00026 #include "currentsource.h"
00027 #include "diode.h"
00028 #include "inductance.h"
00029 #include "logic.h"
00030 #include "opamp.h"
00031 #include "resistance.h"
00032 #include "switch.h"
00033 #include "vccs.h"
00034 #include "vcvs.h"
00035 #include "voltagepoint.h"
00036 #include "voltagesignal.h"
00037 #include "voltagesource.h"
00038 
00039 #include <cmath>
00040 #include <kdebug.h>
00041 #include <qbitarray.h>
00042 #include <qpainter.h>
00043 #include <qwidget.h>
00044 #include <qwmatrix.h>
00045 
00046 const int dipWidth = 112;
00047 const int pairSep = 32;
00048 
00049 // Degrees per radian
00050 static const double DPR = 180/M_PI;
00051 
00052 // #############
00053 
00054 Component::Component(ICNDocument *icnDocument, bool newItem, const QString &id)
00055         : CNItem(icnDocument, newItem, id),
00056         m_angleDegrees(0),
00057         b_flipped(false)
00058 {
00059         m_pCircuitDocument = dynamic_cast<CircuitDocument*>(icnDocument);
00060 
00061         for(int i=0; i<4; ++i) {
00062                 m_pPNode[i] = 0;
00063                 m_pNNode[i] = 0;
00064         }
00065 
00066         // Get configuration options
00067         slotUpdateConfiguration();
00068 
00069         // And finally register this :-)
00070         icnDocument->registerItem(this);
00071 }
00072 
00073 // #############
00074 
00075 Component::~Component()
00076 {
00077         removeElements();
00078         Simulator::self()->detachComponent(this);
00079 }
00080 
00081 // #############
00082 
00083 void Component::removeItem()
00084 {
00085         if(b_deleted) return;
00086 
00087         Simulator::self()->detachComponent(this);
00088         CNItem::removeItem();
00089 }
00090 
00091 // #############
00092 
00093 void Component::removeElements(bool setPinsInterIndependent)
00094 {
00095         const ElementMapList::iterator end = m_elementMapList.end();
00096         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it) {
00097                 Element *e = (*it).e;
00098                 if(e) {
00099                         emit elementDestroyed(e);
00100                         e->componentDeleted();
00101                 }
00102         }
00103 
00104         m_elementMapList.clear();
00105 
00106 // $$$$$$$$$$$$$$$$ KLUDGE, see comments in header about switches. 
00107         const SwitchList::iterator swEnd = m_switchList.end();
00108         for(SwitchList::iterator it = m_switchList.begin(); it != swEnd; ++it) {
00109                 Switch * sw = *it;
00110                 if(!sw) continue;
00111                 emit switchDestroyed(sw);
00112                 delete sw;
00113         }
00114         m_switchList.clear();
00115 // $$$$$$$$$$$$$$$$$$
00116 
00117         if(setPinsInterIndependent) setAllPinsInterIndependent();
00118 }
00119 
00120 // #############
00121 
00122 void Component::removeElement(Element *element, bool setPinsInterIndependent)
00123 {
00124         if(!element) return;
00125 
00126         emit elementDestroyed(element);
00127         element->componentDeleted();
00128 
00129         const ElementMapList::iterator end = m_elementMapList.end();
00130         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end;) {
00131                 // we need to find the next element before we delete the current one.
00132                 ElementMapList::iterator next = it;
00133                 ++next; 
00134 
00135                 if((*it).e == element) m_elementMapList.remove(it);
00136                 it = next;
00137         }
00138 
00139         if(setPinsInterIndependent) rebuildPinInterDepedence();
00140 }
00141 
00142 // #############
00143 
00144 void Component::removeSwitch(Switch * sw)
00145 {
00146         if(!sw) return;
00147 
00148         emit switchDestroyed(sw);
00149         delete sw;
00150         m_switchList.remove(sw);
00151         m_pCircuitDocument->requestAssignCircuits();
00152 }
00153 
00154 // #############
00155 
00156 void Component::setNodalCurrents()
00157 {
00158         const ElementMapList::iterator end = m_elementMapList.end();
00159         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it) {
00160                 ElementMap m = (*it);
00161                 for(int i=0; i<4; i++)  {
00162                         if(m.n[i]) m.n[i]->mergeCurrent(m.e->nodeCurrent(i));
00163                 }
00164         }
00165 }
00166 
00167 void Component::initPainter(QPainter &p)
00168 {
00169         CNItem::initPainter(p);
00170 
00171         if(!b_flipped && (m_angleDegrees%360 == 0)) return;
00172 
00173         p.save();
00174         p.translate(int(x()), int(y()));
00175 
00176         if(b_flipped) p.scale(-1, 1);
00177 
00178         p.rotate(m_angleDegrees);
00179         p.translate(-int(x()), -int(y()));
00180 }
00181 
00182 void Component::deinitPainter(QPainter &p)
00183 {
00184         if(!b_flipped && (m_angleDegrees%360 == 0)) return;
00185 
00186         p.restore();
00187 }
00188 
00189 void Component::setAngleDegrees(int degrees)
00190 {
00191         updateConnectorPoints(false);
00192         m_angleDegrees = degrees;
00193         itemPointsChanged();
00194         updateAttachedPositioning();
00195         p_icnDocument->requestRerouteInvalidatedConnectors();
00196 }
00197 
00198 void Component::setFlipped(bool flipped)
00199 {
00200         updateConnectorPoints(false);
00201         b_flipped = flipped;
00202         itemPointsChanged();
00203         updateAttachedPositioning();
00204         p_icnDocument->requestRerouteInvalidatedConnectors();
00205 }
00206 
00207 void Component::itemPointsChanged()
00208 {
00209         QPointArray transformedPoints = transMatrix(m_angleDegrees, b_flipped, 0, 0, false).map(m_itemPoints);
00210 //      transformedPoints.translate(int(x()), int(y()));
00211         setPoints(transformedPoints);
00212 }
00213 
00214 void Component::restoreFromItemData(const ItemData &itemData)
00215 {
00216         CNItem::restoreFromItemData(itemData);
00217         
00218         setAngleDegrees(int(itemData.angleDegrees));
00219         setFlipped(itemData.flipped);
00220 }
00221 
00222 ItemData Component::itemData() const
00223 {
00224         ItemData itemData = CNItem::itemData();
00225         itemData.angleDegrees = m_angleDegrees;
00226         itemData.flipped = b_flipped;
00227         return itemData;
00228 }
00229 
00230 QWMatrix Component::transMatrix(int angleDegrees, bool flipped, int x, int y, bool inverse)
00231 {
00232         QWMatrix m;
00233         m.translate(x, y);
00234 
00235         if(inverse) {
00236                 m.rotate(-angleDegrees);
00237                 if(flipped) m.scale(-1, 1);
00238         } else {
00239                 if(flipped) m.scale(-1, 1);
00240                 m.rotate(angleDegrees);
00241         }
00242 
00243         m.translate(-x, -y);
00244         m.setTransformationMode(QWMatrix::Areas);
00245         return m;
00246 }
00247 
00248 void Component::finishedCreation()
00249 {
00250         CNItem::finishedCreation();
00251         updateAttachedPositioning();
00252 }
00253 
00254 void Component::updateAttachedPositioning()
00255 {
00256         if(b_deleted || !m_bDoneCreation) return;
00257 
00258         //BEGIN Transform the nodes
00259         const NodeMap::iterator end = m_nodeMap.end();
00260         for(NodeMap::iterator it = m_nodeMap.begin(); it != end; ++it) {
00261                 if(!it.data().node) kdError() << k_funcinfo << "Node in nodemap is null" << endl;
00262                 else {
00263                         int nx = int((std::cos(m_angleDegrees/DPR) * it.data().x) - (std::sin(m_angleDegrees/DPR) * it.data().y));
00264                         int ny = int((std::sin(m_angleDegrees/DPR) * it.data().x) + (std::cos(m_angleDegrees/DPR) * it.data().y));
00265 
00266                         if(b_flipped) nx = -nx;
00267 
00268 #define round_8(x) (((x) > 0) ? int(((x)+4)/8)*8 : int(((x)-4)/8)*8)
00269                         nx = round_8(nx);
00270                         ny = round_8(ny);
00271 #undef round_8
00272 
00273                         int newDir = (((m_angleDegrees + it.data().orientation)%360)+360)%360;
00274                         if(b_flipped) newDir = (((180-newDir)%360)+360)%360;
00275 
00276                         it.data().node->move(nx+x(), ny+y());
00277                         it.data().node->setOrientation((Node::node_dir)newDir);
00278                 }
00279         }
00280         //END Transform the nodes
00281 
00282         //BEGIN Transform the GuiParts
00283         QWMatrix m;
00284         
00285         if(b_flipped) m.scale(-1, 1);
00286 
00287         m.rotate(m_angleDegrees);
00288         m.setTransformationMode(QWMatrix::Areas);
00289 
00290         const TextMap::iterator textMapEnd = m_textMap.end();
00291         for(TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it) {
00292                 QRect newPos = m.mapRect(it.data()->recommendedRect());
00293                 it.data()->move(newPos.x() + x(), newPos.y() + y());
00294                 it.data()->setGuiPartSize(newPos.width(), newPos.height());
00295                 it.data()->setAngleDegrees(m_angleDegrees);
00296         }
00297 
00298         const WidgetMap::iterator widgetMapEnd = m_widgetMap.end();
00299         for(WidgetMap::iterator it = m_widgetMap.begin(); it != widgetMapEnd; ++it) {
00300                 QRect newPos = m.mapRect(it.data()->recommendedRect());
00301                 it.data()->move(newPos.x() + x(), newPos.y() + y());
00302                 it.data()->setGuiPartSize(newPos.width(), newPos.height());
00303                 it.data()->setAngleDegrees(m_angleDegrees);
00304         }
00305         //END Transform the GuiParts
00306 }
00307 
00308 void Component::drawPortShape(QPainter & p)
00309 {
00310         int h = height();
00311         int w = width() - 1;
00312         int _x = int(x() + offsetX());
00313         int _y = int(y() + offsetY());
00314 
00315         double roundSize = 8;
00316         double slantIndent = 8;
00317 
00318         double inner = std::atan(h/slantIndent);        // Angle for slight corner
00319         double outer = M_PI-inner;                      // Angle for sharp corner
00320 
00321         int inner16 = int(16*inner*DPR);
00322         int outer16 = int(16*outer*DPR);
00323 
00324         p.save();
00325         p.setPen(Qt::NoPen);
00326         p.drawPolygon(areaPoints());
00327         p.restore();
00328 
00329         initPainter(p);
00330 
00331         // Left line
00332         p.drawLine(int(_x), int(_y+roundSize/2), int(_x), int(_y+h-roundSize/2));
00333 
00334         // Right line
00335         p.drawLine(int(_x+w), int(_y-slantIndent+h-roundSize/2), int(_x+w), int(_y+slantIndent+roundSize/2));
00336 
00337         // Bottom line
00338         p.drawLine(int(_x+(1-std::cos(outer))*(roundSize/2)), int(_y+h+(std::sin(outer)-1)*(roundSize/2)), int(_x+w+(std::cos(inner)-1)*(roundSize/2)), int(_y+h-slantIndent+(std::sin(inner)-1)*(roundSize/2)));
00339 
00340         // Top line
00341         p.drawLine(int(_x+w+(std::cos(outer)-1)*(roundSize/2)), int(_y+slantIndent+(1-std::sin(inner))*(roundSize/2)), int(_x+(1-std::cos(inner))*(roundSize/2)),       int(_y+(1-std::sin(outer))*(roundSize/2)));
00342 
00343         // Top left
00344         p.drawArc(int(_x), int(_y), int(roundSize), int(roundSize), 90*16, outer16);
00345 
00346         // Bottom left
00347         p.drawArc(int(_x), int(_y+h-roundSize), int(roundSize), int(roundSize), 180*16, outer16);
00348 
00349         // Top right
00350         p.drawArc(int(_x+w-roundSize),  int(_y+slantIndent), int(roundSize), int(roundSize), 0, inner16);
00351 
00352         // Bottom right
00353         p.drawArc(int(_x+w-roundSize),  int(_y-slantIndent+h-roundSize),        int(roundSize), int(roundSize), 270*16, inner16);
00354 
00355         deinitPainter(p);
00356 }
00357 
00358 void Component::initDIP(const QStringList & pins)
00359 {
00360         const int numPins = pins.size();
00361         const int numSide = numPins/2 + numPins%2;
00362 
00363         // Pins along left
00364         for(int i=0; i<numSide; i++) {
00365                 if(!pins[i].isEmpty()) {
00366                         const int nodeX = -8+offsetX();
00367                         const int nodeY = (i+1)*16+offsetY();
00368                         ECNode *node = ecNodeWithID(pins[i]);
00369 
00370                         if(node) {
00371                                 m_nodeMap[pins[i]].x = nodeX;
00372                                 m_nodeMap[pins[i]].y = nodeY;
00373                                 m_nodeMap[pins[i]].orientation = (Node::node_dir)0;
00374                         } else createPin(nodeX, nodeY, 0, pins[i]);
00375                 }
00376         }
00377 
00378         // Pins along right
00379         for(int i=numSide; i<numPins; i++) {
00380                 if(!pins[i].isEmpty()) {
00381                         const int nodeX = width()+8+offsetX();
00382                         const int nodeY = (2*numSide-i)*16+offsetY();
00383                         ECNode *node = ecNodeWithID(pins[i]);
00384                         if(node) {
00385                                 m_nodeMap[pins[i]].x = nodeX;
00386                                 m_nodeMap[pins[i]].y = nodeY;
00387                                 m_nodeMap[pins[i]].orientation = (Node::node_dir)180;
00388                         } else createPin(nodeX, nodeY, 180, pins[i]);
00389                 }
00390         }
00391 
00392         updateAttachedPositioning();
00393 }
00394 
00395 void Component::initDIPSymbol(const QStringList & pins, int _width)
00396 {
00397         const int numPins = pins.size();
00398         const int numSide = numPins/2 + numPins%2;
00399 
00400         setSize(-(_width-(_width%16))/2, -(numSide+1)*8, _width, (numSide+1)*16, true);
00401 
00402         QWidget tmpWidget;
00403         QPainter p(&tmpWidget);
00404 
00405         p.setFont(m_font);
00406 
00407         // Pins along left
00408         for(int i=0; i<numSide; i++) {
00409                 if(!pins[i].isEmpty()) {
00410                         const QString text = *pins.at(i);
00411 
00412                         const int _top = (i+1)*16-8 + offsetY();
00413                         const int _width = width()/2 - 6;
00414                         const int _left = 6 + offsetX();
00415                         const int _height = 16;
00416 
00417                         QRect br = p.boundingRect(QRect(_left, _top, _width, _height), Qt::AlignLeft, text);
00418                         addDisplayText(text, br, text);
00419                 }
00420         }
00421         // Pins along right
00422         for(int i=numSide; i<numPins; i++) {
00423                 if(!pins[i].isEmpty()) {
00424                         const QString text = *pins.at(i);
00425 
00426                         const int _top = (2*numSide-i)*16 - 8 + offsetY();
00427                         const int _width = width()/2 - 6;
00428                         const int _left = (width()/2) + offsetX();
00429                         const int _height = 16;
00430 
00431                         QRect br = p.boundingRect(QRect(_left, _top, _width, _height), Qt::AlignRight, text);
00432                         addDisplayText(text, br, text);
00433                 }
00434         }
00435         
00436         updateAttachedPositioning();
00437 }
00438 
00439 // ###############
00440 
00441 void Component::init1PinLeft(int h1)
00442 {
00443         if(h1 == -1) h1 = offsetY()+height()/2;
00444 
00445         m_pNNode[0] = createPin(offsetX()-8, h1, 0, "n1");
00446 }
00447 
00448 void Component::init2PinLeft(int h1, int h2)
00449 {
00450         if(h1 == -1) h1 = offsetY()+8;
00451         if(h2 == -1) h2 = offsetY()+height()-8;
00452 
00453         m_pNNode[0] = createPin(offsetX()-8, h1, 0, "n1");
00454         m_pNNode[1] = createPin(offsetX()-8, h2, 0, "n2");
00455 }
00456 
00457 void Component::init3PinLeft(int h1, int h2, int h3)
00458 {
00459         if(h1 == -1) h1 = offsetY()+8;
00460         if(h2 == -1) h2 = offsetY()+height()/2;
00461         if(h3 == -1) h3 = offsetY()+height()-8;
00462 
00463         m_pNNode[0] = createPin(offsetX()-8, h1, 0, "n1");
00464         m_pNNode[1] = createPin(offsetX()-8, h2, 0, "n2");
00465         m_pNNode[2] = createPin(offsetX()-8, h3, 0, "n3");
00466 }
00467 
00468 void Component::init4PinLeft(int h1, int h2, int h3, int h4)
00469 {
00470         if(h1 == -1) h1 = offsetY()+8;
00471         if(h2 == -1) h2 = offsetY()+24;
00472         if(h3 == -1) h3 = offsetY()+height()-24;
00473         if(h4 == -1) h4 = offsetY()+height()-8;
00474 
00475         m_pNNode[0] = createPin(offsetX()-8, h1, 0, "n1");
00476         m_pNNode[1] = createPin(offsetX()-8, h2, 0, "n2");
00477         m_pNNode[2] = createPin(offsetX()-8, h3, 0, "n3");
00478         m_pNNode[3] = createPin(offsetX()-8, h4, 0, "n4");
00479 }
00480 
00481 void Component::init1PinRight(int h1)
00482 {
00483         if(h1 == -1) h1 = offsetY()+height()/2;
00484 
00485         m_pPNode[0] = createPin(offsetX()+width()+8, h1, 180, "p1");
00486 }
00487 
00488 void Component::init2PinRight(int h1, int h2)
00489 {
00490         if(h1 == -1) h1 = offsetY()+8;
00491         if(h2 == -1) h2 = offsetY()+height()-8;
00492 
00493         m_pPNode[0] = createPin(offsetX()+width()+8, h1, 180, "p1");
00494         m_pPNode[1] = createPin(offsetX()+width()+8, h2, 180, "p2");
00495 }
00496 
00497 void Component::init3PinRight(int h1, int h2, int h3)
00498 {
00499         if(h1 == -1) h1 = offsetY()+8;
00500         if(h2 == -1) h2 = offsetY()+height()/2;
00501         if(h3 == -1) h3 = offsetY()+height()-8;
00502 
00503         m_pPNode[0] = createPin(offsetX()+width()+8, h1, 180, "p1");
00504         m_pPNode[1] = createPin(offsetX()+width()+8, h2, 180, "p2");
00505         m_pPNode[2] = createPin(offsetX()+width()+8, h3, 180, "p3");
00506 }
00507 
00508 void Component::init4PinRight(int h1, int h2, int h3, int h4)
00509 {
00510         if(h1 == -1) h1 = offsetY()+8;
00511         if(h2 == -1) h2 = offsetY()+24;
00512         if(h3 == -1) h3 = offsetY()+height()-24;
00513         if(h4 == -1) h4 = offsetY()+height()-8;
00514 
00515         m_pPNode[0] = createPin(offsetX()+width()+8, h1, 180, "p1");
00516         m_pPNode[1] = createPin(offsetX()+width()+8, h2, 180, "p2");
00517         m_pPNode[2] = createPin(offsetX()+width()+8, h3, 180, "p3");
00518         m_pPNode[3] = createPin(offsetX()+width()+8, h4, 180, "p4");
00519 }
00520 
00521 // ###############
00522 
00523 ECNode* Component::ecNodeWithID(const QString &ecNodeId)
00524 {
00525         return dynamic_cast<ECNode*>(p_icnDocument->nodeWithID(nodeId(ecNodeId)));
00526 }
00527 
00528 void Component::slotUpdateConfiguration()
00529 {
00530         const LogicConfig logicConfig = LogicIn::getConfig();
00531 
00532         const ElementMapList::iterator end = m_elementMapList.end();
00533         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it)
00534         {
00535                 if(LogicIn *logicIn = dynamic_cast<LogicIn*>((*it).e))
00536                         logicIn->setLogic(logicConfig);
00537         }
00538 }
00539 
00540 BJT *Component::createBJT(ECNode *c, ECNode *b, ECNode *e, bool isNPN)
00541 {
00542         return createBJT(c->pin(), b->pin(), e->pin(), isNPN);
00543 }
00544 
00545 Capacitance *Component::createCapacitance(ECNode *n0, ECNode *n1, double capacitance)
00546 {
00547         return createCapacitance(n0->pin(), n1->pin(), capacitance);
00548 }
00549 
00550 CCCS *Component::createCCCS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain)
00551 {
00552         return createCCCS(n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain);
00553 }
00554 
00555 CCVS *Component::createCCVS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain)
00556 {
00557         return createCCVS(n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain);
00558 }
00559 
00560 CurrentSignal *Component::createCurrentSignal(ECNode *n0, ECNode *n1, double current)
00561 {
00562         return createCurrentSignal(n0->pin(), n1->pin(), current);
00563 }
00564 
00565 CurrentSource *Component::createCurrentSource(ECNode *n0, ECNode *n1, double current)
00566 {
00567         return createCurrentSource(n0->pin(), n1->pin(), current);
00568 }
00569 
00570 Diode *Component::createDiode(ECNode *n0, ECNode *n1)
00571 {
00572         return createDiode(n0->pin(), n1->pin());
00573 }
00574 
00575 Inductance *Component::createInductance(ECNode *n0, ECNode *n1, double inductance)
00576 {
00577         return createInductance(n0->pin(), n1->pin(), inductance);
00578 }
00579 
00580 LogicIn *Component::createLogicIn(ECNode *node)
00581 {
00582         return createLogicIn(node->pin());
00583 }
00584 
00585 LogicOut *Component::createLogicOut(ECNode *node, bool isHigh)
00586 {
00587         return createLogicOut(node->pin(), isHigh);
00588 }
00589 
00590 OpAmp *Component::createOpAmp(ECNode * nonInverting, ECNode * out, ECNode * inverting)
00591 {
00592         return createOpAmp(nonInverting->pin(), out->pin(), inverting->pin());
00593 }
00594 
00595 Resistance *Component::createResistance(ECNode *n0, ECNode *n1, double resistance)
00596 {
00597         return createResistance(n0->pin(), n1->pin(), resistance);
00598 }
00599 
00600 Switch *Component::createSwitch(ECNode *n0, ECNode *n1, bool open)
00601 {
00602         return createSwitch(n0->pin(), n1->pin(), open);
00603 }
00604 
00605 VCCS *Component::createVCCS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain)
00606 {
00607         return createVCCS(n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain); }
00608 
00609 VCVS *Component::createVCVS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain)
00610 {
00611         return createVCVS(n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain);
00612 }
00613 
00614 VoltagePoint *Component::createVoltagePoint(ECNode *n0, double voltage)
00615 {
00616         return createVoltagePoint(n0->pin(), voltage);
00617 }
00618 
00619 VoltageSignal *Component::createVoltageSignal(ECNode *n0, ECNode *n1, double voltage)
00620 {
00621         return createVoltageSignal(n0->pin(), n1->pin(), voltage);
00622 }
00623 
00624 VoltageSource *Component::createVoltageSource(ECNode *n0, ECNode *n1, double voltage)
00625 {
00626         return createVoltageSource(n0->pin(), n1->pin(), voltage);
00627 }
00628 
00629 BJT* Component::createBJT(Pin *cN, Pin *bN, Pin *eN, bool isNPN)
00630 {
00631         BJT *e = new BJT(isNPN);
00632 
00633         QValueList<Pin*> pins;
00634         pins << bN << cN << eN;
00635 
00636         ElementMapList::iterator it = handleElement(e, pins);
00637         setInterDependent(it, pins);
00638         return e;
00639 }
00640 
00641 Capacitance* Component::createCapacitance(Pin *n0, Pin *n1, double capacitance)
00642 {
00643         Capacitance *e = new Capacitance(capacitance, 1./LINEAR_UPDATE_RATE);
00644 
00645         QValueList<Pin*> pins;
00646         pins << n0 << n1;
00647 
00648         ElementMapList::iterator it = handleElement(e, pins);
00649         setInterDependent(it, pins);
00650         return e;
00651 }
00652 
00653 CCCS* Component::createCCCS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain)
00654 {
00655         CCCS *e = new CCCS(gain);
00656 
00657         QValueList<Pin*> pins;
00658         pins << n0 << n1 << n2 << n3;
00659 
00660         ElementMapList::iterator it = handleElement(e, pins);
00661         setInterDependent(it, pins);
00662         return e;
00663 }
00664 
00665 CCVS* Component::createCCVS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain)
00666 {
00667         CCVS *e = new CCVS(gain);
00668 
00669         QValueList<Pin*> pins;
00670         pins << n0 << n1 << n2 << n3;
00671 
00672         ElementMapList::iterator it = handleElement(e, pins);
00673         setInterCircuitDependent(it, pins);
00674 
00675         pins.clear();
00676         pins << n0 << n1;
00677         setInterGroundDependent(it, pins);
00678 
00679         pins.clear();
00680         pins << n2 << n3;
00681         setInterGroundDependent(it, pins);
00682 
00683         return e;
00684 }
00685 
00686 CurrentSignal *Component::createCurrentSignal(Pin *n0, Pin *n1, double current)
00687 {
00688         CurrentSignal *e = new CurrentSignal(1./LINEAR_UPDATE_RATE, current);
00689 
00690         QValueList<Pin*> pins;
00691         pins << n0 << n1;
00692 
00693         ElementMapList::iterator it = handleElement(e, pins);
00694         setInterDependent(it, pins);
00695         return e;
00696 }
00697 
00698 CurrentSource *Component::createCurrentSource(Pin *n0, Pin *n1, double current)
00699 {
00700         CurrentSource *e = new CurrentSource(current);
00701 
00702         QValueList<Pin*> pins;
00703         pins << n0 << n1;
00704 
00705         ElementMapList::iterator it = handleElement(e, pins);
00706         setInterDependent(it, pins);
00707         return e;
00708 }
00709 
00710 Diode *Component::createDiode(Pin *n0, Pin *n1)
00711 {
00712         Diode *e = new Diode();
00713 
00714         QValueList<Pin*> pins;
00715         pins << n0 << n1;
00716 
00717         ElementMapList::iterator it = handleElement(e, pins);
00718         setInterDependent(it, pins);
00719         return e;
00720 }
00721 
00722 Inductance *Component::createInductance(Pin *n0, Pin *n1, double inductance)
00723 {
00724         Inductance *e = new Inductance(inductance, 1./LINEAR_UPDATE_RATE);
00725 
00726         QValueList<Pin*> pins;
00727         pins << n0 << n1;
00728 
00729         ElementMapList::iterator it = handleElement(e, pins);
00730         setInterDependent(it, pins);
00731         return e;
00732 }
00733 
00734 LogicIn *Component::createLogicIn(Pin *node)
00735 {
00736         LogicIn *e = new LogicIn(LogicIn::getConfig());
00737 
00738         QValueList<Pin*> pins;
00739         pins << node;
00740 
00741         ElementMapList::iterator it = handleElement(e, pins);
00742         return e;
00743 }
00744 
00745 LogicOut *Component::createLogicOut(Pin *node, bool isHigh)
00746 {
00747         LogicOut *e = new LogicOut(LogicIn::getConfig(), isHigh);
00748 
00749         QValueList<Pin*> pins;
00750         pins << node;
00751 
00752         ElementMapList::iterator it = handleElement(e, pins);
00753         setInterDependent(it, pins);
00754         return e;
00755 }
00756 
00757 OpAmp * Component::createOpAmp(Pin * nonInverting, Pin * inverting, Pin * out)
00758 {
00759         OpAmp *e = new OpAmp();
00760 
00761         QValueList<Pin*> pins;
00762         pins << nonInverting << inverting << out;
00763 
00764         ElementMapList::iterator it = handleElement(e, pins);
00765         setInterDependent(it, pins);
00766         return e;
00767 }
00768 
00769 Resistance* Component::createResistance(Pin *n0, Pin *n1, double resistance)
00770 {
00771         Resistance *e = new Resistance(resistance);
00772 
00773         QValueList<Pin*> pins;
00774         pins << n0 << n1;
00775 
00776         ElementMapList::iterator it = handleElement(e, pins);
00777         setInterDependent(it, pins);
00778         return e;
00779 }
00780 
00781 Switch* Component::createSwitch(Pin *n0, Pin *n1, bool open)
00782 {
00783         // Note that a Switch is not really an element (although in many cases it
00784         // behaves very much like one).
00785 
00786         Switch *e = new Switch(this, n0, n1, open ? Switch::Open : Switch::Closed);
00787         m_switchList.append(e);
00788         n0->addSwitch(e);
00789         n1->addSwitch(e);
00790         emit switchCreated(e);
00791         return e;
00792 }
00793 
00794 VCCS* Component::createVCCS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain)
00795 {
00796         VCCS *e = new VCCS(gain);
00797 
00798         QValueList<Pin*> pins;
00799         pins << n0 << n1 << n2 << n3;
00800 
00801         ElementMapList::iterator it = handleElement(e, pins);
00802         setInterDependent(it, pins);
00803         return e;
00804 }
00805 
00806 VCVS* Component::createVCVS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain)
00807 {
00808         VCVS *e = new VCVS(gain);
00809 
00810         QValueList<Pin*> pins;
00811         pins << n0 << n1 << n2 << n3;
00812 
00813         ElementMapList::iterator it = handleElement(e, pins);
00814         setInterCircuitDependent(it, pins);
00815 
00816         pins.clear();
00817         pins << n0 << n1;
00818         setInterGroundDependent(it, pins);
00819 
00820         pins.clear();
00821         pins << n2 << n3;
00822         setInterGroundDependent(it, pins);
00823         return e;
00824 }
00825 
00826 VoltagePoint* Component::createVoltagePoint(Pin *n0, double voltage)
00827 {
00828         VoltagePoint *e = new VoltagePoint(voltage);
00829 
00830         QValueList<Pin*> pins;
00831         pins << n0;
00832 
00833         ElementMapList::iterator it = handleElement(e, pins);
00834         setInterDependent(it, pins);
00835         return e;
00836 }
00837 
00838 VoltageSignal* Component::createVoltageSignal(Pin *n0, Pin *n1, double voltage)
00839 {
00840         VoltageSignal *e = new VoltageSignal(1./LINEAR_UPDATE_RATE, voltage);
00841 
00842         QValueList<Pin*> pins;
00843         pins << n0 << n1;
00844 
00845         ElementMapList::iterator it = handleElement(e, pins);
00846         setInterDependent(it, pins);
00847         return e;
00848 }
00849 
00850 VoltageSource* Component::createVoltageSource(Pin *n0, Pin *n1, double voltage)
00851 {
00852         VoltageSource *e = new VoltageSource(voltage);
00853 
00854         QValueList<Pin*> pins;
00855         pins << n0 << n1;
00856 
00857         ElementMapList::iterator it = handleElement(e, pins);
00858         setInterDependent(it, pins);
00859         return e;
00860 }
00861 
00862 ElementMapList::iterator Component::handleElement(Element *e, const QValueList<Pin*> & pins) {
00863         if(!e) return m_elementMapList.end();
00864 
00865         ElementMap em;
00866         em.e = e;
00867         int at = 0;
00868 
00869         QValueList<Pin*>::ConstIterator end = pins.end();
00870         for(QValueList<Pin*>::ConstIterator it = pins.begin(); it != end; ++it) {
00871                 (*it)->addElement(e);
00872                 em.n[at++] = *it;
00873         }
00874 
00875         ElementMapList::iterator it = m_elementMapList.append(em);
00876 
00877         emit elementCreated(e);
00878         return it;
00879 }
00880 
00881 void Component::setInterDependent(ElementMapList::iterator it, const QValueList<Pin*> &pins)
00882 {
00883         setInterCircuitDependent(it, pins);
00884         setInterGroundDependent(it, pins);
00885 }
00886 
00887 void Component::setInterCircuitDependent(ElementMapList::iterator it, const QValueList<Pin*> & pins)
00888 {
00889         QValueList<Pin*>::ConstIterator end = pins.end();
00890         for(QValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1) {
00891                 for(QValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2) {
00892                         (*it1)->addCircuitDependentPin(*it2);
00893                 }
00894         }
00895 
00896         (*it).interCircuitDependent.append(pins);
00897 }
00898 
00899 void Component::setInterGroundDependent(ElementMapList::iterator it, const QValueList<Pin*> & pins)
00900 {
00901         QValueList<Pin*>::ConstIterator end = pins.end();
00902         for(QValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1) {
00903                 for(QValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2) {
00904                         (*it1)->addGroundDependentPin(*it2);
00905                 }
00906         }
00907 
00908         (*it).interGroundDependent.append(pins);
00909 }
00910 
00911 void Component::rebuildPinInterDepedence()
00912 {
00913         setAllPinsInterIndependent();
00914 
00915         // Rebuild dependencies
00916         ElementMapList::iterator emlEnd = m_elementMapList.end();
00917         for(ElementMapList::iterator it = m_elementMapList.begin(); it != emlEnd; ++it)
00918         {
00919         // Many copies of the pin lists as these will be affected when we call setInter*Dependent
00920                 PinListList list = (*it).interCircuitDependent;
00921 
00922                 PinListList::iterator depEnd = list.end();
00923                 for(PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt)
00924                         setInterCircuitDependent(it, *depIt);
00925 
00926                 list = (*it).interGroundDependent;
00927 
00928                 depEnd = list.end();
00929                 for(PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt)
00930                         setInterGroundDependent(it, *depIt);
00931         }
00932 }
00933 
00934 void Component::setAllPinsInterIndependent()
00935 {
00936         NodeMap::iterator nmEnd = m_nodeMap.end();
00937         for(NodeMap::iterator it = m_nodeMap.begin(); it != nmEnd; ++it)
00938         {
00939                 PinVector pins = (static_cast<ECNode*>(it.data().node))->pins();
00940                 PinVector::iterator pinsEnd = pins.end();
00941                 for(PinVector::iterator pinsIt = pins.begin(); pinsIt != pinsEnd; ++pinsIt)
00942                 {
00943                         if(*pinsIt) (*pinsIt)->removeDependentPins();
00944                 }
00945         }
00946 }
00947 
00948 void Component::initElements(const uint stage)
00949 {
00951 
00952         const ElementMapList::iterator end = m_elementMapList.end();
00953 
00954         if(stage == 1) {
00955                 for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it) {
00956                         (*it).e->add_initial_dc();
00957                 }
00958                 return;
00959         }
00960         
00961         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it) {
00962                 ElementMap m = *it;
00963 
00964                 if(m.n[3])      m.e->setCNodes(m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId(), m.n[3]->eqId());
00965                 else if(m.n[2]) m.e->setCNodes(m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId());
00966                 else if(m.n[1]) m.e->setCNodes(m.n[0]->eqId(), m.n[1]->eqId());
00967                 else if(m.n[0]) m.e->setCNodes(m.n[0]->eqId());
00968         }
00969         
00970         for(ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it) {
00971                 (*it).e->add_map();
00972         }
00973 }
00974 
00975 ECNode *Component::createPin(double x, double y, int orientation, const QString & name)
00976 {
00977         return dynamic_cast<ECNode*>(createNode(x, y, orientation, name, Node::ec_pin));
00978 }
00979 
00980 //BEGIN class ElementMap
00981 ElementMap::ElementMap()
00982 {
00983         e = 0;
00984         for(int i = 0; i < 4; ++i) n[i] = 0;
00985 }
00986 //END class ElementMap
00987 
00988 
00989 #include "component.moc"

Generated on Tue May 8 17:05:28 2007 for KTechLab by  doxygen 1.5.1