You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktechlab/src/electronics/components/multiplexer.cpp

177 lines
4.7 KiB

/***************************************************************************
* Copyright (C) 2004-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 "multiplexer.h"
#include "logic.h"
#include "libraryitem.h"
#include <kiconloader.h>
#include <tdelocale.h>
#include <cmath>
Item* Multiplexer::construct( ItemDocument *itemDocument, bool newItem, const char *id )
{
return new Multiplexer( (ICNDocument*)itemDocument, newItem, id );
}
LibraryItem* Multiplexer::libraryItem()
{
return new LibraryItem(
TQString("ec/multiplexer"),
i18n("Multiplexer"),
i18n("Integrated Circuits"),
"ic1.png",
LibraryItem::lit_component,
Multiplexer::construct
);
}
Multiplexer::Multiplexer( ICNDocument *icnDocument, bool newItem, const char *id )
: Component( icnDocument, newItem, (id) ? id : "multiplexer" )
{
m_name = i18n("Multiplexer");
m_desc = i18n("Combines the input data stream into one single stream. The value of the input selected by the \"A\" inputs is passed to the output.");
m_output = 0l;
createProperty( "addressSize", Variant::Type::Int );
property("addressSize")->setCaption( i18n("Address Size") );
property("addressSize")->setMinValue(1);
property("addressSize")->setMaxValue(8);
property("addressSize")->setValue(1);
// For backwards compatibility
createProperty( "numInput", Variant::Type::Int );
property("numInput")->setMinValue(-1);
property("numInput")->setValue(-1);
property("numInput")->setHidden(true);
}
Multiplexer::~Multiplexer()
{
}
void Multiplexer::dataChanged()
{
if ( hasProperty("numInput") && dataInt("numInput") != -1 )
{
int addressSize = int( std::ceil( std::log( (double)dataInt("numInput") ) / std::log(2.0) ) );
property("numInput")->setValue(-1);
if ( addressSize < 1 )
addressSize = 1;
else if ( addressSize > 8 )
addressSize = 8;
// This function will get called again when we set the value of numInput
property("addressSize")->setValue(addressSize);
return;
}
if ( hasProperty("numInput") )
{
m_variantData["numInput"]->deleteLater();
m_variantData.remove("numInput");
}
initPins( unsigned(dataInt("addressSize")) );
}
void Multiplexer::inStateChanged( bool /*state*/ )
{
unsigned long long pos = 0;
for ( unsigned i = 0; i < m_aLogic.size(); ++i )
{
if ( m_aLogic[i]->isHigh() )
pos += 1 << i;
}
m_output->setHigh( m_xLogic[pos]->isHigh() );
}
void Multiplexer::initPins( unsigned newAddressSize )
{
unsigned oldAddressSize = m_aLogic.size();
unsigned long long oldXLogicCount = m_xLogic.size();
unsigned long long newXLogicCount = 1 << newAddressSize;
if ( newXLogicCount == oldXLogicCount )
return;
TQStringList pins;
const int length = newAddressSize + newXLogicCount;
for ( unsigned i=0; i<newAddressSize; ++i )
pins += "A"+TQString::number(i);
for ( unsigned i=0; i<newXLogicCount; ++i )
pins += "X"+TQString::number(i);
for ( int i=0; i<(length-(length%2))/2; ++i )
pins += "";
pins += "X";
for ( int i=0; i<((length+(length%2))/2)-1; ++i )
pins += "";
initDIPSymbol( pins, 64 );
initDIP(pins);
ECNode *node;
if (!m_output)
{
node = ecNodeWithID("X");
m_output = createLogicOut( node, false );
}
if ( newXLogicCount > oldXLogicCount )
{
m_xLogic.resize(newXLogicCount);
for ( unsigned i=oldXLogicCount; i<newXLogicCount; ++i )
{
node = ecNodeWithID("X"+TQString::number(i));
m_xLogic.insert( i, createLogicIn(node) );
m_xLogic[i]->setCallback( this, (CallbackPtr)(&Multiplexer::inStateChanged) );
}
m_aLogic.resize(newAddressSize);
for ( unsigned i=oldAddressSize; i<newAddressSize; ++i )
{
node = ecNodeWithID("A"+TQString::number(i));
m_aLogic.insert( i, createLogicIn(node) );
m_aLogic[i]->setCallback( this, (CallbackPtr)(&Multiplexer::inStateChanged) );
}
}
else
{
for ( unsigned i = newXLogicCount; i < oldXLogicCount; ++i )
{
TQString id = "X"+TQString::number(i);
removeDisplayText(id);
removeElement( m_xLogic[i], false );
removeNode(id);
}
m_xLogic.resize(newXLogicCount);
for ( unsigned i = newAddressSize; i < oldAddressSize; ++i )
{
TQString id = "A"+TQString::number(i);
removeDisplayText(id);
removeElement( m_aLogic[i], false );
removeNode(id);
}
m_aLogic.resize(newAddressSize);
}
}