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

0001 /***************************************************************************
0002  *   Copyright (C) 2006 by William Hillerby - william.hillerby@ntlworld.com*
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  ***************************************************************************/
0009 
0010 #include "ledbargraphdisplay.h"
0011 #include "colorutils.h"
0012 #include "led.h"
0013 #include "libraryitem.h"
0014 #include "simulator.h"
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <QDebug>
0019 #include <QPainter>
0020 #include <QStyle>
0021 
0022 LEDPart::LEDPart(Component *pParent, const QString &strPNode, const QString &strNNode)
0023 {
0024     m_pParent = pParent;
0025 
0026     m_strPNode = strPNode;
0027     m_strNNode = strNNode;
0028 
0029     m_pDiode = pParent->createDiode(pParent->ecNodeWithID(strPNode), pParent->ecNodeWithID(strNNode));
0030 
0031     avg_brightness = 255;
0032     lastUpdatePeriod = 1.;
0033     last_brightness = 255;
0034     r = g = b = 0;
0035 }
0036 
0037 LEDPart::~LEDPart()
0038 {
0039     m_pParent->removeNode(m_strPNode);
0040     m_pParent->removeNode(m_strNNode);
0041     m_pParent->removeElement(m_pDiode, false);
0042 }
0043 
0044 void LEDPart::setDiodeSettings(const DiodeSettings &ds)
0045 {
0046     m_pDiode->setDiodeSettings(ds);
0047 }
0048 
0049 void LEDPart::setColor(const QColor &color)
0050 {
0051     r = color.red() / double(0x100);
0052     g = color.green() / double(0x100);
0053     b = color.blue() / double(0x100);
0054 }
0055 
0056 void LEDPart::step()
0057 {
0058     avg_brightness += LED::brightness(m_pDiode->current()) * LINEAR_UPDATE_PERIOD;
0059     lastUpdatePeriod += LINEAR_UPDATE_PERIOD;
0060 }
0061 
0062 void LEDPart::draw(QPainter &p, int x, int y, int w, int h)
0063 {
0064     uint _b;
0065     if (lastUpdatePeriod == 0.)
0066         _b = last_brightness;
0067     else {
0068         _b = uint(avg_brightness / lastUpdatePeriod);
0069         last_brightness = _b;
0070     }
0071 
0072     avg_brightness = 0.;
0073     lastUpdatePeriod = 0.;
0074 
0075     p.setBrush(QColor(uint(255 - (255 - _b) * (1 - r)), uint(255 - (255 - _b) * (1 - g)), uint(255 - (255 - _b) * (1 - b))));
0076     p.drawRect(x, y, w, h);
0077 }
0078 
0079 Item *LEDBarGraphDisplay::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0080 {
0081     return new LEDBarGraphDisplay(static_cast<ICNDocument *>(itemDocument), newItem, id);
0082 }
0083 
0084 LibraryItem *LEDBarGraphDisplay::libraryItem()
0085 {
0086     return new LibraryItem(QStringList(QString("ec/bar_graph_display")), i18n("Bar Graph Display"), i18n("Outputs"), "bar_graph_display.png", LibraryItem::lit_component, LEDBarGraphDisplay::construct);
0087 }
0088 
0089 LEDBarGraphDisplay::LEDBarGraphDisplay(ICNDocument *icnDocument, bool newItem, const QString &id)
0090     : Component(icnDocument, newItem, (!id.isEmpty()) ? id : "bar_graph_display")
0091 {
0092     m_name = i18n("Bar Graph Display");
0093     m_bDynamicContent = true;
0094 
0095     m_numRows = 0;
0096 
0097     for (unsigned i = 0; i < max_LED_rows; i++)
0098         m_LEDParts[i] = nullptr;
0099 
0100     // Create a Row property.
0101     createProperty("rows", Variant::Type::Int);
0102     property("rows")->setCaption(i18n("Rows"));
0103     property("rows")->setMinValue(1);
0104     property("rows")->setMaxValue(max_LED_rows);
0105     property("rows")->setValue(7);
0106 
0107     createProperty("color", Variant::Type::Color);
0108     property("color")->setCaption(i18n("Color"));
0109     property("color")->setColorScheme(ColorUtils::LED);
0110 
0111     DiodeSettings ds;
0112 
0113     createProperty("I_S", Variant::Type::Double);
0114     property("I_S")->setCaption("Saturation Current");
0115     property("I_S")->setUnit("A");
0116     property("I_S")->setMinValue(1e-20);
0117     property("I_S")->setMaxValue(1e-0);
0118     property("I_S")->setValue(ds.I_S);
0119     property("I_S")->setAdvanced(true);
0120 
0121     createProperty("N", Variant::Type::Double);
0122     property("N")->setCaption(i18n("Emission Coefficient"));
0123     property("N")->setMinValue(1e0);
0124     property("N")->setMaxValue(1e1);
0125     property("N")->setValue(ds.N);
0126     property("N")->setAdvanced(true);
0127 
0128     createProperty("V_B", Variant::Type::Double);
0129     property("V_B")->setCaption(i18n("Breakdown Voltage"));
0130     property("V_B")->setUnit("V");
0131     property("V_B")->setMinAbsValue(1e-5);
0132     property("V_B")->setMaxValue(1e10);
0133     property("V_B")->setValue(ds.V_B);
0134     property("V_B")->setAdvanced(true);
0135 }
0136 
0137 LEDBarGraphDisplay::~LEDBarGraphDisplay()
0138 {
0139 }
0140 
0141 void LEDBarGraphDisplay::dataChanged()
0142 {
0143     DiodeSettings ds;
0144     QColor color = dataColor("color");
0145 
0146     ds.I_S = dataDouble("I_S");
0147     ds.V_B = dataDouble("V_B");
0148     ds.N = dataDouble("N");
0149 
0150     initPins();
0151 
0152     // Update each diode in array with new diode setting as they are acting individually.
0153     for (unsigned i = 0; i < m_numRows; i++) {
0154         m_LEDParts[i]->setDiodeSettings(ds);
0155         m_LEDParts[i]->setColor(color);
0156     }
0157 }
0158 
0159 void LEDBarGraphDisplay::initPins()
0160 {
0161     unsigned int numRows = dataInt("rows");
0162 
0163     if (numRows == m_numRows)
0164         return;
0165 
0166     if (numRows > max_LED_rows)
0167         numRows = max_LED_rows;
0168     if (numRows < 1)
0169         numRows = 1;
0170 
0171     // Create a list of named pins.
0172     // A default setup looks like:
0173     //       -------
0174     // p_0--|1    14|--n_0
0175     // p_1--|2    13|--n_1
0176     // p_2--|3    12|--n_2
0177     // p_3--|4    11|--n_3
0178     // p_4--|5    10|--n_4
0179     // p_5--|6     9|--n_5
0180     // p_6--|7     8|--n_6
0181     //       -------
0182     //
0183     // And this is the scheme used to create the nodes and diodes.
0184     //
0185 
0186     // Create the positive & negative pin names in an anticlockwise fashion
0187     // as shown in the pin schematic above.
0188     QStringList pins;
0189     for (unsigned i = 0; i < numRows; i++)
0190         pins += QString("p_" + QString::number(i));
0191 
0192     for (int i = numRows - 1; i >= 0; i--)
0193         pins += QString("n_" + QString::number(i));
0194 
0195     // Set the size of the component *BEFORE* initDIP() is called
0196     // as initDIP() uses this data to initialise the pin positions.
0197     setSize(-16, -(numRows + 1) * 8, 32, (numRows + 1) * 16, true);
0198 
0199     // Create the nodes.
0200     initDIP(pins);
0201 
0202     // Create or remove LED parts
0203     if (numRows > m_numRows) {
0204         // Create the extra LED parts required.
0205         for (unsigned i = m_numRows; i < numRows; i++)
0206             m_LEDParts[i] = new LEDPart(static_cast<Component *>(this), QString("p_" + QString::number(i)), QString("n_" + QString::number(i)));
0207     } else {
0208         // Remove excess LED parts.
0209         for (unsigned i = numRows; i < m_numRows; i++) {
0210             delete m_LEDParts[i];
0211             m_LEDParts[i] = nullptr;
0212         }
0213     }
0214 
0215     m_numRows = numRows;
0216 }
0217 
0218 void LEDBarGraphDisplay::stepNonLogic()
0219 {
0220     // Update LED brightnesses.
0221     for (unsigned i = 0; i < m_numRows; i++)
0222         m_LEDParts[i]->step();
0223 }
0224 
0225 void LEDBarGraphDisplay::drawShape(QPainter &p)
0226 {
0227     Component::drawShape(p);
0228     initPainter(p);
0229 
0230     // Init _x and _y to top left hand corner of component.
0231     int _x = int(x() + offsetX());
0232     int _y = int(y() + offsetY());
0233 
0234     // Draw LED elements, passing in a position for each.
0235     for (unsigned i = 0; i < m_numRows; i++)
0236         m_LEDParts[i]->draw(p, _x + 4, _y + (i * 16) + 10, 24, 12);
0237 
0238     deinitPainter(p);
0239 }