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

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 "demultiplexer.h"
0012 
0013 #include "libraryitem.h"
0014 #include "logic.h"
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <cmath>
0019 
0020 Item *Demultiplexer::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0021 {
0022     return new Demultiplexer(static_cast<ICNDocument *>(itemDocument), newItem, id);
0023 }
0024 
0025 LibraryItem *Demultiplexer::libraryItem()
0026 {
0027     return new LibraryItem(QStringList(QString("ec/demultiplexer")), i18n("Demultiplexer"), i18n("Integrated Circuits"), "ic1.png", LibraryItem::lit_component, Demultiplexer::construct);
0028 }
0029 
0030 void Demultiplexer_inStateChanged(void *objV, bool newState) {
0031     Demultiplexer *objT = static_cast<Demultiplexer*>(objV);
0032     objT->inStateChanged(newState);
0033 }
0034 
0035 Demultiplexer::Demultiplexer(ICNDocument *icnDocument, bool newItem, const char *id)
0036     : Component(icnDocument, newItem, id ? id : "demultiplexer")
0037 {
0038     m_name = i18n("Demultiplexer");
0039 
0040     m_input = 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 Demultiplexer::~Demultiplexer()
0056 {
0057 }
0058 
0059 void Demultiplexer::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 Demultiplexer::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     for (int i = 0; i < m_xLogic.size(); ++i)
0091         m_xLogic[i]->setHigh((int(pos) == i) && m_input->isHigh());
0092 }
0093 
0094 void Demultiplexer::initPins(unsigned newAddressSize)
0095 {
0096     unsigned oldAddressSize = m_aLogic.size();
0097     unsigned long long oldXLogicCount = m_xLogic.size();
0098     unsigned long long newXLogicCount = 1 << newAddressSize;
0099 
0100     if (newXLogicCount == oldXLogicCount)
0101         return;
0102 
0103     QStringList pins;
0104 
0105     for (unsigned i = 0; i < newAddressSize; ++i)
0106         pins += "A" + QString::number(i);
0107     for (unsigned i = newAddressSize; i < (newXLogicCount + (newXLogicCount % 2)) / 2; ++i)
0108         pins += "";
0109     pins += "X";
0110     for (unsigned i = (newXLogicCount + (newXLogicCount % 2)) / 2 + 1; i < newXLogicCount; ++i)
0111         pins += "";
0112     for (int i = newXLogicCount - 1; i >= 0; --i)
0113         pins += "X" + QString::number(i);
0114 
0115     initDIPSymbol(pins, 64);
0116     initDIP(pins);
0117 
0118     ECNode *node;
0119 
0120     if (!m_input) {
0121         node = ecNodeWithID("X");
0122         m_input = createLogicIn(node);
0123         //m_input->setCallback(this, (CallbackPtr)(&Demultiplexer::inStateChanged));
0124         m_input->setCallback2(Demultiplexer_inStateChanged, this);
0125     }
0126 
0127     if (newXLogicCount > oldXLogicCount) {
0128         m_xLogic.resize(newXLogicCount);
0129         for (unsigned i = oldXLogicCount; i < newXLogicCount; ++i) {
0130             node = ecNodeWithID("X" + QString::number(i));
0131             m_xLogic.insert(i, createLogicOut(node, false));
0132         }
0133 
0134         m_aLogic.resize(newAddressSize);
0135         for (unsigned i = oldAddressSize; i < newAddressSize; ++i) {
0136             node = ecNodeWithID("A" + QString::number(i));
0137             m_aLogic.insert(i, createLogicIn(node));
0138             //m_aLogic[i]->setCallback(this, (CallbackPtr)(&Demultiplexer::inStateChanged));
0139             m_aLogic[i]->setCallback2(Demultiplexer_inStateChanged, this);
0140         }
0141     } else {
0142         for (unsigned i = newXLogicCount; i < oldXLogicCount; ++i) {
0143             QString id = "X" + QString::number(i);
0144             removeDisplayText(id);
0145             removeElement(m_xLogic[i], false);
0146             removeNode(id);
0147         }
0148         m_xLogic.resize(newXLogicCount);
0149 
0150         for (unsigned i = newAddressSize; i < oldAddressSize; ++i) {
0151             QString id = "A" + QString::number(i);
0152             removeDisplayText(id);
0153             removeElement(m_aLogic[i], false);
0154             removeNode(id);
0155         }
0156         m_aLogic.resize(newAddressSize);
0157     }
0158 }