File indexing completed on 2024-05-05 05:46:07

0001 /***************************************************************************
0002  *   Copyright (C) 2004-2005 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 #include "multiplexer.h"
0012 
0013 #include "libraryitem.h"
0014 #include "logic.h"
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <cmath>
0019 
0020 void Multiplexer_inStateChanged(void *objV, bool state) {
0021     Multiplexer *objT = static_cast<Multiplexer*>(objV);
0022     objT->inStateChanged(state);
0023 }
0024 
0025 Item *Multiplexer::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0026 {
0027     return new Multiplexer(static_cast<ICNDocument *>(itemDocument), newItem, id);
0028 }
0029 
0030 LibraryItem *Multiplexer::libraryItem()
0031 {
0032     return new LibraryItem(QStringList(QString("ec/multiplexer")), i18n("Multiplexer"), i18n("Integrated Circuits"), "ic1.png", LibraryItem::lit_component, Multiplexer::construct);
0033 }
0034 
0035 Multiplexer::Multiplexer(ICNDocument *icnDocument, bool newItem, const char *id)
0036     : Component(icnDocument, newItem, id ? id : "multiplexer")
0037 {
0038     m_name = i18n("Multiplexer");
0039 
0040     m_output = nullptr;
0041 
0042     createProperty("addressSize", Variant::Type::Int);
0043     property("addressSize")->setCaption(i18n("Address Size"));
0044     property("addressSize")->setMinValue(1);
0045     property("addressSize")->setMaxValue(8);
0046     property("addressSize")->setValue(1);
0047 
0048     // For backwards compatibility
0049     createProperty("numInput", Variant::Type::Int);
0050     property("numInput")->setMinValue(-1);
0051     property("numInput")->setValue(-1);
0052     property("numInput")->setHidden(true);
0053 }
0054 
0055 Multiplexer::~Multiplexer()
0056 {
0057 }
0058 
0059 void Multiplexer::dataChanged()
0060 {
0061     if (hasProperty("numInput") && dataInt("numInput") != -1) {
0062         int addressSize = int(std::ceil(std::log(double(dataInt("numInput"))) / std::log(2.0)));
0063         property("numInput")->setValue(-1);
0064 
0065         if (addressSize < 1)
0066             addressSize = 1;
0067         else if (addressSize > 8)
0068             addressSize = 8;
0069 
0070         // This function will get called again when we set the value of numInput
0071         property("addressSize")->setValue(addressSize);
0072         return;
0073     }
0074 
0075     if (hasProperty("numInput")) {
0076         m_variantData["numInput"]->deleteLater();
0077         m_variantData.remove("numInput");
0078     }
0079 
0080     initPins(unsigned(dataInt("addressSize")));
0081 }
0082 
0083 void Multiplexer::inStateChanged(bool /*state*/)
0084 {
0085     unsigned long long pos = 0;
0086     for (int i = 0; i < m_aLogic.size(); ++i) {
0087         if (m_aLogic[i]->isHigh())
0088             pos += 1 << i;
0089     }
0090     m_output->setHigh(m_xLogic[pos]->isHigh());
0091 }
0092 
0093 void Multiplexer::initPins(unsigned newAddressSize)
0094 {
0095     unsigned oldAddressSize = m_aLogic.size();
0096     unsigned long long oldXLogicCount = m_xLogic.size();
0097     unsigned long long newXLogicCount = 1 << newAddressSize;
0098 
0099     if (newXLogicCount == oldXLogicCount)
0100         return;
0101 
0102     QStringList pins;
0103 
0104     const int length = newAddressSize + newXLogicCount;
0105 
0106     for (unsigned i = 0; i < newAddressSize; ++i)
0107         pins += "A" + QString::number(i);
0108     for (unsigned i = 0; i < newXLogicCount; ++i)
0109         pins += "X" + QString::number(i);
0110     for (int i = 0; i < (length - (length % 2)) / 2; ++i)
0111         pins += "";
0112     pins += "X";
0113     for (int i = 0; i < ((length + (length % 2)) / 2) - 1; ++i)
0114         pins += "";
0115 
0116     initDIPSymbol(pins, 64);
0117     initDIP(pins);
0118 
0119     ECNode *node;
0120 
0121     if (!m_output) {
0122         node = ecNodeWithID("X");
0123         m_output = createLogicOut(node, false);
0124     }
0125 
0126     if (newXLogicCount > oldXLogicCount) {
0127         m_xLogic.resize(newXLogicCount);
0128         for (unsigned i = oldXLogicCount; i < newXLogicCount; ++i) {
0129             node = ecNodeWithID("X" + QString::number(i));
0130             m_xLogic.insert(i, createLogicIn(node));
0131             //m_xLogic[i]->setCallback(this, (CallbackPtr)(&Multiplexer::inStateChanged));
0132             m_xLogic[i]->setCallback2(Multiplexer_inStateChanged, this);
0133         }
0134 
0135         m_aLogic.resize(newAddressSize);
0136         for (unsigned i = oldAddressSize; i < newAddressSize; ++i) {
0137             node = ecNodeWithID("A" + QString::number(i));
0138             m_aLogic.insert(i, createLogicIn(node));
0139             //m_aLogic[i]->setCallback(this, (CallbackPtr)(&Multiplexer::inStateChanged));
0140             m_aLogic[i]->setCallback2(Multiplexer_inStateChanged, this);
0141         }
0142     } else {
0143         for (unsigned i = newXLogicCount; i < oldXLogicCount; ++i) {
0144             QString id = "X" + QString::number(i);
0145             removeDisplayText(id);
0146             removeElement(m_xLogic[i], false);
0147             removeNode(id);
0148         }
0149         m_xLogic.resize(newXLogicCount);
0150 
0151         for (unsigned i = newAddressSize; i < oldAddressSize; ++i) {
0152             QString id = "A" + QString::number(i);
0153             removeDisplayText(id);
0154             removeElement(m_aLogic[i], false);
0155             removeNode(id);
0156         }
0157         m_aLogic.resize(newAddressSize);
0158     }
0159 }