diff options
Diffstat (limited to 'src/electronics/components/binarycounter.cpp')
-rw-r--r-- | src/electronics/components/binarycounter.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/electronics/components/binarycounter.cpp b/src/electronics/components/binarycounter.cpp new file mode 100644 index 0000000..f278104 --- /dev/null +++ b/src/electronics/components/binarycounter.cpp @@ -0,0 +1,186 @@ +/*************************************************************************** + * Copyright (C) 2003-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 "binarycounter.h" + +#include "logic.h" +#include "libraryitem.h" + +#include <kiconloader.h> +#include <klocale.h> + +Item* BinaryCounter::construct( ItemDocument *itemDocument, bool newItem, const char *id ) +{ + return new BinaryCounter( (ICNDocument*)itemDocument, newItem, id ); +} + +LibraryItem* BinaryCounter::libraryItem() +{ + QStringList ids; + ids << "ec/binary_counter" << "ec/4_bit_binary_counter"; + return new LibraryItem( + ids, + i18n("Binary Counter"), + i18n("Integrated Circuits"), + "ic1.png", + LibraryItem::lit_component, + BinaryCounter::construct + ); +} + +BinaryCounter::BinaryCounter( ICNDocument *icnDocument, bool newItem, const char *id ) + : Component( icnDocument, newItem, id ? id : "binary_counter" ) +{ + m_name = i18n("Binary Counter"); + m_desc = i18n("Holds an internal count, which changes when the clock input <i>></i> pin is pulsed.<br><br>" + "Normal operation: <i>en</i> (Enable) and <i>u/d</i> (Up/Down) are held high, <i>r</i> (Reset) is low."); + + enLogic = inLogic = rLogic = udLogic = 0L; + + b_reset = false; + b_triggerHigh = true; + b_oldIn = false; + m_value = 0; + b_en = false; + b_ud = false; + m_numBits = 0; + m_maxValue = false; + m_bDoneLogicIn = false; + + createProperty( "trig", Variant::Type::Select ); + property("trig")->setCaption( i18n("Trigger Edge") ); + property("trig")->setAllowed( QStringList::split( ',', "Rising,Falling" ) ); + property("trig")->setValue("Rising"); + + createProperty( "bitcount", Variant::Type::Int ); + property("bitcount")->setCaption( i18n("Bit Count") ); + property("bitcount")->setMinValue(1); + property("bitcount")->setMaxValue(26); + property("bitcount")->setValue(4); +} + + +BinaryCounter::~BinaryCounter() +{ +} + + +void BinaryCounter::dataChanged() +{ + initPins( dataInt("bitcount") ); + + b_triggerHigh = dataString("trig") == "Rising"; + setDisplayText( ">", b_triggerHigh ? "^>" : "_>" ); +} + + +void BinaryCounter::initPins( unsigned numBits ) +{ + if ( m_numBits == numBits ) + return; + + QStringList pins; + pins << "en" << ">" << "u/d" << "r"; + + for ( int i = 0; i < QABS(4-int(numBits)); i++ ) + pins << ""; + + for ( int i = numBits-1; i >= 0; i-- ) + pins << QChar('A'+i); + + initDIPSymbol( pins, 64 ); + initDIP(pins); + + if ( m_numBits < numBits ) + { + for ( unsigned i = m_numBits; i < numBits; i++ ) + m_pLogicOut[i] = createLogicOut( ecNodeWithID( QChar('A'+i) ), false ); + } + else + { + for ( unsigned i = numBits; i < m_numBits; i++ ) + { + QString id = QChar('A'+i); + removeElement( m_pLogicOut[i], false ); + removeDisplayText(id); + removeNode(id); + } + } + + m_numBits = numBits; + m_maxValue = (1<<m_numBits)-1; + + if (!m_bDoneLogicIn) + { + enLogic = createLogicIn( ecNodeWithID("en") ); + inLogic = createLogicIn( ecNodeWithID(">") ); + rLogic = createLogicIn( ecNodeWithID("r") ); + udLogic = createLogicIn( ecNodeWithID("u/d") ); + + enLogic->setCallback( this, (CallbackPtr)(&BinaryCounter::enStateChanged) ); + inLogic->setCallback( this, (CallbackPtr)(&BinaryCounter::inStateChanged) ); + rLogic->setCallback( this, (CallbackPtr)(&BinaryCounter::rStateChanged) ); + udLogic->setCallback( this, (CallbackPtr)(&BinaryCounter::udStateChanged) ); + + m_bDoneLogicIn = true; + } + + outputValue(); +} + + +void BinaryCounter::inStateChanged( bool state ) +{ + if ( (state != b_oldIn) && b_en && !b_reset && state == b_triggerHigh ) + { + m_value += (b_ud) ? 1 : -1; + + if ( m_value < 0 ) + m_value = m_maxValue; + + else if ( m_value > m_maxValue ) + m_value = 0; + + outputValue(); + } + + b_oldIn = state; +} + + +void BinaryCounter::rStateChanged( bool state ) +{ + b_reset = state; + if (b_reset) + { + m_value = 0; + outputValue(); + } +} + + +void BinaryCounter::enStateChanged( bool state ) +{ + b_en = state; +} + + +void BinaryCounter::udStateChanged( bool state ) +{ + b_ud = state; +} + + +void BinaryCounter::outputValue() +{ + for ( unsigned i = 0; i < m_numBits; i++ ) + m_pLogicOut[i]->setHigh( m_value & (1 << i) ); +} + |