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

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