You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktechlab/src/electronics/component.cpp

1018 lines
26 KiB

/***************************************************************************
* Copyright (C) 2004-2005 by David Saxton *
* david@bluehaze.org *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "canvasitemparts.h"
#include "circuitdocument.h"
#include "component.h"
#include "src/core/ktlconfig.h"
#include "ecnode.h"
#include "itemdocumentdata.h"
#include "node.h"
#include "pin.h"
#include "simulator.h"
#include "bjt.h"
#include "capacitance.h"
#include "cccs.h"
#include "ccvs.h"
#include "currentsignal.h"
#include "currentsource.h"
#include "diode.h"
#include "inductance.h"
#include "logic.h"
#include "opamp.h"
#include "resistance.h"
#include "switch.h"
#include "vccs.h"
#include "vcvs.h"
#include "voltagepoint.h"
#include "voltagesignal.h"
#include "voltagesource.h"
#include <cmath>
#include <kdebug.h>
#include <tqbitarray.h>
#include <tqpainter.h>
#include <tqwidget.h>
#include <tqwmatrix.h>
const int dipWidth = 112;
const int pairSep = 32;
// Degrees per radian
static const double DPR = 57.29577951308232087665461840231273527024;
Component::Component( ICNDocument *icnDocument, bool newItem, const TQString &id )
: CNItem( icnDocument, newItem, id ),
m_angleDegrees(0),
b_flipped(false)
{
m_pCircuitDocument = dynamic_cast<CircuitDocument*>(icnDocument);
for ( int i=0; i<4; ++i )
{
m_pPNode[i] = 0l;
m_pNNode[i] = 0l;
}
// Get configuration options
slotUpdateConfiguration();
// And finally register this :-)
icnDocument->registerItem(this);
}
Component::~Component()
{
removeElements();
Simulator::self()->detachComponent(this);
}
void Component::removeItem( )
{
if (b_deleted)
return;
Simulator::self()->detachComponent(this);
CNItem::removeItem();
}
void Component::removeElements( bool setPinsInterIndependent )
{
const ElementMapList::iterator end = m_elementMapList.end();
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
Element * e = (*it).e;
if (e)
{
emit elementDestroyed(e);
e->componentDeleted();
}
}
m_elementMapList.clear();
const SwitchList::iterator swEnd = m_switchList.end();
for ( SwitchList::iterator it = m_switchList.begin(); it != swEnd; ++it )
{
Switch * sw = *it;
if ( !sw )
continue;
emit switchDestroyed( sw );
delete sw;
}
m_switchList.clear();
if ( setPinsInterIndependent )
setAllPinsInterIndependent();
}
void Component::removeElement( Element * element, bool setPinsInterIndependent )
{
if (!element)
return;
emit elementDestroyed(element);
element->componentDeleted();
const ElementMapList::iterator end = m_elementMapList.end();
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; )
{
ElementMapList::iterator next = it;
++next;
if ( (*it).e == element )
m_elementMapList.remove(it);
it = next;
}
if ( setPinsInterIndependent )
rebuildPinInterDepedence();
}
void Component::removeSwitch( Switch * sw )
{
if ( !sw )
return;
emit switchDestroyed( sw );
delete sw;
m_switchList.remove(sw);
m_pCircuitDocument->requestAssignCircuits();
}
void Component::setNodalCurrents()
{
const ElementMapList::iterator end = m_elementMapList.end();
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
ElementMap m = (*it);
for ( int i=0; i<4; i++ )
{
if ( m.n[i] ) {
m.n[i]->mergeCurrent( m.e->m_cnodeI[i] );
}
}
}
}
void Component::initPainter( TQPainter &p )
{
CNItem::initPainter(p);
if ( !b_flipped && (m_angleDegrees%360 == 0) )
return;
p.save();
p.translate( int(x()), int(y()) );
if (b_flipped)
p.scale( -1, 1 );
p.rotate(m_angleDegrees);
p.translate( -int(x()), -int(y()) );
}
void Component::deinitPainter( TQPainter &p )
{
if ( !b_flipped && (m_angleDegrees%360 == 0) )
return;
p.restore();
}
void Component::setAngleDegrees( int degrees )
{
updateConnectorPoints(false);
m_angleDegrees = degrees;
itemPointsChanged();
updateAttachedPositioning();
p_icnDocument->requestRerouteInvalidatedConnectors();
}
void Component::setFlipped( bool flipped )
{
updateConnectorPoints(false);
b_flipped = flipped;
itemPointsChanged();
updateAttachedPositioning();
p_icnDocument->requestRerouteInvalidatedConnectors();
}
void Component::itemPointsChanged()
{
TQPointArray transformedPoints = transMatrix( m_angleDegrees, b_flipped, 0, 0, false ).map(m_itemPoints);
// transformedPoints.translate( int(x()), int(y()) );
setPoints(transformedPoints);
}
void Component::restoreFromItemData( const ItemData &itemData )
{
CNItem::restoreFromItemData(itemData);
setAngleDegrees( int(itemData.angleDegrees) );
setFlipped(itemData.flipped);
}
ItemData Component::itemData() const
{
ItemData itemData = CNItem::itemData();
itemData.angleDegrees = m_angleDegrees;
itemData.flipped = b_flipped;
return itemData;
}
TQWMatrix Component::transMatrix( int angleDegrees, bool flipped, int x, int y, bool inverse )
{
TQWMatrix m;
m.translate( x, y );
if (inverse)
{
m.rotate(-angleDegrees);
if (flipped)
m.scale( -1, 1 );
}
else
{
if (flipped)
m.scale( -1, 1 );
m.rotate(angleDegrees);
}
m.translate( -x, -y );
m.setTransformationMode( TQWMatrix::Areas );
return m;
}
void Component::finishedCreation()
{
CNItem::finishedCreation();
updateAttachedPositioning();
}
void Component::updateAttachedPositioning()
{
if (b_deleted || !m_bDoneCreation)
return;
//BEGIN Transform the nodes
const NodeMap::iterator end = m_nodeMap.end();
for ( NodeMap::iterator it = m_nodeMap.begin(); it != end; ++it )
{
if ( !it.data().node )
kdError() << k_funcinfo << "Node in nodemap is null" << endl;
else
{
int nx = int((std::cos(m_angleDegrees/DPR) * it.data().x) - (std::sin(m_angleDegrees/DPR) * it.data().y));
int ny = int((std::sin(m_angleDegrees/DPR) * it.data().x) + (std::cos(m_angleDegrees/DPR) * it.data().y));
if (b_flipped)
nx = -nx;
#define round_8(x) (((x) > 0) ? int(((x)+4)/8)*8 : int(((x)-4)/8)*8)
nx = round_8(nx);
ny = round_8(ny);
#undef round_8
int newDir = (((m_angleDegrees + it.data().orientation)%360)+360)%360;
if (b_flipped)
newDir = (((180-newDir)%360)+360)%360;
it.data().node->move( nx+x(), ny+y() );
it.data().node->setOrientation( (Node::node_dir)newDir );
}
}
//END Transform the nodes
//BEGIN Transform the GuiParts
TQWMatrix m;
if (b_flipped)
m.scale( -1, 1 );
m.rotate(m_angleDegrees);
m.setTransformationMode( TQWMatrix::Areas );
const TextMap::iterator textMapEnd = m_textMap.end();
for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
{
TQRect newPos = m.mapRect( it.data()->recommendedRect() );
it.data()->move( newPos.x() + x(), newPos.y() + y() );
it.data()->setGuiPartSize( newPos.width(), newPos.height() );
it.data()->setAngleDegrees(m_angleDegrees);
}
const WidgetMap::iterator widgetMapEnd = m_widgetMap.end();
for ( WidgetMap::iterator it = m_widgetMap.begin(); it != widgetMapEnd; ++it )
{
TQRect newPos = m.mapRect( it.data()->recommendedRect() );
it.data()->move( newPos.x() + x(), newPos.y() + y() );
it.data()->setGuiPartSize( newPos.width(), newPos.height() );
it.data()->setAngleDegrees(m_angleDegrees);
}
//END Transform the GuiParts
}
void Component::drawPortShape( TQPainter & p )
{
int h = height();
int w = width() - 1;
int _x = int( x() + offsetX() );
int _y = int( y() + offsetY() );
double roundSize = 8;
double slantIndent = 8;
const double pi = 3.1415926536;
const double DPR = 180./pi;
double inner = std::atan(h/slantIndent); // Angle for slight corner
double outer = pi-inner; // Angle for sharp corner
int inner16 = int(16*inner*DPR);
int outer16 = int(16*outer*DPR);
p.save();
p.setPen( TQt::NoPen );
p.drawPolygon( areaPoints() );
p.restore();
initPainter( p );
// Left line
p.drawLine( int(_x), int(_y+roundSize/2), int(_x), int(_y+h-roundSize/2) );
// Right line
p.drawLine( int(_x+w), int(_y-slantIndent+h-roundSize/2), int(_x+w), int(_y+slantIndent+roundSize/2) );
// Bottom line
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)) );
// Top line
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)) );
// Top left
p.drawArc( int(_x), int(_y), int(roundSize), int(roundSize), 90*16, outer16 );
// Bottom left
p.drawArc( int(_x), int(_y+h-roundSize), int(roundSize), int(roundSize), 180*16, outer16 );
// Top right
p.drawArc( int(_x+w-roundSize), int(_y+slantIndent), int(roundSize), int(roundSize), 0, inner16 );
// Bottom right
p.drawArc( int(_x+w-roundSize), int(_y-slantIndent+h-roundSize), int(roundSize), int(roundSize), 270*16, inner16 );
deinitPainter( p );
}
void Component::initDIP( const TQStringList & pins )
{
const int numPins = pins.size();
const int numSide = numPins/2 + numPins%2;
// Pins along left
for ( int i=0; i<numSide; i++ )
{
if ( !pins[i].isEmpty() )
{
const int nodeX = -8+offsetX();
const int nodeY = (i+1)*16+offsetY();
ECNode *node = ecNodeWithID(pins[i]);
if (node)
{
m_nodeMap[pins[i]].x = nodeX;
m_nodeMap[pins[i]].y = nodeY;
m_nodeMap[pins[i]].orientation = (Node::node_dir)0;
}
else
createPin( nodeX, nodeY, 0, pins[i] );
}
}
// Pins along right
for ( int i=numSide; i<numPins; i++ )
{
if ( !pins[i].isEmpty() )
{
const int nodeX = width()+8+offsetX();
const int nodeY = (2*numSide-i)*16+offsetY();
ECNode *node = ecNodeWithID(pins[i]);
if (node)
{
m_nodeMap[pins[i]].x = nodeX;
m_nodeMap[pins[i]].y = nodeY;
m_nodeMap[pins[i]].orientation = (Node::node_dir)180;
}
else
createPin( nodeX, nodeY, 180, pins[i] );
}
}
updateAttachedPositioning();
}
void Component::initDIPSymbol( const TQStringList & pins, int _width )
{
const int numPins = pins.size();
const int numSide = numPins/2 + numPins%2;
setSize( -(_width-(_width%16))/2, -(numSide+1)*8, _width, (numSide+1)*16, true );
TQWidget tmpWidget;
TQPainter p(&tmpWidget);
p.setFont(m_font);
// Pins along left
for ( int i=0; i<numSide; i++ )
{
if ( !pins[i].isEmpty() )
{
const TQString text = *pins.at(i);
const int _top = (i+1)*16-8 + offsetY();
const int _width = width()/2 - 6;
const int _left = 6 + offsetX();
const int _height = 16;
TQRect br = p.boundingRect( TQRect( _left, _top, _width, _height ), TQt::AlignLeft, text );
addDisplayText( text, br, text );
}
}
// Pins along right
for ( int i=numSide; i<numPins; i++ )
{
if ( !pins[i].isEmpty() )
{
const TQString text = *pins.at(i);
const int _top = (2*numSide-i)*16 - 8 + offsetY();
const int _width = width()/2 - 6;
const int _left = (width()/2) + offsetX();
const int _height = 16;
TQRect br = p.boundingRect( TQRect( _left, _top, _width, _height ), TQt::AlignRight, text );
addDisplayText( text, br, text );
}
}
updateAttachedPositioning();
}
// TQString createNode( double _x, double _y, int shape, int orientation, const TQString &name, int type, bool isInput = true );
void Component::init1PinLeft( int h1 )
{
if ( h1 == -1 ) h1 = offsetY()+height()/2;
m_pNNode[0] = createPin( offsetX()-8, h1, 0, "n1" );
}
void Component::init2PinLeft( int h1, int h2 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+height()-8;
m_pNNode[0] = createPin( offsetX()-8, h1, 0, "n1" );
m_pNNode[1] = createPin( offsetX()-8, h2, 0, "n2" );
}
void Component::init3PinLeft( int h1, int h2, int h3 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+height()/2;
if ( h3 == -1 ) h3 = offsetY()+height()-8;
m_pNNode[0] = createPin( offsetX()-8, h1, 0, "n1" );
m_pNNode[1] = createPin( offsetX()-8, h2, 0, "n2" );
m_pNNode[2] = createPin( offsetX()-8, h3, 0, "n3" );
}
void Component::init4PinLeft( int h1, int h2, int h3, int h4 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+24;
if ( h3 == -1 ) h3 = offsetY()+height()-24;
if ( h4 == -1 ) h4 = offsetY()+height()-8;
m_pNNode[0] = createPin( offsetX()-8, h1, 0, "n1" );
m_pNNode[1] = createPin( offsetX()-8, h2, 0, "n2" );
m_pNNode[2] = createPin( offsetX()-8, h3, 0, "n3" );
m_pNNode[3] = createPin( offsetX()-8, h4, 0, "n4" );
}
void Component::init1PinRight( int h1 )
{
if ( h1 == -1 ) h1 = offsetY()+height()/2;
m_pPNode[0] = createPin( offsetX()+width()+8, h1, 180, "p1" );
}
void Component::init2PinRight( int h1, int h2 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+height()-8;
m_pPNode[0] = createPin( offsetX()+width()+8, h1, 180, "p1" );
m_pPNode[1] = createPin( offsetX()+width()+8, h2, 180, "p2" );
}
void Component::init3PinRight( int h1, int h2, int h3 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+height()/2;
if ( h3 == -1 ) h3 = offsetY()+height()-8;
m_pPNode[0] = createPin( offsetX()+width()+8, h1, 180, "p1" );
m_pPNode[1] = createPin( offsetX()+width()+8, h2, 180, "p2" );
m_pPNode[2] = createPin( offsetX()+width()+8, h3, 180, "p3" );
}
void Component::init4PinRight( int h1, int h2, int h3, int h4 )
{
if ( h1 == -1 ) h1 = offsetY()+8;
if ( h2 == -1 ) h2 = offsetY()+24;
if ( h3 == -1 ) h3 = offsetY()+height()-24;
if ( h4 == -1 ) h4 = offsetY()+height()-8;
m_pPNode[0] = createPin( offsetX()+width()+8, h1, 180, "p1" );
m_pPNode[1] = createPin( offsetX()+width()+8, h2, 180, "p2" );
m_pPNode[2] = createPin( offsetX()+width()+8, h3, 180, "p3" );
m_pPNode[3] = createPin( offsetX()+width()+8, h4, 180, "p4" );
}
ECNode* Component::ecNodeWithID( const TQString &ecNodeId )
{
return dynamic_cast<ECNode*>( p_icnDocument->nodeWithID( nodeId(ecNodeId) ) );
}
void Component::slotUpdateConfiguration()
{
const LogicConfig logicConfig = LogicIn::getConfig();
const ElementMapList::iterator end = m_elementMapList.end();
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
if ( LogicIn * logicIn = dynamic_cast<LogicIn*>((*it).e) )
logicIn->setLogic(logicConfig);
}
}
BJT * Component::createBJT( ECNode *c, ECNode *b, ECNode *e, bool isNPN )
{ return createBJT( c->pin(), b->pin(), e->pin(), isNPN ); }
Capacitance * Component::createCapacitance( ECNode *n0, ECNode *n1, double capacitance )
{ return createCapacitance( n0->pin(), n1->pin(), capacitance ); }
CCCS * Component::createCCCS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createCCCS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
CCVS * Component::createCCVS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createCCVS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
CurrentSignal * Component::createCurrentSignal( ECNode *n0, ECNode *n1, double current )
{ return createCurrentSignal( n0->pin(), n1->pin(), current ); }
CurrentSource * Component::createCurrentSource( ECNode *n0, ECNode *n1, double current )
{ return createCurrentSource( n0->pin(), n1->pin(), current ); }
Diode * Component::createDiode( ECNode *n0, ECNode *n1 )
{ return createDiode( n0->pin(), n1->pin() ); }
Inductance * Component::createInductance( ECNode *n0, ECNode *n1, double inductance )
{ return createInductance( n0->pin(), n1->pin(), inductance ); }
LogicIn * Component::createLogicIn( ECNode *node )
{ return createLogicIn( node->pin() ); }
LogicOut * Component::createLogicOut( ECNode *node, bool isHigh )
{ return createLogicOut( node->pin(), isHigh ); }
OpAmp * Component::createOpAmp( ECNode * nonInverting, ECNode * out, ECNode * inverting )
{ return createOpAmp( nonInverting->pin(), out->pin(), inverting->pin() ); }
Resistance * Component::createResistance( ECNode *n0, ECNode *n1, double resistance )
{ return createResistance( n0->pin(), n1->pin(), resistance ); }
Switch * Component::createSwitch( ECNode *n0, ECNode *n1, bool open )
{ return createSwitch( n0->pin(), n1->pin(), open ); }
VCCS * Component::createVCCS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createVCCS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
VCVS * Component::createVCVS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createVCVS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
VoltagePoint * Component::createVoltagePoint( ECNode *n0, double voltage )
{ return createVoltagePoint( n0->pin(), voltage ); }
VoltageSignal * Component::createVoltageSignal( ECNode *n0, ECNode *n1, double voltage )
{ return createVoltageSignal( n0->pin(), n1->pin(), voltage ); }
VoltageSource * Component::createVoltageSource( ECNode *n0, ECNode *n1, double voltage )
{ return createVoltageSource( n0->pin(), n1->pin(), voltage ); }
BJT* Component::createBJT( Pin *cN, Pin *bN, Pin *eN, bool isNPN )
{
BJT *e = new BJT(isNPN);
TQValueList<Pin*> pins;
pins << bN << cN << eN;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
Capacitance* Component::createCapacitance( Pin *n0, Pin *n1, double capacitance )
{
Capacitance *e = new Capacitance( capacitance, 1./LINEAR_UPDATE_RATE );
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
CCCS* Component::createCCCS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
CCCS *e = new CCCS(gain);
TQValueList<Pin*> pins;
pins << n0 << n1 << n2 << n3;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
CCVS* Component::createCCVS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
CCVS *e = new CCVS(gain);
TQValueList<Pin*> pins;
pins << n0 << n1 << n2 << n3;
ElementMapList::iterator it = handleElement( e, pins );
setInterCircuitDependent( it, pins );
pins.clear();
pins << n0 << n1;
setInterGroundDependent( it, pins );
pins.clear();
pins << n2 << n3;
setInterGroundDependent( it, pins );
return e;
}
CurrentSignal* Component::createCurrentSignal( Pin *n0, Pin *n1, double current )
{
CurrentSignal *e = new CurrentSignal( 1./LINEAR_UPDATE_RATE, current );
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
CurrentSource* Component::createCurrentSource( Pin *n0, Pin *n1, double current )
{
CurrentSource *e = new CurrentSource(current);
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
Diode* Component::createDiode( Pin *n0, Pin *n1 )
{
Diode *e = new Diode();
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
Inductance* Component::createInductance( Pin *n0, Pin *n1, double inductance )
{
Inductance *e = new Inductance( inductance, 1./LINEAR_UPDATE_RATE );
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
LogicIn *Component::createLogicIn( Pin *node )
{
LogicIn *e = new LogicIn(LogicIn::getConfig());
TQValueList<Pin*> pins;
pins << node;
ElementMapList::iterator it = handleElement( e, pins );
return e;
}
LogicOut *Component::createLogicOut( Pin *node, bool isHigh )
{
LogicOut *e = new LogicOut( LogicIn::getConfig(), isHigh);
TQValueList<Pin*> pins;
pins << node;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
OpAmp * Component::createOpAmp( Pin * nonInverting, Pin * inverting, Pin * out )
{
OpAmp * e = new OpAmp();
TQValueList<Pin*> pins;
pins << nonInverting << inverting << out;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
Resistance* Component::createResistance( Pin *n0, Pin *n1, double resistance )
{
Resistance *e = new Resistance(resistance);
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
Switch* Component::createSwitch( Pin *n0, Pin *n1, bool open )
{
// Note that a Switch is not really an element (although in many cases it
// behaves very much like one).
Switch * e = new Switch( this, n0, n1, open ? Switch::Open : Switch::Closed );
m_switchList.append(e);
n0->addSwitch( e );
n1->addSwitch( e );
emit switchCreated( e );
return e;
}
VCCS* Component::createVCCS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
VCCS *e = new VCCS(gain);
TQValueList<Pin*> pins;
pins << n0 << n1 << n2 << n3;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
VCVS* Component::createVCVS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
VCVS *e = new VCVS(gain);
TQValueList<Pin*> pins;
pins << n0 << n1 << n2 << n3;
ElementMapList::iterator it = handleElement( e, pins );
setInterCircuitDependent( it, pins );
pins.clear();
pins << n0 << n1;
setInterGroundDependent( it, pins );
pins.clear();
pins << n2 << n3;
setInterGroundDependent( it, pins );
return e;
}
VoltagePoint* Component::createVoltagePoint( Pin *n0, double voltage )
{
VoltagePoint *e = new VoltagePoint(voltage);
TQValueList<Pin*> pins;
pins << n0;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
VoltageSignal* Component::createVoltageSignal( Pin *n0, Pin *n1, double voltage )
{
VoltageSignal *e = new VoltageSignal( 1./LINEAR_UPDATE_RATE, voltage );
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
VoltageSource* Component::createVoltageSource( Pin *n0, Pin *n1, double voltage )
{
VoltageSource *e = new VoltageSource(voltage);
TQValueList<Pin*> pins;
pins << n0 << n1;
ElementMapList::iterator it = handleElement( e, pins );
setInterDependent( it, pins );
return e;
}
ElementMapList::iterator Component::handleElement( Element *e, const TQValueList<Pin*> & pins )
{
if (!e)
return m_elementMapList.end();
ElementMap em;
em.e = e;
int at = 0;
TQValueList<Pin*>::ConstIterator end = pins.end();
for ( TQValueList<Pin*>::ConstIterator it = pins.begin(); it != end; ++it )
{
(*it)->addElement(e);
em.n[at++] = *it;
}
ElementMapList::iterator it = m_elementMapList.append(em);
emit elementCreated(e);
return it;
}
void Component::setInterDependent( ElementMapList::iterator it, const TQValueList<Pin*> & pins )
{
setInterCircuitDependent( it, pins );
setInterGroundDependent( it, pins );
}
void Component::setInterCircuitDependent( ElementMapList::iterator it, const TQValueList<Pin*> & pins )
{
TQValueList<Pin*>::ConstIterator end = pins.end();
for ( TQValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1 )
{
for ( TQValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2 )
{
(*it1)->addCircuitDependentPin( *it2 );
}
}
(*it).interCircuitDependent.append( pins );
}
void Component::setInterGroundDependent( ElementMapList::iterator it, const TQValueList<Pin*> & pins )
{
TQValueList<Pin*>::ConstIterator end = pins.end();
for ( TQValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1 )
{
for ( TQValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2 )
{
(*it1)->addGroundDependentPin( *it2 );
}
}
(*it).interGroundDependent.append( pins );
}
void Component::rebuildPinInterDepedence()
{
setAllPinsInterIndependent();
// Rebuild dependencies
ElementMapList::iterator emlEnd = m_elementMapList.end();
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != emlEnd; ++it )
{
// Many copies of the pin lists as these will be affected when we call setInter*Dependent
PinListList list = (*it).interCircuitDependent;
PinListList::iterator depEnd = list.end();
for ( PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt )
setInterCircuitDependent( it, *depIt );
list = (*it).interGroundDependent;
depEnd = list.end();
for ( PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt )
setInterGroundDependent( it, *depIt );
}
}
void Component::setAllPinsInterIndependent()
{
NodeMap::iterator nmEnd = m_nodeMap.end();
for ( NodeMap::iterator it = m_nodeMap.begin(); it != nmEnd; ++it )
{
PinVector pins = (static_cast<ECNode*>(it.data().node))->pins();
PinVector::iterator pinsEnd = pins.end();
for ( PinVector::iterator pinsIt = pins.begin(); pinsIt != pinsEnd; ++pinsIt )
{
if ( *pinsIt )
(*pinsIt)->removeDependentPins();
}
}
}
void Component::initElements( const uint stage )
{
/// @todo this function is ugly and messy and needs tidying up
const ElementMapList::iterator end = m_elementMapList.end();
if ( stage == 1 )
{
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
(*it).e->add_initial_dc();
}
return;
}
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
ElementMap m = (*it);
if ( m.n[3] ) {
m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId(), m.n[3]->eqId() );
}
else if ( m.n[2] ) {
m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId() );
}
else if ( m.n[1] ) {
m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId() );
}
else if ( m.n[0] ) {
m.e->setCNodes( m.n[0]->eqId() );
}
}
for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
{
(*it).e->add_map();
}
}
ECNode * Component::createPin( double x, double y, int orientation, const TQString & name )
{
return dynamic_cast<ECNode*>( createNode( x, y, orientation, name, Node::ec_pin ) );
}
//BEGIN class ElementMap
ElementMap::ElementMap()
{
e = 0;
for ( int i = 0; i < 4; ++i )
n[i] = 0;
}
//END class ElementMap
#include "component.moc"