Logo Search packages:      
Sourcecode: ktechlab version File versions

matrixdisplay.cpp

/***************************************************************************
 *   Copyright (C) 2005 by David Saxton                                    *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "colorcombo.h"
#include "diode.h"
#include "ecled.h"
#include "ecnode.h"
#include "libraryitem.h"
#include "matrixdisplay.h"
#include "simulator.h"

#include <kdebug.h>
#include <klocale.h>
#include <qpainter.h>
#include <qstring.h>

Item* MatrixDisplay::construct( ItemDocument *itemDocument, bool newItem, const char *id )
{
      return new MatrixDisplay( (ICNDocument*)itemDocument, newItem, id );
}


LibraryItem* MatrixDisplay::libraryItem()
{
      return new LibraryItem(
            "ec/matrix_display",
            i18n("Matrix Display"),
            i18n("Outputs"),
            "matrixdisplay.png",
            LibraryItem::lit_component,
            MatrixDisplay::construct );
}


MatrixDisplay::MatrixDisplay( ICNDocument *icnDocument, bool newItem, const char *id )
      : Component( icnDocument, newItem, id ? id : "matrix_display" )
{
      m_name = i18n("Matrix Display");
      m_desc = i18n("A matrix display of LEDs with a configurable number of columns and rows.");
      m_bDynamicContent = true;
      
      //BEGIN Reset members
      for ( unsigned i = 0; i < max_md_height; i++ )
            m_pRowNodes[i] = 0l;
      for ( unsigned i = 0; i < max_md_width; i++ )
            m_pColNodes[i] = 0l;
      
      m_lastUpdatePeriod = 0.0;
      m_r = m_g = m_b = 0.0;
      m_bRowCathode = true;
      m_numRows = 0;
      m_numCols = 0;
      //END Reset members
      
      createProperty( "0-rows", Variant::Type::Int );
      property("0-rows")->setCaption( i18n("Rows") );
      property("0-rows")->setMinValue(1);
      property("0-rows")->setMaxValue(max_md_height);
      property("0-rows")->setValue(7);
      
      createProperty( "1-cols", Variant::Type::Int );
      property("1-cols")->setCaption( i18n("Columns") );
      property("1-cols")->setMinValue(1);
      property("1-cols")->setMaxValue(max_md_width);
      property("1-cols")->setValue(5);
      
      createProperty( "color", Variant::Type::Color );
      property("color")->setCaption( i18n("Color") );
      property("color")->setColorScheme( ColorCombo::LED );
      
      createProperty( "diode-configuration", Variant::Type::Select );
      property("diode-configuration")->setCaption( i18n("Configuration") );
      property("diode-configuration")->setAllowed( QStringList::split(',',"Row Cathode,Column Cathode") );
      property("diode-configuration")->setValue("Row Cathode");
      property("diode-configuration")->setAdvanced(true);
}


MatrixDisplay::~MatrixDisplay()
{
}


void MatrixDisplay::dataChanged()
{
      QColor color = dataColor("color");
      m_r = double(color.red())     / double(0x100);
      m_g = double(color.green())   / double(0x100);
      m_b = double(color.blue())    / double(0x100);
      
      int numRows = dataInt("0-rows");
      int numCols = dataInt("1-cols");
      
      bool ledsChanged = (numRows != int(m_numRows)) || (numCols != int(m_numCols));
      
      if (ledsChanged)
            initPins( numRows, numCols );
      
      bool rowCathode = dataString("diode-configuration") == "Row Cathode";
      if ( (rowCathode != m_bRowCathode) || ledsChanged)
      {
            m_bRowCathode = rowCathode;
            
            for ( unsigned i = 0; i < m_numCols; i++ )
            {
                  for ( unsigned j = 0; j < m_numRows; j++ )
                  {
                        removeElement( m_pDiodes[i][j], false );
                        if (rowCathode)
                              m_pDiodes[i][j] = createDiode( m_pColNodes[i], m_pRowNodes[j] );
                        else
                              m_pDiodes[i][j] = createDiode( m_pRowNodes[j], m_pColNodes[i] );
                  }
            }
      }
}


void MatrixDisplay::initPins( unsigned numRows, unsigned numCols )
{
      if ( (numRows == m_numRows) && (numCols == m_numCols) )
            return;
      
      if ( numRows > max_md_height )
            numRows = max_md_height;
      
      if ( numCols > max_md_width )
            numCols = max_md_width;
      
      m_lastUpdatePeriod = 0.0;
      
      //BEGIN Remove diodes
      // All the diodes are going to be readded from dataChanged (where this
      // function is called from), so easiest just to delete the diodes now and
      // resize.
      
      for ( unsigned i = 0; i < m_numCols; i++ )
      {
            for ( unsigned j = 0; j < m_numRows; j++ )
                  removeElement( m_pDiodes[i][j], false );
      }
      
      m_avgBrightness.resize(numCols);
      m_lastBrightness.resize(numCols);
      m_pDiodes.resize(numCols);
      
      for ( unsigned i = 0; i < numCols; i++ )
      {
            m_avgBrightness[i].resize(numRows);
            m_lastBrightness[i].resize(numRows);
            m_pDiodes[i].resize(numRows);
            
            for ( unsigned j = 0; j < numRows; j++ )
            {
                  m_avgBrightness[i][j] = 0.0;
                  m_lastBrightness[i][j] = 255;
                  m_pDiodes[i][j] = 0l;
            }
                  
      }
      //END Remove diodes
      
      
      //BEGIN Create or destroy pins
      if ( numCols >= m_numCols )
      {
            for ( unsigned i = m_numCols; i < numCols; i++ )
                  m_pColNodes[i] = createPin( 0, 0, 270, colPinID(i) );
      }
      else
      {
            for ( unsigned i = numCols; i < m_numCols; i++ )
            {
                  removeNode( colPinID(i) );
                  m_pColNodes[i] = 0l;
            }
      }
      m_numCols = numCols;
      
      if ( numRows >= m_numRows )
      {
            for ( unsigned i = m_numRows; i < numRows; i++ )
                  m_pRowNodes[i] = createPin( 0, 0, 0, rowPinID(i) );
      }
      else
      {
            for ( unsigned i = numRows; i < m_numRows; i++ )
            {
                  removeNode( rowPinID(i) );
                  m_pRowNodes[i] = 0l;
            }
      }
      m_numRows = numRows;
      //END Create or destroy pins
      
      
      //BEGIN Position pins et al
      setSize( -int(numCols+1)*8, -int(numRows+1)*8, int(numCols+1)*16, int(numRows+1)*16, true );
      
      for ( int i = 0; i < int(m_numCols); i++ )
      {
            m_nodeMap[colPinID(i)].x = offsetX() + 16 + 16*i;
            m_nodeMap[colPinID(i)].y = offsetY() + height() + 8;
      }
      
      for ( int i = 0; i < int(m_numRows); i++ )
      {
            m_nodeMap[rowPinID(i)].x = offsetX() - 8;
            m_nodeMap[rowPinID(i)].y = offsetY() + 16 + 16*i;
      }
      
      updateAttachedPositioning();
      //END Position pins et al
}


QString MatrixDisplay::colPinID( int col ) const
{
      return QString("col_%1").arg(QString::number(col));
}
QString MatrixDisplay::rowPinID( int row ) const
{
      return QString("row_%1").arg(QString::number(row));
}


void MatrixDisplay::stepNonLogic()
{
      double interval = 1./LINEAR_UPDATE_RATE;
      
      for ( unsigned i = 0; i < m_numCols; i++ )
      {
            for ( unsigned j = 0; j < m_numRows; j++ )
                  m_avgBrightness[i][j] += ECLed::brightness( m_pDiodes[i][j]->current() )*interval;
      }
      
      m_lastUpdatePeriod += interval;
}


void MatrixDisplay::drawShape( QPainter &p )
{
      if ( isSelected() )
            p.setPen(m_selectedCol);
      p.drawRect( boundingRect() );
      
      initPainter(p);
      
      const int _x = int(x()+offsetX());
      const int _y = int(y()+offsetY());
      
      // To avoid flicker, require at least a 10 ms sample before changing
      // the brightness
      double minUpdatePeriod = 0.0099;
      
      for ( int i = 0; i < int(m_numCols); i++ )
      {
            for ( int j = 0; j < int(m_numRows); j++ )
            {
                  if ( m_lastUpdatePeriod > minUpdatePeriod )
                        m_lastBrightness[i][j] = unsigned(m_avgBrightness[i][j]/m_lastUpdatePeriod);
                  
                  double _b = m_lastBrightness[i][j];
                  
                  QColor brush = QColor( uint(255-(255-_b)*(1-m_r)), uint(255-(255-_b)*(1-m_g)), uint(255-(255-_b)*(1-m_b)) );
                  p.setBrush(brush);
                  p.setPen( Qt::NoPen );
                  p.drawEllipse( _x+10+i*16, _y+10+j*16, 12, 12 );
            }
      }
      
      if ( m_lastUpdatePeriod > minUpdatePeriod )
      {
            m_lastUpdatePeriod = 0.0;
      
            for ( unsigned i = 0; i < m_numCols; i++ )
            {
                  for ( unsigned j = 0; j < m_numRows; j++ )
                        m_avgBrightness[i][j] = 0.0;
            }
      }
      
      deinitPainter(p);
}

Generated by  Doxygen 1.6.0   Back to index