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

0001 /***************************************************************************
0002  *   Copyright (C) 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 "ram.h"
0012 #include "libraryitem.h"
0013 #include "logic.h"
0014 #include "variant.h"
0015 
0016 #include <KLocalizedString>
0017 #include <cmath>
0018 
0019 void RAM_inStateChanged(void *objV, bool state) {
0020     RAM *objT = static_cast<RAM*>(objV);
0021     objT->inStateChanged(state);
0022 }
0023 
0024 Item *RAM::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0025 {
0026     return new RAM(static_cast<ICNDocument *>(itemDocument), newItem, id);
0027 }
0028 
0029 LibraryItem *RAM::libraryItem()
0030 {
0031     return new LibraryItem(QStringList(QString("ec/ram")), i18n("RAM"), i18n("Integrated Circuits"), "ic2.png", LibraryItem::lit_component, RAM::construct);
0032 }
0033 
0034 RAM::RAM(ICNDocument *icnDocument, bool newItem, const char *id)
0035     : Component(icnDocument, newItem, id ? id : "ram")
0036 {
0037     m_name = i18n("RAM");
0038 
0039     // m_data = nullptr; // should be initialized by the constructor anyway
0040     m_pCS = nullptr;
0041     m_pOE = nullptr;
0042     m_pWE = nullptr;
0043     m_wordSize = 0;
0044     m_addressSize = 0;
0045 
0046     createProperty("wordSize", Variant::Type::Int);
0047     property("wordSize")->setCaption(i18n("Word Size"));
0048     property("wordSize")->setMinValue(1);
0049     property("wordSize")->setMaxValue(64);
0050     property("wordSize")->setValue(2);
0051 
0052     createProperty("addressSize", Variant::Type::Int);
0053     property("addressSize")->setCaption(i18n("Address Size"));
0054     property("addressSize")->setMinValue(1);
0055     property("addressSize")->setMaxValue(24);
0056     property("addressSize")->setValue(4);
0057 
0058     m_data = createProperty("data", Variant::Type::Raw)->value().toBitArray();
0059 }
0060 
0061 RAM::~RAM()
0062 {
0063 }
0064 
0065 void RAM::dataChanged()
0066 {
0067     m_wordSize = dataInt("wordSize");
0068     m_addressSize = dataInt("addressSize");
0069 
0070     int newSize = int(m_wordSize * std::pow(2., m_addressSize));
0071     m_data.resize(newSize);
0072 
0073     initPins();
0074 }
0075 
0076 void RAM::inStateChanged(bool newState)
0077 {
0078     Q_UNUSED(newState);
0079 
0080     bool cs = m_pCS->isHigh();
0081     bool oe = m_pOE->isHigh();
0082     bool we = m_pWE->isHigh();
0083 
0084     if (!cs || !oe) {
0085         for (int i = 0; i < m_wordSize; ++i)
0086             m_dataOut[i]->setHigh(false);
0087     }
0088 
0089     if (!cs || (!oe && !we))
0090         return;
0091 
0092     unsigned address = 0;
0093     for (int i = 0; i < m_addressSize; ++i)
0094         address += (m_address[i]->isHigh() ? 1 : 0) << i;
0095 
0096     if (we) {
0097         for (int i = 0; i < m_wordSize; ++i)
0098             m_data[m_wordSize * address + i] = m_dataIn[i]->isHigh();
0099     }
0100 
0101     if (oe) {
0102         for (int i = 0; i < m_wordSize; ++i)
0103             m_dataOut[i]->setHigh(m_data[m_wordSize * address + i]);
0104     }
0105 }
0106 
0107 void RAM::initPins()
0108 {
0109     int oldWordSize = m_dataIn.size();
0110     int oldAddressSize = m_address.size();
0111 
0112     int newWordSize = dataInt("wordSize");
0113     int newAddressSize = dataInt("addressSize");
0114 
0115     if (newAddressSize == oldAddressSize && newWordSize == oldWordSize)
0116         return;
0117 
0118     QStringList leftPins; // Pins on left of IC
0119     leftPins << "CS"
0120              << "OE"
0121              << "WE";
0122     for (int i = 0; i < newAddressSize; ++i)
0123         leftPins << QString("A%1").arg(QString::number(i));
0124 
0125     QStringList rightPins; // Pins on right of IC
0126     for (unsigned i = newWordSize; i > 0; --i)
0127         rightPins << QString("DI%1").arg(QString::number(i - 1));
0128     for (unsigned i = newWordSize; i > 0; --i)
0129         rightPins << QString("DO%1").arg(QString::number(i - 1));
0130 
0131     // Make pin lists of consistent sizes
0132     for (int i = leftPins.size(); i < rightPins.size(); ++i)
0133         leftPins.append("");
0134     for (int i = rightPins.size(); i < leftPins.size(); ++i)
0135         rightPins.prepend("");
0136 
0137     QStringList pins = leftPins + rightPins;
0138 
0139     initDIPSymbol(pins, 72);
0140     initDIP(pins);
0141 
0142     ECNode *node;
0143 
0144     if (!m_pCS) {
0145         node = ecNodeWithID("CS");
0146         m_pCS = createLogicIn(node);
0147         //m_pCS->setCallback(this, (CallbackPtr)(&RAM::inStateChanged));
0148         m_pCS->setCallback2(RAM_inStateChanged, this);
0149     }
0150 
0151     if (!m_pOE) {
0152         node = ecNodeWithID("OE");
0153         m_pOE = createLogicIn(node);
0154         //m_pOE->setCallback(this, (CallbackPtr)(&RAM::inStateChanged));
0155         m_pOE->setCallback2(RAM_inStateChanged, this);
0156     }
0157 
0158     if (!m_pWE) {
0159         node = ecNodeWithID("WE");
0160         m_pWE = createLogicIn(node);
0161         //m_pWE->setCallback(this, (CallbackPtr)(&RAM::inStateChanged));
0162         m_pWE->setCallback2(RAM_inStateChanged, this);
0163     }
0164 
0165     if (newWordSize > oldWordSize) {
0166         m_dataIn.resize(newWordSize);
0167         m_dataOut.resize(newWordSize);
0168 
0169         for (int i = oldWordSize; i < newWordSize; ++i) {
0170             node = ecNodeWithID(QString("DI%1").arg(QString::number(i)));
0171             m_dataIn.insert(i, createLogicIn(node));
0172             //m_dataIn[i]->setCallback(this, (CallbackPtr)(&RAM::inStateChanged));
0173             m_dataIn[i]->setCallback2(RAM_inStateChanged, this);
0174 
0175             node = ecNodeWithID(QString("DO%1").arg(QString::number(i)));
0176             m_dataOut.insert(i, createLogicOut(node, false));
0177         }
0178     } else if (newWordSize < oldWordSize) {
0179         for (int i = newWordSize; i < oldWordSize; ++i) {
0180             QString id = QString("DO%1").arg(QString::number(i));
0181             removeDisplayText(id);
0182             removeElement(m_dataIn[i], false);
0183             removeNode(id);
0184 
0185             id = QString("DI%1").arg(QString::number(i));
0186             removeDisplayText(id);
0187             removeElement(m_dataOut[i], false);
0188             removeNode(id);
0189         }
0190 
0191         m_dataIn.resize(newWordSize);
0192         m_dataOut.resize(newWordSize);
0193     }
0194 
0195     if (newAddressSize > oldAddressSize) {
0196         m_address.resize(newAddressSize);
0197 
0198         for (int i = oldAddressSize; i < newAddressSize; ++i) {
0199             node = ecNodeWithID(QString("A%1").arg(QString::number(i)));
0200             m_address.insert(i, createLogicIn(node));
0201             //m_address[i]->setCallback(this, (CallbackPtr)(&RAM::inStateChanged));
0202             m_address[i]->setCallback2(RAM_inStateChanged, this);
0203 
0204         }
0205     } else if (newAddressSize < oldAddressSize) {
0206         for (int i = newAddressSize; i < oldAddressSize; ++i) {
0207             QString id = QString("A%1").arg(QString::number(i));
0208             removeDisplayText(id);
0209             removeElement(m_address[i], false);
0210             removeNode(id);
0211         }
0212 
0213         m_address.resize(newAddressSize);
0214     }
0215 }