summaryrefslogtreecommitdiffstats
path: root/src/electronics/components/multiinputgate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/electronics/components/multiinputgate.cpp')
-rw-r--r--src/electronics/components/multiinputgate.cpp530
1 files changed, 530 insertions, 0 deletions
diff --git a/src/electronics/components/multiinputgate.cpp b/src/electronics/components/multiinputgate.cpp
new file mode 100644
index 0000000..7453845
--- /dev/null
+++ b/src/electronics/components/multiinputgate.cpp
@@ -0,0 +1,530 @@
+/***************************************************************************
+ * 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 "ecnode.h"
+#include "icndocument.h"
+#include "libraryitem.h"
+#include "multiinputgate.h"
+#include "logic.h"
+
+#include <cmath>
+#include <klocale.h>
+#include <qpainter.h>
+
+//BEGIN class MultiInputGate
+MultiInputGate::MultiInputGate( ICNDocument *icnDocument, bool newItem, const char *id, int baseWidth )
+ : Component( icnDocument, newItem, id )
+{
+ b_doneInit = false;
+ m_numInputs = 0;
+ if ( baseWidth == -1 ) {
+ baseWidth = 32;
+ }
+ m_baseWidth = baseWidth;
+
+ for ( int i=0; i<maxGateInput; ++i )
+ {
+ inLogic[i] = 0l;
+ inNode[i] = 0l;
+ }
+
+ updateInputs(2);
+
+ init1PinRight(16);
+ m_pOut = createLogicOut( m_pPNode[0], false );
+
+
+ createProperty( "numInput", Variant::Type::Int );
+ property("numInput")->setCaption( i18n("Number Inputs") );
+ property("numInput")->setMinValue(2);
+ property("numInput")->setMaxValue(maxGateInput);
+ property("numInput")->setValue(2);
+
+ b_doneInit = true;
+}
+
+
+MultiInputGate::~MultiInputGate()
+{
+}
+
+
+void MultiInputGate::dataChanged()
+{
+ updateInputs( QMIN( maxGateInput, dataInt("numInput") ) );
+}
+
+
+void MultiInputGate::updateInputs( int newNum )
+{
+ if ( newNum == m_numInputs ) {
+ return;
+ }
+
+ if ( newNum < 2 ) {
+ newNum = 2;
+ }
+ else if ( newNum > maxGateInput ) {
+ newNum = maxGateInput;
+ }
+
+ const int newWidth = m_baseWidth;
+
+ setSize( -newWidth/2, -8*newNum, newWidth, 16*newNum, true );
+
+ const bool added = ( newNum > m_numInputs );
+ if (added)
+ {
+ for ( int i = m_numInputs; i<newNum; ++i )
+ {
+ ECNode *node = createPin( 0, 0, 0, "in"+QString::number(i) );
+ inNode[i] = node;
+ inLogic[i] = createLogicIn(node);
+ inLogic[i]->setCallback( this, (CallbackPtr)(&MultiInputGate::inStateChanged) );
+ }
+ }
+ else
+ {
+ for ( int i=newNum; i<m_numInputs; ++i )
+ {
+ removeNode("in"+QString::number(i));
+ removeElement( inLogic[i], false );
+ inNode[i] = 0l;
+ inLogic[i] = 0l;
+ }
+ }
+
+ m_numInputs = newNum;
+
+ // We can't call a pure-virtual function if we haven't finished our constructor yet...
+ if (b_doneInit)
+ inStateChanged(!added);
+
+ updateAttachedPositioning();
+}
+
+
+void MultiInputGate::updateAttachedPositioning()
+{
+ // Check that our ndoes have been created before we attempt to use them
+ if ( !m_nodeMap.contains("p1") || !m_nodeMap.contains("in"+QString::number(m_numInputs-1)) )
+ return;
+
+ int _x = offsetX()+8;
+ int _y = offsetY()+8;
+
+ m_nodeMap["p1"].x = m_baseWidth/2 + 8;
+ m_nodeMap["p1"].y = 0;
+
+ for ( int i=0; i< m_numInputs; ++i )
+ {
+ m_nodeMap["in"+QString::number(i)].x = _x - 16;
+ m_nodeMap["in"+QString::number(i)].y = _y + 16*i;
+ }
+
+ if (b_doneInit)
+ Component::updateAttachedPositioning();
+}
+//END class MultiInputGate
+
+
+//BEGIN class ECXNor
+Item* ECXnor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECXnor( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECXnor::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/xnor"),
+ i18n("XNOR gate"),
+ i18n("Logic"),
+ "xnor.png",
+ LibraryItem::lit_component,
+ ECXnor::construct );
+}
+
+ECXnor::ECXnor( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, (id) ? id : "xnor", 48 )
+{
+ m_name = i18n("XNOR gate");
+ m_desc = i18n("Exclusive NOR gate. Output is low when exactly one input is high.");
+
+ inStateChanged(false);
+}
+
+ECXnor::~ECXnor()
+{
+}
+
+void ECXnor::inStateChanged(bool)
+{
+ int highCount = 0;
+ for ( int i=0; i<m_numInputs; ++i )
+ {
+ if ( inLogic[i]->isHigh() )
+ highCount++;
+ }
+
+ m_pOut->setHigh( highCount != 1 );
+}
+
+void ECXnor::drawShape( QPainter &p )
+{
+ initPainter(p);
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+
+ p.save();
+ p.setPen( Qt::NoPen );
+ p.drawChord( _x-width()+22, _y, 2*width()-28, height(), -16*81, 16*162 );
+ p.restore();
+
+ p.drawArc( _x-width()+22, _y, 2*width()-28, height(), -16*90, 16*180 );
+ p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
+ p.drawArc( _x, _y, 16, height(), -16*90, 16*180 );
+
+ p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
+
+ const int n = m_numInputs;
+ for ( int i=0; i<n; ++i )
+ {
+ p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
+ int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
+ p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
+ }
+
+ deinitPainter(p);
+}
+//END class ECXnor
+
+
+//BEGIN class ECXor
+Item* ECXor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECXor( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECXor::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/xor"),
+ i18n("XOR gate"),
+ i18n("Logic"),
+ "xor.png",
+ LibraryItem::lit_component,
+ ECXor::construct );
+}
+
+ECXor::ECXor( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, (id) ? id : "xor", 48 )
+{
+ m_name = i18n("XOR gate");
+ m_desc = i18n("Exclusive OR gate. Output is high when exactly one input is high.");
+
+ inStateChanged(false);
+}
+
+ECXor::~ECXor()
+{
+}
+
+void ECXor::inStateChanged(bool)
+{
+ int highCount = 0;
+ for ( int i=0; i<m_numInputs; ++i )
+ {
+ if ( inLogic[i]->isHigh() )
+ highCount++;
+ }
+
+ m_pOut->setHigh( highCount == 1 );
+}
+
+void ECXor::drawShape( QPainter &p )
+{
+ initPainter(p);
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+
+ p.save();
+ p.setPen( Qt::NoPen );
+ p.drawChord( _x-width()+16, _y, 2*width()-16, height(), -16*81, 16*162 );
+ p.restore();
+
+ p.drawArc( _x-width()+16, _y, 2*width()-16, height(), -16*90, 16*180 );
+ p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
+ p.drawArc( _x, _y, 16, height(), -16*90, 16*180 );
+
+ const int n = m_numInputs;
+ for ( int i=0; i<n; ++i )
+ {
+ p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
+ int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
+ p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
+ }
+
+ deinitPainter(p);
+}
+//END class ECXor
+
+
+//BEGIN class EXOr
+Item* ECOr::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECOr( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECOr::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/or"),
+ i18n("OR gate"),
+ i18n("Logic"),
+ "or.png",
+ LibraryItem::lit_component,
+ ECOr::construct );
+}
+
+ECOr::ECOr( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, (id) ? id : "or", 48 )
+{
+ m_name = i18n("OR gate");
+ m_desc = i18n("The output is high when at least one of the inputs is high; or low when all of the inputs are off");
+
+ inStateChanged(false);
+}
+
+ECOr::~ECOr()
+{
+}
+
+void ECOr::inStateChanged(bool)
+{
+ bool allLow = true;
+ for ( int i=0; i<m_numInputs && allLow; ++i )
+ {
+ if ( inLogic[i]->isHigh() )
+ allLow = false;
+ }
+
+ m_pOut->setHigh(!allLow);
+}
+
+void ECOr::drawShape( QPainter &p )
+{
+ initPainter(p);
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+
+ p.save();
+ p.setPen( Qt::NoPen );
+// p.setBrush( Qt::red );
+ p.drawChord( _x-width(), _y, 2*width(), height(), -16*81, 16*162 );
+// p.drawPie( _x-width()+16, _y, 2*width()-16, height(), -16*100, 16*200 );
+ p.restore();
+
+ p.drawArc( _x-width(), _y, 2*width(), height(), -16*90, 16*180 );
+ p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
+
+ const int n = m_numInputs;
+ for ( int i=0; i<n; ++i )
+ {
+ p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
+ int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
+ p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
+ }
+
+ deinitPainter(p);
+}
+//END class ECOr
+
+
+//BEGIN class ECNor
+Item* ECNor::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECNor( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECNor::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/nor"),
+ i18n("NOR gate"),
+ i18n("Logic"),
+ "nor.png",
+ LibraryItem::lit_component,
+ ECNor::construct );
+}
+
+ECNor::ECNor( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, (id) ? id : "nor", 48 )
+{
+ m_name = i18n("NOR Gate");
+ m_desc = i18n("The output is high when all inputs are low.");
+
+ inStateChanged(false);
+}
+
+ECNor::~ECNor()
+{
+}
+
+void ECNor::inStateChanged(bool)
+{
+ bool allLow = true;
+ for ( int i=0; i<m_numInputs && allLow; ++i )
+ {
+ if ( inLogic[i]->isHigh() )
+ allLow = false;
+ }
+
+ m_pOut->setHigh(allLow);
+}
+
+void ECNor::drawShape( QPainter &p )
+{
+ initPainter(p);
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+
+ p.save();
+ p.setPen( Qt::NoPen );
+ p.drawChord( _x-width()+6, _y, 2*width()-12, height(), -16*81, 16*162 );
+ p.restore();
+
+ p.drawArc( _x-width()+6, _y, 2*width()-12, height(), -16*90, 16*180 );
+ p.drawArc( _x-8, _y, 16, height(), -16*90, 16*180 );
+
+ p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
+
+ const int n = m_numInputs;
+ for ( int i=0; i<n; ++i )
+ {
+ p.setPen( inNode[i]->isSelected() ? m_selectedCol : Qt::black );
+ int pin_x = (int)std::sqrt((double)(64*n*n - (8*n-8-16*i)*(8*n-8-16*i)))/n;
+ p.drawLine( _x, _y+16*i+8, _x+pin_x, _y+16*i+8 );
+ }
+
+ deinitPainter(p);
+}
+//END class ECNor
+
+
+//BEGIN class ECNand
+Item* ECNand::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECNand( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECNand::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/nand"),
+ i18n("NAND gate"),
+ i18n("Logic"),
+ "nand.png",
+ LibraryItem::lit_component,
+ ECNand::construct );
+}
+
+ECNand::ECNand( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, id ? id : "nand" )
+{
+ m_name = i18n("NAND Gate");
+ m_desc = i18n("The output is low only when all of the inputs are high.");
+
+ inStateChanged(false);
+}
+
+ECNand::~ECNand()
+{
+}
+
+void ECNand::inStateChanged(bool)
+{
+ bool allHigh = true;
+ for ( int i=0; i<m_numInputs && allHigh; ++i )
+ {
+ if ( !inLogic[i]->isHigh() )
+ allHigh = false;
+ }
+
+ m_pOut->setHigh(!allHigh);
+}
+
+void ECNand::drawShape( QPainter &p )
+{
+ initPainter(p);
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+ p.drawChord( _x-width()+6, _y, 2*width()-12, height(), -16*90, 16*180 );
+ p.drawEllipse( _x+width()-6, _y+(height()/2)-3, 6, 6 );
+ deinitPainter(p);
+}
+//END class ECNand
+
+
+//BEGIN class ECAnd
+Item* ECAnd::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECAnd( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECAnd::libraryItem()
+{
+ QStringList idList;
+ idList << "ec/and" << "ec/and_2";
+ return new LibraryItem(
+ idList,
+ i18n("AND gate"),
+ i18n("Logic"),
+ "and.png",
+ LibraryItem::lit_component,
+ ECAnd::construct );
+}
+
+ECAnd::ECAnd( ICNDocument *icnDocument, bool newItem, const char *id )
+ : MultiInputGate( icnDocument, newItem, id ? id : "and" )
+{
+ m_name = i18n("AND Gate");
+ m_desc = i18n("The output is high if and only if all of the inputs are high.");
+
+ inStateChanged(false);
+}
+
+ECAnd::~ECAnd()
+{
+}
+
+void ECAnd::inStateChanged(bool)
+{
+ bool allHigh = true;
+ for ( int i=0; i<m_numInputs && allHigh; ++i )
+ {
+ if ( !inLogic[i]->isHigh() )
+ allHigh = false;
+ }
+
+ m_pOut->setHigh(allHigh);
+}
+
+void ECAnd::drawShape( QPainter &p )
+{
+ initPainter(p);
+
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+ p.drawChord( _x-width(), _y, 2*width(), height(), -16*90, 16*180 );
+
+ deinitPainter(p);
+}
+//END class ECAnd