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

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 "addac.h"
0012 #include "ecnode.h"
0013 #include "libraryitem.h"
0014 #include "logic.h"
0015 #include "pin.h"
0016 #include "voltagepoint.h"
0017 
0018 #include <KLocalizedString>
0019 #include <cmath>
0020 
0021 Item *ADC::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0022 {
0023     return new ADC(static_cast<ICNDocument *>(itemDocument), newItem, id);
0024 }
0025 
0026 Item *DAC::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0027 {
0028     return new DAC(static_cast<ICNDocument *>(itemDocument), newItem, id);
0029 }
0030 
0031 LibraryItem *ADC::libraryItem()
0032 {
0033     return new LibraryItem(QStringList(QString("ec/adc")), i18n("Analog-Digital"), i18n("Integrated Circuits"), "ic1.png", LibraryItem::lit_component, ADC::construct);
0034 }
0035 
0036 LibraryItem *DAC::libraryItem()
0037 {
0038     return new LibraryItem(QStringList(QString("ec/dac")), i18n("Digital-Analog"), i18n("Integrated Circuits"), "ic1.png", LibraryItem::lit_component, DAC::construct);
0039 }
0040 
0041 // BEGIN class ADDAC
0042 ADDAC::ADDAC(ICNDocument *icnDocument, bool newItem, const char *id)
0043     : Component(icnDocument, newItem, id)
0044 {
0045     m_numBits = 0;
0046     m_range = 0;
0047 
0048     createProperty("numBits", Variant::Type::Int);
0049     property("numBits")->setCaption(i18n("Number Bits"));
0050     property("numBits")->setMinValue(2);
0051     property("numBits")->setMaxValue(max_ADDAC_bits);
0052     property("numBits")->setValue(2);
0053 
0054     createProperty("range", Variant::Type::Double);
0055     property("range")->setCaption(i18n("Input Range"));
0056     property("range")->setUnit("V");
0057     property("range")->setMinValue(-1e12);
0058     property("range")->setMaxValue(1e12);
0059     property("range")->setValue(5);
0060 }
0061 
0062 ADDAC::~ADDAC()
0063 {
0064 }
0065 
0066 void ADDAC::dataChanged()
0067 {
0068     m_range = dataDouble("range");
0069     initPins();
0070 }
0071 
0072 // END class ADDAC
0073 
0074 // BEGIN class ADC
0075 ADC::ADC(ICNDocument *icnDocument, bool newItem, const char *id)
0076     : ADDAC(icnDocument, newItem, id ? id : "adc")
0077 {
0078     m_name = i18n("ADC");
0079 
0080     for (int i = 0; i < max_ADDAC_bits; ++i)
0081         m_logic[i] = nullptr;
0082 
0083     m_realNode = nullptr;
0084 }
0085 
0086 ADC::~ADC()
0087 {
0088 }
0089 
0090 void ADC::stepNonLogic()
0091 {
0092     double floatBitValue = m_realNode->pin()->voltage() * (std::pow(2, double(m_numBits)) - 1.) / m_range;
0093     double roundBitValue = std::floor(floatBitValue + 0.5);
0094 
0095     if (roundBitValue < 0) {
0096         for (int i = 0; i < m_numBits; ++i)
0097             m_logic[i]->setHigh(false);
0098         return;
0099     }
0100 
0101     uint roundedBitValue = uint(roundBitValue);
0102     for (int i = 0; i < m_numBits; ++i)
0103         m_logic[i]->setHigh(roundedBitValue & (1 << i));
0104 }
0105 
0106 void ADC::initPins()
0107 {
0108     int numBits = dataInt("numBits");
0109 
0110     if (numBits < 2)
0111         numBits = 2;
0112     else if (numBits > max_ADDAC_bits)
0113         numBits = max_ADDAC_bits;
0114 
0115     if (numBits == m_numBits)
0116         return;
0117 
0118     QStringList pins;
0119 
0120     int inPos = (numBits - 1 + (numBits % 2)) / 2;
0121     for (int i = 0; i < inPos; ++i)
0122         pins += "";
0123 
0124     pins += "In";
0125 
0126     for (int i = inPos + 1; i < numBits; ++i)
0127         pins += "";
0128 
0129     for (int i = numBits - 1; i >= 0; --i)
0130         pins += QString::number(i);
0131 
0132     initDIPSymbol(pins, 64);
0133     initDIP(pins);
0134 
0135     if (!m_realNode)
0136         m_realNode = ecNodeWithID("In");
0137 
0138     if (numBits > m_numBits) {
0139         for (int i = m_numBits; i < numBits; ++i) {
0140             ECNode *node = ecNodeWithID(QString::number(i));
0141             m_logic[i] = createLogicOut(node, false);
0142         }
0143     } else {
0144         for (int i = numBits; i < m_numBits; ++i) {
0145             QString id = QString::number(i);
0146             removeDisplayText(id);
0147             removeElement(m_logic[i], false);
0148             removeNode(id);
0149             m_logic[i] = nullptr;
0150         }
0151     }
0152 
0153     m_numBits = numBits;
0154 }
0155 // END class ADC
0156 
0157 // BEGIN class DAC
0158 DAC::DAC(ICNDocument *icnDocument, bool newItem, const char *id)
0159     : ADDAC(icnDocument, newItem, id ? id : "dac")
0160 {
0161     m_name = i18n("DAC");
0162 
0163     for (int i = 0; i < max_ADDAC_bits; ++i)
0164         m_logic[i] = nullptr;
0165 
0166     m_voltagePoint = nullptr;
0167 }
0168 
0169 DAC::~DAC()
0170 {
0171 }
0172 
0173 void DAC::stepNonLogic()
0174 {
0175     uint value = 0;
0176     for (int i = 0; i < m_numBits; ++i)
0177         value |= (m_logic[i]->isHigh() ? 1 : 0) << i;
0178 
0179     //  double valueAsDouble = double(value);
0180     //  double powChange = std::pow( double(m_numBits), 2 )-1.;
0181     //  m_voltagePoint->setVoltage( m_range * valueAsDouble / powChange );
0182     m_voltagePoint->setVoltage(m_range * double(value) / (std::pow(2, double(m_numBits)) - 1.));
0183 }
0184 
0185 void DAC::initPins()
0186 {
0187     int numBits = dataInt("numBits");
0188 
0189     if (numBits < 2)
0190         numBits = 2;
0191     else if (numBits > max_ADDAC_bits)
0192         numBits = max_ADDAC_bits;
0193 
0194     if (numBits == m_numBits)
0195         return;
0196 
0197     QStringList pins;
0198 
0199     for (int i = 0; i < numBits; ++i)
0200         pins += QString::number(i);
0201 
0202     int inPos = (numBits + 1 + (numBits % 2)) / 2;
0203     for (int i = numBits - 1; i >= inPos; --i)
0204         pins += "";
0205 
0206     pins += "Out";
0207 
0208     for (int i = inPos - 2; i >= 0; --i)
0209         pins += "";
0210 
0211     initDIPSymbol(pins, 64);
0212     initDIP(pins);
0213 
0214     if (!m_voltagePoint)
0215         m_voltagePoint = createVoltagePoint(ecNodeWithID("Out"), 0.);
0216 
0217     if (numBits > m_numBits) {
0218         for (int i = m_numBits; i < numBits; ++i) {
0219             ECNode *node = ecNodeWithID(QString::number(i));
0220             m_logic[i] = createLogicIn(node);
0221         }
0222     } else {
0223         for (int i = numBits; i < m_numBits; ++i) {
0224             QString id = QString::number(i);
0225             removeDisplayText(id);
0226             removeElement(m_logic[i], false);
0227             removeNode(id);
0228             m_logic[i] = nullptr;
0229         }
0230     }
0231 
0232     m_numBits = numBits;
0233 }
0234 // END class DAC