File indexing completed on 2024-04-28 13:39:06
0001 /*************************************************************************** 0002 * Copyright (C) 2003 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 #ifndef COMPONENT_H 0012 #define COMPONENT_H 0013 0014 #include "circuitdocument.h" 0015 #include "cnitem.h" 0016 0017 #include <QList> 0018 0019 class ICNDocument; 0020 class CircuitDocument; 0021 class ECNode; 0022 class ECSubcircuit; 0023 class Element; 0024 class Node; 0025 class Pin; 0026 0027 class BJT; 0028 class Capacitance; 0029 class CCCS; 0030 class CCVS; 0031 class CurrentSignal; 0032 class CurrentSource; 0033 class Diode; 0034 class JFET; 0035 class Inductance; 0036 class LogicIn; 0037 class LogicOut; 0038 class MOSFET; 0039 class OpAmp; 0040 class Resistance; 0041 class Switch; 0042 class Transformer; 0043 class VCCS; 0044 class VCVS; 0045 class VoltagePoint; 0046 class VoltageSignal; 0047 class VoltageSource; 0048 0049 typedef QList<ECNode *> ECNodeList; 0050 typedef QList<Element *> ElementList; 0051 typedef QList<Switch *> SwitchList; 0052 0053 typedef QList<QList<Pin *>> PinListList; 0054 0055 /** 0056 Contains vital information about the elements in the component. 0057 */ 0058 class ElementMap 0059 { 0060 public: 0061 ElementMap(); 0062 0063 Element *e; // The element 0064 Pin *n[4]; // The Pins associated with the CNodes in the element 0065 0066 /// @see Component::setInterCircuitDependent 0067 PinListList interCircuitDependent; 0068 0069 /// @see Component::setInterGroundDependent 0070 PinListList interGroundDependent; 0071 }; 0072 0073 typedef QList<ElementMap> ElementMapList; 0074 0075 /** 0076 @short Base class for all electrical components 0077 @author David Saxton 0078 */ 0079 class Component : public CNItem 0080 { 0081 Q_OBJECT 0082 public: 0083 Component(ICNDocument *icnDocument, bool newItem, const QString &id); 0084 ~Component() override; 0085 0086 ECNode *createPin(double _x, double _y, int orientation, const QString &name); 0087 /** 0088 * Converts the voltage level to a colour - this is used in drawing 0089 * wires and pins. 0090 */ 0091 static QColor voltageColor(double v); 0092 /** 0093 * @return a value between 0.0 and 1.0, representing a scaled version of 0094 * the absolute value of the voltage. 0095 * @see voltageColor 0096 */ 0097 static double voltageLength(double v); 0098 /** 0099 * Angle of orientation 0100 */ 0101 int angleDegrees() const 0102 { 0103 return m_angleDegrees; 0104 } 0105 /** 0106 * Sets the angle (in degrees) 0107 */ 0108 void setAngleDegrees(int degrees); 0109 /** 0110 * Whether or not the item is flipped 0111 */ 0112 bool flipped() const 0113 { 0114 return b_flipped; 0115 } 0116 /** 0117 * Sets whether or not the item is flipped 0118 */ 0119 void setFlipped(bool flipped); 0120 /** 0121 * After calculating nodal voltages, each component will be 0122 * called to tell its nodes what the current flowing *into* 0123 * the component is. 0124 */ 0125 void setNodalCurrents(); 0126 /** 0127 * @return pointer to the CircuitDocument that we're in. 0128 */ 0129 CircuitDocument *circuitDocument() const 0130 { 0131 return m_pCircuitDocument; 0132 } 0133 void initElements(const uint stage); 0134 void finishedCreation() override; 0135 /** 0136 * If reinherit (and use) the stepNonLogic function, then you must also 0137 * reinherit this function so that it returns true. Else your component 0138 * will not get called. 0139 */ 0140 virtual bool doesStepNonLogic() const 0141 { 0142 return false; 0143 } 0144 virtual void stepNonLogic() {}; 0145 /** 0146 * Returns the translation matrix used for painting et al 0147 * @param angleDegrees The orientation to use 0148 * @param x x co-ordinate of the center of the object to be mapped 0149 * @param y y co-ordinate of the center of the object to be mapped 0150 * @param inverse If false, maps the unrotated item to a rotated one, else mapped->unmapped 0151 */ 0152 static QTransform transMatrix(int angleDegrees, bool flipped, int x, int y, bool inverse = false); 0153 /** 0154 * @return Information about the component in an ItemData struct. 0155 */ 0156 ItemData itemData() const override; 0157 /** 0158 * Restores the state of the component from the ItemData struct. 0159 */ 0160 void restoreFromItemData(const ItemData &itemData) override; 0161 0162 BJT *createBJT(Pin *c, Pin *b, Pin *e, bool isNPN = true); 0163 BJT *createBJT(ECNode *c, ECNode *b, ECNode *e, bool isNPN = true); 0164 0165 Capacitance *createCapacitance(Pin *n0, Pin *n1, double capacitance); 0166 Capacitance *createCapacitance(ECNode *n0, ECNode *n1, double capacitance); 0167 0168 CCCS *createCCCS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain); 0169 CCCS *createCCCS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain); 0170 0171 CCVS *createCCVS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain); 0172 CCVS *createCCVS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain); 0173 0174 CurrentSignal *createCurrentSignal(Pin *n0, Pin *n1, double current); 0175 CurrentSignal *createCurrentSignal(ECNode *n0, ECNode *n1, double current); 0176 0177 CurrentSource *createCurrentSource(Pin *n0, Pin *n1, double current); 0178 CurrentSource *createCurrentSource(ECNode *n0, ECNode *n1, double current); 0179 0180 Diode *createDiode(Pin *n0, Pin *n1); 0181 Diode *createDiode(ECNode *n0, ECNode *n1); 0182 0183 JFET *createJFET(Pin *D, Pin *G, Pin *S, int JFET_type); 0184 JFET *createJFET(ECNode *D, ECNode *G, ECNode *S, int JFET_type); 0185 0186 Inductance *createInductance(Pin *n0, Pin *n1, double inductance); 0187 Inductance *createInductance(ECNode *n0, ECNode *n1, double inductance); 0188 0189 LogicIn *createLogicIn(Pin *node); 0190 LogicIn *createLogicIn(ECNode *node); 0191 0192 LogicOut *createLogicOut(Pin *node, bool isHigh); 0193 LogicOut *createLogicOut(ECNode *node, bool isHigh); 0194 0195 MOSFET *createMOSFET(Pin *D, Pin *G, Pin *S, Pin *B, int MOSFET_type); 0196 MOSFET *createMOSFET(ECNode *D, ECNode *G, ECNode *S, ECNode *B, int MOSFET_type); 0197 0198 OpAmp *createOpAmp(Pin *nonInverting, Pin *out, Pin *inverting); 0199 OpAmp *createOpAmp(ECNode *nonInverting, ECNode *out, ECNode *inverting); 0200 0201 Resistance *createResistance(Pin *n0, Pin *n1, double resistance); 0202 Resistance *createResistance(ECNode *n0, ECNode *n1, double resistance); 0203 0204 Switch *createSwitch(Pin *n0, Pin *n1, bool open); 0205 Switch *createSwitch(ECNode *n0, ECNode *n1, bool open); 0206 0207 VCCS *createVCCS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain); 0208 VCCS *createVCCS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain); 0209 0210 VCVS *createVCVS(Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain); 0211 VCVS *createVCVS(ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain); 0212 0213 VoltagePoint *createVoltagePoint(Pin *n0, double voltage); 0214 VoltagePoint *createVoltagePoint(ECNode *n0, double voltage); 0215 0216 VoltageSignal *createVoltageSignal(Pin *n0, Pin *n1, double voltage); 0217 VoltageSignal *createVoltageSignal(ECNode *n0, ECNode *n1, double voltage); 0218 0219 VoltageSource *createVoltageSource(Pin *n0, Pin *n1, double voltage); 0220 VoltageSource *createVoltageSource(ECNode *n0, ECNode *n1, double voltage); 0221 0222 ECNode *ecNodeWithID(const QString &ecNodeId); 0223 0224 /** 0225 * Safely delete an element - in this case, calls element->componentDeleted, 0226 * and removes it from the element list. 0227 * @param setPinsInterIndependent whether to call 0228 * setPinsInterIndependent. The call is time-consuming, and unnecessary 0229 * if the pins from which the element was originally attached will be/ 0230 * were removed, or they will become interdependent again. 0231 */ 0232 void removeElement(Element *element, bool setPinsInterIndependent); 0233 /** 0234 * Safely remove a switch. 0235 */ 0236 void removeSwitch(Switch *sw); 0237 /** 0238 * Removes all elements and switches. 0239 * @param setPinsInterIndependent whether to bother calling 0240 * setPinsInterIndependent. This is false when calling from the 0241 * destructor, or when the dependency information is the same. 0242 */ 0243 void removeElements(bool setPinsInterIndependent = false); 0244 /** 0245 * @return the list of switches that this component uses. 0246 */ 0247 SwitchList switchList() const 0248 { 0249 return m_switchList; 0250 } 0251 0252 signals: 0253 /** 0254 * Emitted when an element is created. 0255 */ 0256 void elementCreated(Element *element); 0257 /** 0258 * Emitted when an element is destroyed. 0259 */ 0260 void elementDestroyed(Element *element); 0261 /** 0262 * Emitted when a switch. is created 0263 */ 0264 void switchCreated(Switch *sw); 0265 /** 0266 * Emitted when a switch is destroyed. 0267 */ 0268 void switchDestroyed(Switch *sw); 0269 0270 public slots: 0271 virtual void slotUpdateConfiguration(); 0272 void removeItem() override; 0273 0274 protected: 0275 /** 0276 * Convenience functionality provided for components in a port shape 0277 * (such as ParallelPortComponent and SerialPortComponent). 0278 */ 0279 void drawPortShape(QPainter &p); 0280 void itemPointsChanged() override; 0281 void updateAttachedPositioning() override; 0282 void initPainter(QPainter &p) override; 0283 /** 0284 * Untranforms the painter from the matrix. This *must* be called after doing 0285 * initPainter( QPainter &p ); 0286 */ 0287 virtual void deinitPainter(QPainter &p); 0288 /** 0289 * This creates a set of nodes with their internal IDs set to those in QStringList pins. 0290 * The pins are in a DIP arrangement, and are spaced width() apart. 0291 */ 0292 void initDIP(const QStringList &pins); 0293 /** 0294 * Creates the DIP symbol: 0295 * @li constructs rectangular shape 0296 * @li puts on text labels in appropriate positions from QStringList pins 0297 */ 0298 void initDIPSymbol(const QStringList &pins, int width); 0299 /** 0300 * Create 1 pin on the left of the component, placed half way down if h1 is 0301 * -1 - else at the position of h1. 0302 */ 0303 void init1PinLeft(int h1 = -1); 0304 /** 0305 * Create 2 pins on the left of the component, either spread out, or at the 0306 * given heights. 0307 */ 0308 void init2PinLeft(int h1 = -1, int h2 = -1); 0309 /** 0310 * Create 3 pins on the left of the component, either spread out, or at the 0311 * given heights. 0312 */ 0313 void init3PinLeft(int h1 = -1, int h2 = -1, int h3 = -1); 0314 /** 0315 * Create 4 pins on the left of the component, either spread out, or at the 0316 * given heights. 0317 */ 0318 void init4PinLeft(int h1 = -1, int h2 = -1, int h3 = -1, int h4 = -1); 0319 /** 0320 * Create 1 pin on the right of the component, placed half way down if h1 is 0321 * -1 - else at the position of h1. 0322 */ 0323 void init1PinRight(int h1 = -1); 0324 /** 0325 * Create 2 pins on the right of the component, either spread out, or at the 0326 * given heights. 0327 */ 0328 void init2PinRight(int h1 = -1, int h2 = -1); 0329 /** 0330 * Create 3 pins on the right of the component, either spread out, or at the 0331 * given heights. 0332 */ 0333 void init3PinRight(int h1 = -1, int h2 = -1, int h3 = -1); 0334 /** 0335 * Create 4 pins on the right of the component, either spread out, or at the 0336 * given heights. 0337 */ 0338 void init4PinRight(int h1 = -1, int h2 = -1, int h3 = -1, int h4 = -1); 0339 /** 0340 * When we remove an element, we have to rebuild the list of inter-dependent 0341 * nodes. (when adding elements, we just call setInterDependent). 0342 */ 0343 void rebuildPinInterDepedence(); 0344 0345 // Pointers to commonly used nodes 0346 // TODO: why do we have two sets of these? 0347 ECNode *m_pPNode[4]; 0348 ECNode *m_pNNode[4]; 0349 0350 // TODO: only Switch cares about this, so either demote it to a member of class switch or 0351 // refactor it out alltogether. 0352 QPointer<CircuitDocument> m_pCircuitDocument; 0353 int m_angleDegrees; 0354 bool b_flipped; 0355 0356 private: 0357 /** 0358 * Convenience function for calling both setInterCircuitDependent and 0359 * setInterGroundDependent. 0360 * @param it Which pins are inter-dependent needs to be recorded in case 0361 * this information is later needed in rebuildPinInterDependence. 0362 */ 0363 void setInterDependent(ElementMapList::iterator it, const QList<Pin *> &pins); 0364 /** 0365 * Sets all pins independent of each other. 0366 */ 0367 void setAllPinsInterIndependent(); 0368 /** 0369 * The given pins will affect the simulation of each other. Therefore, they 0370 * will need to be simulated in the same circuit. 0371 */ 0372 void setInterCircuitDependent(ElementMapList::iterator it, const QList<Pin *> &pins); 0373 /** 0374 * If any of the given pins are ground, then that will affect whether 0375 * any of the other pins can be ground. 0376 */ 0377 void setInterGroundDependent(ElementMapList::iterator it, const QList<Pin *> &pins); 0378 /** 0379 * List of ElementMaps; which contain information on the pins associated 0380 * with the element as well as the dependence between the pins for that 0381 * element. 0382 * @see ElementMap 0383 */ 0384 ElementMapList m_elementMapList; 0385 /** 0386 * The switches used by the component. 0387 TODO: ammend this comment with a more complete justification for the design decision to put this here. 0388 */ 0389 SwitchList m_switchList; 0390 /** 0391 * @return an iterator to the element in m_elementMapList 0392 */ 0393 ElementMapList::iterator handleElement(Element *e, const QList<Pin *> &pins); 0394 }; 0395 0396 #endif