File indexing completed on 2024-05-19 09:39:06
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 "matrixdisplay.h" 0012 #include "colorutils.h" 0013 #include "diode.h" 0014 #include "ecnode.h" 0015 #include "led.h" 0016 #include "libraryitem.h" 0017 #include "simulator.h" 0018 0019 #include <KLocalizedString> 0020 0021 #include <QDebug> 0022 #include <QPainter> 0023 #include <QString> 0024 0025 Item *MatrixDisplay::construct(ItemDocument *itemDocument, bool newItem, const char *id) 0026 { 0027 return new MatrixDisplay(static_cast<ICNDocument *>(itemDocument), newItem, id); 0028 } 0029 0030 LibraryItem *MatrixDisplay::libraryItem() 0031 { 0032 return new LibraryItem(QStringList(QString("ec/matrix_display")), i18n("Matrix Display"), i18n("Outputs"), "matrixdisplay.png", LibraryItem::lit_component, MatrixDisplay::construct); 0033 } 0034 0035 MatrixDisplay::MatrixDisplay(ICNDocument *icnDocument, bool newItem, const char *id) 0036 : Component(icnDocument, newItem, id ? id : "matrix_display") 0037 { 0038 m_name = i18n("Matrix Display"); 0039 m_bDynamicContent = true; 0040 0041 // BEGIN Reset members 0042 for (unsigned i = 0; i < max_md_height; i++) 0043 m_pRowNodes[i] = nullptr; 0044 for (unsigned i = 0; i < max_md_width; i++) 0045 m_pColNodes[i] = nullptr; 0046 0047 m_lastUpdatePeriod = 0.0; 0048 m_r = m_g = m_b = 0.0; 0049 m_bRowCathode = true; 0050 m_numRows = 0; 0051 m_numCols = 0; 0052 // END Reset members 0053 0054 createProperty("0-rows", Variant::Type::Int); 0055 property("0-rows")->setCaption(i18n("Rows")); 0056 property("0-rows")->setMinValue(1); 0057 property("0-rows")->setMaxValue(max_md_height); 0058 property("0-rows")->setValue(7); 0059 0060 createProperty("1-cols", Variant::Type::Int); 0061 property("1-cols")->setCaption(i18n("Columns")); 0062 property("1-cols")->setMinValue(1); 0063 property("1-cols")->setMaxValue(max_md_width); 0064 property("1-cols")->setValue(5); 0065 0066 createProperty("color", Variant::Type::Color); 0067 property("color")->setCaption(i18n("Color")); 0068 property("color")->setColorScheme(ColorUtils::LED); 0069 0070 createProperty("diode-configuration", Variant::Type::Select); 0071 property("diode-configuration")->setCaption(i18n("Configuration")); 0072 QStringMap allowed; 0073 allowed["Row Cathode"] = i18n("Row Cathode"); 0074 allowed["Column Cathode"] = i18n("Column Cathode"); 0075 property("diode-configuration")->setAllowed(allowed); 0076 property("diode-configuration")->setValue("Row Cathode"); 0077 property("diode-configuration")->setAdvanced(true); 0078 } 0079 0080 MatrixDisplay::~MatrixDisplay() 0081 { 0082 } 0083 0084 void MatrixDisplay::dataChanged() 0085 { 0086 QColor color = dataColor("color"); 0087 m_r = double(color.red()) / 0x100; 0088 m_g = double(color.green()) / 0x100; 0089 m_b = double(color.blue()) / 0x100; 0090 0091 int numRows = dataInt("0-rows"); 0092 int numCols = dataInt("1-cols"); 0093 0094 bool ledsChanged = (numRows != int(m_numRows)) || (numCols != int(m_numCols)); 0095 0096 if (ledsChanged) 0097 initPins(numRows, numCols); 0098 0099 bool rowCathode = dataString("diode-configuration") == "Row Cathode"; 0100 if ((rowCathode != m_bRowCathode) || ledsChanged) { 0101 m_bRowCathode = rowCathode; 0102 0103 for (unsigned i = 0; i < m_numCols; i++) { 0104 for (unsigned j = 0; j < m_numRows; j++) { 0105 removeElement(m_pDiodes[i][j], false); 0106 if (rowCathode) 0107 m_pDiodes[i][j] = createDiode(m_pColNodes[i], m_pRowNodes[j]); 0108 else 0109 m_pDiodes[i][j] = createDiode(m_pRowNodes[j], m_pColNodes[i]); 0110 } 0111 } 0112 } 0113 } 0114 0115 void MatrixDisplay::initPins(unsigned numRows, unsigned numCols) 0116 { 0117 if ((numRows == m_numRows) && (numCols == m_numCols)) 0118 return; 0119 0120 if (numRows > max_md_height) 0121 numRows = max_md_height; 0122 0123 if (numCols > max_md_width) 0124 numCols = max_md_width; 0125 0126 m_lastUpdatePeriod = 0.0; 0127 0128 // BEGIN Remove diodes 0129 // All the diodes are going to be readded from dataChanged (where this 0130 // function is called from), so easiest just to delete the diodes now and 0131 // resize. 0132 0133 for (unsigned i = 0; i < m_numCols; i++) { 0134 for (unsigned j = 0; j < m_numRows; j++) 0135 removeElement(m_pDiodes[i][j], false); 0136 } 0137 0138 m_avgBrightness.resize(numCols); 0139 m_lastBrightness.resize(numCols); 0140 m_pDiodes.resize(numCols); 0141 0142 for (unsigned i = 0; i < numCols; i++) { 0143 m_avgBrightness[i].resize(numRows); 0144 m_lastBrightness[i].resize(numRows); 0145 m_pDiodes[i].resize(numRows); 0146 0147 for (unsigned j = 0; j < numRows; j++) { 0148 m_avgBrightness[i][j] = 0.0; 0149 m_lastBrightness[i][j] = 255; 0150 m_pDiodes[i][j] = nullptr; 0151 } 0152 } 0153 // END Remove diodes 0154 0155 // BEGIN Create or destroy pins 0156 if (numCols >= m_numCols) { 0157 for (unsigned i = m_numCols; i < numCols; i++) 0158 m_pColNodes[i] = createPin(0, 0, 270, colPinID(i)); 0159 } else { 0160 for (unsigned i = numCols; i < m_numCols; i++) { 0161 removeNode(colPinID(i)); 0162 m_pColNodes[i] = nullptr; 0163 } 0164 } 0165 m_numCols = numCols; 0166 0167 if (numRows >= m_numRows) { 0168 for (unsigned i = m_numRows; i < numRows; i++) 0169 m_pRowNodes[i] = createPin(0, 0, 0, rowPinID(i)); 0170 } else { 0171 for (unsigned i = numRows; i < m_numRows; i++) { 0172 removeNode(rowPinID(i)); 0173 m_pRowNodes[i] = nullptr; 0174 } 0175 } 0176 m_numRows = numRows; 0177 // END Create or destroy pins 0178 0179 // BEGIN Position pins et al 0180 setSize(-int(numCols + 1) * 8, -int(numRows + 1) * 8, int(numCols + 1) * 16, int(numRows + 1) * 16, true); 0181 0182 for (int i = 0; i < int(m_numCols); i++) { 0183 m_nodeMap[colPinID(i)].x = offsetX() + 16 + 16 * i; 0184 m_nodeMap[colPinID(i)].y = offsetY() + height() + 8; 0185 } 0186 0187 for (int i = 0; i < int(m_numRows); i++) { 0188 m_nodeMap[rowPinID(i)].x = offsetX() - 8; 0189 m_nodeMap[rowPinID(i)].y = offsetY() + 16 + 16 * i; 0190 } 0191 0192 updateAttachedPositioning(); 0193 // END Position pins et al 0194 } 0195 0196 QString MatrixDisplay::colPinID(int col) const 0197 { 0198 return QString("col_%1").arg(QString::number(col)); 0199 } 0200 QString MatrixDisplay::rowPinID(int row) const 0201 { 0202 return QString("row_%1").arg(QString::number(row)); 0203 } 0204 0205 void MatrixDisplay::stepNonLogic() 0206 { 0207 for (unsigned i = 0; i < m_numCols; i++) { 0208 for (unsigned j = 0; j < m_numRows; j++) 0209 m_avgBrightness[i][j] += LED::brightness(m_pDiodes[i][j]->current()) * LINEAR_UPDATE_PERIOD; 0210 } 0211 0212 m_lastUpdatePeriod += LINEAR_UPDATE_PERIOD; 0213 } 0214 0215 void MatrixDisplay::drawShape(QPainter &p) 0216 { 0217 if (isSelected()) 0218 p.setPen(m_selectedCol); 0219 p.drawRect(boundingRect()); 0220 0221 initPainter(p); 0222 0223 const int _x = int(x() + offsetX()); 0224 const int _y = int(y() + offsetY()); 0225 0226 // To avoid flicker, require at least a 10 ms sample before changing 0227 // the brightness 0228 double minUpdatePeriod = 0.0099; 0229 0230 for (int i = 0; i < int(m_numCols); i++) { 0231 for (int j = 0; j < int(m_numRows); j++) { 0232 if (m_lastUpdatePeriod > minUpdatePeriod) 0233 m_lastBrightness[i][j] = unsigned(m_avgBrightness[i][j] / m_lastUpdatePeriod); 0234 0235 double _b = m_lastBrightness[i][j]; 0236 0237 QColor brush = QColor(uint(255 - (255 - _b) * (1 - m_r)), uint(255 - (255 - _b) * (1 - m_g)), uint(255 - (255 - _b) * (1 - m_b))); 0238 p.setBrush(brush); 0239 p.setPen(Qt::NoPen); 0240 p.drawEllipse(_x + 10 + i * 16, _y + 10 + j * 16, 12, 12); 0241 } 0242 } 0243 0244 if (m_lastUpdatePeriod > minUpdatePeriod) { 0245 m_lastUpdatePeriod = 0.0; 0246 0247 for (unsigned i = 0; i < m_numCols; i++) { 0248 for (unsigned j = 0; j < m_numRows; j++) 0249 m_avgBrightness[i][j] = 0.0; 0250 } 0251 } 0252 0253 deinitPainter(p); 0254 }