summaryrefslogtreecommitdiffstats
path: root/src/electronics/components/flipflop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/electronics/components/flipflop.cpp')
-rw-r--r--src/electronics/components/flipflop.cpp347
1 files changed, 347 insertions, 0 deletions
diff --git a/src/electronics/components/flipflop.cpp b/src/electronics/components/flipflop.cpp
new file mode 100644
index 0000000..5c55baf
--- /dev/null
+++ b/src/electronics/components/flipflop.cpp
@@ -0,0 +1,347 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * *
+ * 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 "flipflop.h"
+#include "icndocument.h"
+#include "logic.h"
+#include "libraryitem.h"
+#include "node.h"
+#include "simulator.h"
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <qpainter.h>
+
+
+//BEGIN class ECDFlipFlop
+Item* ECDFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECDFlipFlop( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECDFlipFlop::libraryItem()
+{
+ return new LibraryItem(
+ "ec/d_flipflop",
+ i18n("D Flip-Flop"),
+ i18n("Integrated Circuits"),
+ "ic3.png",
+ LibraryItem::lit_component,
+ ECDFlipFlop::construct );
+}
+
+ECDFlipFlop::ECDFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
+ : Component( icnDocument, newItem, (id) ? id : "d_flipflop" )
+{
+ m_name = i18n("D-Type Flip-Flop");
+ m_desc = i18n("The output state is set from the input state when the clock is pulsed.");
+
+ setSize( -32, -24, 64, 48 );
+
+ init2PinLeft( -8, 8 );
+ init2PinRight( -8, 8 );
+
+ m_prevD[0] = m_prevD[1] = false;
+ m_whichPrevD = 0;
+ m_prevDSimTime = 0;
+ m_pSimulator = Simulator::self();
+
+ m_bPrevClock = false;
+ m_pD = createLogicIn( m_pNNode[0] );
+ m_pClock = createLogicIn( m_pNNode[1] );
+ m_pQ = createLogicOut( m_pPNode[0], false );
+ m_pQBar = createLogicOut( m_pPNode[1], false );
+
+ setp = createLogicIn( createPin( 0, -32, 90, "set" ) );
+ rstp = createLogicIn( createPin( 0, 32, 270, "rst" ) );
+
+ addDisplayText( "D", QRect( -32, -16, 20, 16 ), "D" );
+ addDisplayText( ">", QRect( -32, 0, 20, 16 ), ">" );
+ addDisplayText( "Q", QRect( 12, -16, 20, 16 ), "Q" );
+ addDisplayText( "Q'", QRect( 12, 0, 20, 16 ), "Q'" );
+ addDisplayText( "Set", QRect( -16, -20, 32, 16 ), "Set" );
+ addDisplayText( "Rst", QRect( -16, 4, 32, 16 ), "Rst" );
+
+ m_pD->setCallback( this, (CallbackPtr)(&ECDFlipFlop::inputChanged) );
+ m_pClock->setCallback( this, (CallbackPtr)(&ECDFlipFlop::clockChanged) );
+ setp->setCallback( this, (CallbackPtr)(&ECDFlipFlop::asyncChanged) );
+ rstp->setCallback( this, (CallbackPtr)(&ECDFlipFlop::asyncChanged) );
+
+ inStateChanged(false);
+}
+
+ECDFlipFlop::~ECDFlipFlop()
+{
+}
+
+void ECDFlipFlop::asyncChanged(bool)
+{
+ bool set = setp->isHigh();
+ bool rst = rstp->isHigh();
+ if(set || rst)
+ {
+ m_pQ->setHigh(set);
+ m_pQBar->setHigh(rst);
+ }
+}
+
+void ECDFlipFlop::inputChanged( bool newState )
+{
+ unsigned long long simTime = m_pSimulator->time();
+ if ( (simTime == m_prevDSimTime) && (newState == m_prevD[m_whichPrevD]) )
+ return;
+
+ m_prevDSimTime = simTime;
+ m_whichPrevD = 1-m_whichPrevD;
+ m_prevD[m_whichPrevD] = newState;
+}
+
+void ECDFlipFlop::clockChanged( bool newState )
+{
+ bool set = setp->isHigh();
+ bool rst = rstp->isHigh();
+
+ bool fallingEdge = m_bPrevClock && !newState;
+ m_bPrevClock = newState;
+
+ if( set || rst ) return;
+
+ if (fallingEdge)
+ {
+ unsigned long long simTime = m_pSimulator->time();
+ bool d = ( simTime == m_prevDSimTime ) ? m_prevD[1-m_whichPrevD] : m_prevD[m_whichPrevD];
+
+ m_pQ->setHigh(d);
+ m_pQBar->setHigh(!d);
+ }
+}
+
+void ECDFlipFlop::inStateChanged(bool)
+{
+ // Only called when the flipflop is created.
+ m_pQ->setHigh(false);
+ m_pQBar->setHigh(true);
+}
+//END class ECDFlipFlop
+
+
+//BEGIN class ECJKFlipFlop
+Item* ECJKFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECJKFlipFlop( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECJKFlipFlop::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/jk_flipflop"),
+ i18n("JK Flip-Flop"),
+ i18n("Integrated Circuits"),
+ "ic3.png",
+ LibraryItem::lit_component,
+ ECJKFlipFlop::construct );
+}
+
+ECJKFlipFlop::ECJKFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
+ : Component( icnDocument, newItem, (id) ? id : "jk_flipflop" )
+{
+ m_name = i18n("JK-Type Flip-Flop");
+ m_desc = i18n("The output state is set according to J and K when the clock is pulsed.");
+
+ setSize( -32, -32, 64, 64 );
+
+ init3PinLeft( -16, 0, 16 );
+ init2PinRight( -16, 16 );
+
+ m_pJ = createLogicIn( m_pNNode[0] );
+ m_pClock = createLogicIn( m_pNNode[1] );
+ m_pK = createLogicIn( m_pNNode[2] );
+
+ m_pQ = createLogicOut( m_pPNode[0], false );
+ m_pQBar = createLogicOut( m_pPNode[1], false );
+
+ setp = createLogicIn( createPin( 0, -40, 90, "set" ) );
+ rstp = createLogicIn( createPin( 0, 40, 270, "rst" ) );
+
+ addDisplayText( "J", QRect( -32, -24, 20, 16 ), "J" );
+ addDisplayText( ">", QRect( -32, -8, 20, 16 ), ">" );
+ addDisplayText( "K", QRect( -32, 8, 20, 16 ), "K" );
+ addDisplayText( "Q", QRect( 12, -24, 20, 16 ), "Q" );
+ addDisplayText( "Q'", QRect( 12, 8, 20, 16 ), "Q'" );
+ addDisplayText( "Set", QRect( -16, -28, 32, 16 ), "Set" );
+ addDisplayText( "Rst", QRect( -16, 12, 32, 16 ), "Rst" );
+
+ m_pClock->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::clockChanged) );
+ setp->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::asyncChanged) );
+ rstp->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::asyncChanged) );
+
+ inStateChanged(false);
+}
+
+ECJKFlipFlop::~ECJKFlipFlop()
+{
+}
+
+void ECJKFlipFlop::clockChanged(bool newvalue)
+{
+ bool j = m_pJ->isHigh();
+ bool k = m_pK->isHigh();
+ bool set = setp->isHigh();
+ bool rst = rstp->isHigh();
+
+ if( set || rst ) return;
+
+// a JK flip-flop change state when clock do 1->0
+ if (!newvalue && (j || k)) {
+ if ( j && k ) {
+ m_pQ->setHigh(!prev_state);
+ m_pQBar->setHigh(prev_state);
+ prev_state = !prev_state;
+ } else {
+ // (J=1 && K=0) || (J=0 && K=1)
+ m_pQ->setHigh(j);
+ m_pQBar->setHigh(k);
+ prev_state = j;
+ }
+ }
+}
+
+void ECJKFlipFlop::asyncChanged(bool)
+{
+ bool set = setp->isHigh();
+ bool rst = rstp->isHigh();
+
+ if (set || rst) {
+ m_pQ->setHigh(set);
+ m_pQBar->setHigh(rst);
+ prev_state = set;
+ }
+}
+
+void ECJKFlipFlop::inStateChanged(bool)
+{
+ m_pQBar->setHigh(true);
+ m_pQ->setHigh(false);
+ prev_state = false;
+}
+//END class ECJKFlipFlop
+
+
+//BEGIN class ECSRFlipFlop
+Item* ECSRFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
+{
+ return new ECSRFlipFlop( (ICNDocument*)itemDocument, newItem, id );
+}
+
+LibraryItem* ECSRFlipFlop::libraryItem()
+{
+ return new LibraryItem(
+ QString::QString("ec/sr_flipflop"),
+ i18n("SR Flip-Flop"),
+ i18n("Integrated Circuits"),
+ "ic3.png",
+ LibraryItem::lit_component,
+ ECSRFlipFlop::construct );
+}
+
+ECSRFlipFlop::ECSRFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
+ : Component( icnDocument, newItem, (id) ? id : "sr_flipflop" )
+{
+ m_name = i18n("SR Flip-Flop");
+ m_desc = i18n("The output is made high by holding <i>set</i> high, and low by holding <i>reset</i> high.");
+
+ setSize( -24, -24, 48, 48 );
+
+ init2PinLeft( -8, 8 );
+ init2PinRight( -8, 8 );
+
+ m_pS = createLogicIn( m_pNNode[0] );
+ m_pR = createLogicIn( m_pNNode[1] );
+ m_pQ = createLogicOut( m_pPNode[0], true );
+ m_pQBar = createLogicOut( m_pPNode[1], false );
+
+ old_q1 = true;
+ old_q2 = false;
+ m_pQ->setHigh(old_q1);
+ m_pQBar->setHigh(old_q2);
+
+ addDisplayText( "S", QRect( -24, -16, 20, 16 ), "S" );
+ addDisplayText( "R", QRect( -24, 0, 20, 16 ), "R" );
+ addDisplayText( "Q", QRect( 4, -16, 20, 16 ), "Q" );
+ addDisplayText( "Q'", QRect( 4, 0, 20, 16 ), "Q'" );
+
+ m_pS->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
+ m_pR->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
+ m_pQ->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
+ m_pQBar->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
+}
+
+ECSRFlipFlop::~ECSRFlipFlop()
+{
+}
+
+void ECSRFlipFlop::inStateChanged(bool)
+{
+ // Q = v_q1, Q-bar = v_q2
+ bool new_q1 = false;
+ bool new_q2 = false;
+
+ bool s = m_pS->isHigh();
+ bool r = m_pR->isHigh();
+ bool q1 = m_pQ->isHigh();
+ bool q2 = m_pQBar->isHigh();
+
+ // Easy ones to do :-)
+ if (!q1) new_q2 = true;
+ if (!q2) new_q1 = true;
+
+ if ( q1 && q2 )
+ {
+ if ( s && !r )
+ {
+ new_q1 = true;
+ new_q2 = false;
+ }
+ else if ( !s && r )
+ {
+ new_q1 = false;
+ new_q2 = true;
+ }
+ else if ( s && r )
+ {
+ new_q1 = old_q1;
+ new_q2 = old_q2;
+ }
+ else if ( !s && !r )
+ {
+ new_q1 = false;
+ new_q2 = false;
+ }
+ }
+ else if ( q1 && !q2 )
+ {
+ // Note: We only need to set the value of v_q2
+ if ( r && !s ) new_q2 = true;
+ else new_q2 = false;
+ }
+ else if ( !q1 && q2 )
+ {
+ // Note: We only need to set the value of v_q1
+ if ( s && !r ) new_q1 = true;
+ else new_q1 = false;
+ }
+
+ old_q1 = new_q1;
+ old_q2 = new_q2;
+
+ m_pQ->setHigh(new_q1);
+ m_pQBar->setHigh(new_q2);
+}
+//END class ECSRFlipFlop