flipflop.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "flipflop.h"
00012 #include "icndocument.h"
00013 #include "logic.h"
00014 #include "libraryitem.h"
00015 #include "node.h"
00016 #include "simulator.h"
00017 
00018 #include <kiconloader.h>
00019 #include <klocale.h>
00020 #include <qpainter.h>
00021 
00022 
00023 //BEGIN class ECDFlipFlop
00024 Item* ECDFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00025 {
00026         return new ECDFlipFlop( (ICNDocument*)itemDocument, newItem, id );
00027 }
00028 
00029 LibraryItem* ECDFlipFlop::libraryItem()
00030 {
00031         return new LibraryItem(
00032                 "ec/d_flipflop",
00033                 i18n("D Flip-Flop"),
00034                 i18n("Integrated Circuits"),
00035                 "ic3.png",
00036                 LibraryItem::lit_component,
00037                 ECDFlipFlop::construct );
00038 }
00039 
00040 ECDFlipFlop::ECDFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
00041         : Component( icnDocument, newItem, (id) ? id : "d_flipflop" )
00042 {
00043         m_name = i18n("D-Type Flip-Flop");
00044         m_desc = i18n("The output state is set from the input state when the clock is pulsed.");
00045         
00046         setSize( -32, -24, 64, 48 );
00047 
00048         init2PinLeft( -8, 8 );
00049         init2PinRight( -8, 8 );
00050         
00051         m_prevD[0] = m_prevD[1] = false;
00052         m_whichPrevD = 0;
00053         m_prevDSimTime = 0;
00054         m_pSimulator = Simulator::self();
00055         
00056         m_bPrevClock = false;
00057         m_pD = createLogicIn( m_pNNode[0] );
00058         m_pClock = createLogicIn( m_pNNode[1] );
00059         m_pQ = createLogicOut( m_pPNode[0], false );
00060         m_pQBar = createLogicOut( m_pPNode[1], false );
00061         
00062         setp = createLogicIn( createPin( 0, -32, 90, "set" ) );
00063         rstp = createLogicIn( createPin( 0, 32, 270, "rst" ) );
00064         
00065         addDisplayText( "D",    QRect( -32,     -16,    20, 16 ), "D" );
00066         addDisplayText( ">",    QRect( -32,     0,              20, 16 ), ">" ); 
00067         addDisplayText( "Q",    QRect( 12,      -16,    20, 16 ), "Q" );
00068         addDisplayText( "Q'",   QRect( 12,      0,              20, 16 ), "Q'" );
00069         addDisplayText( "Set",  QRect( -16,     -20,    32, 16 ), "Set" );
00070         addDisplayText( "Rst",  QRect( -16,     4,              32, 16 ), "Rst" );
00071         
00072         m_pD->setCallback( this, (CallbackPtr)(&ECDFlipFlop::inputChanged) );
00073         m_pClock->setCallback( this, (CallbackPtr)(&ECDFlipFlop::clockChanged) );
00074         setp->setCallback( this, (CallbackPtr)(&ECDFlipFlop::asyncChanged) );
00075         rstp->setCallback( this, (CallbackPtr)(&ECDFlipFlop::asyncChanged) );
00076         
00077         inStateChanged(false);
00078 }
00079 
00080 ECDFlipFlop::~ECDFlipFlop()
00081 {
00082 }
00083 
00084 void ECDFlipFlop::asyncChanged(bool)
00085 {
00086         bool set = setp->isHigh();
00087         bool rst = rstp->isHigh();
00088         if(set || rst)
00089         {
00090                 m_pQ->setHigh(set);
00091                 m_pQBar->setHigh(rst);
00092         }
00093 }
00094 
00095 void ECDFlipFlop::inputChanged( bool newState )
00096 {
00097         unsigned long long simTime = m_pSimulator->time();
00098         if ( (simTime == m_prevDSimTime) && (newState == m_prevD[m_whichPrevD]) )
00099                 return;
00100         
00101         m_prevDSimTime = simTime;
00102         m_whichPrevD = 1-m_whichPrevD;
00103         m_prevD[m_whichPrevD] = newState;
00104 }
00105 
00106 void ECDFlipFlop::clockChanged( bool newState )
00107 {
00108         bool set = setp->isHigh();
00109         bool rst = rstp->isHigh();
00110         
00111         bool fallingEdge = m_bPrevClock && !newState;
00112         m_bPrevClock = newState;
00113         
00114         if( set || rst ) return;
00115         
00116         if (fallingEdge)
00117         {
00118                 unsigned long long simTime = m_pSimulator->time();
00119                 bool d = ( simTime == m_prevDSimTime ) ? m_prevD[1-m_whichPrevD] : m_prevD[m_whichPrevD];
00120                 
00121                 m_pQ->setHigh(d);
00122                 m_pQBar->setHigh(!d);
00123         }
00124 }
00125         
00126 void ECDFlipFlop::inStateChanged(bool)
00127 {
00128         // Only called when the flipflop is created.
00129         m_pQ->setHigh(false);
00130         m_pQBar->setHigh(true);
00131 }
00132 //END class ECDFlipFlop
00133 
00134 
00135 //BEGIN class ECJKFlipFlop
00136 Item* ECJKFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00137 {
00138         return new ECJKFlipFlop( (ICNDocument*)itemDocument, newItem, id );
00139 }
00140 
00141 LibraryItem* ECJKFlipFlop::libraryItem()
00142 {
00143         return new LibraryItem(
00144                 QString::QString("ec/jk_flipflop"),
00145                 i18n("JK Flip-Flop"),
00146                 i18n("Integrated Circuits"),
00147                 "ic3.png",
00148                 LibraryItem::lit_component,
00149                 ECJKFlipFlop::construct );
00150 }
00151 
00152 ECJKFlipFlop::ECJKFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
00153         : Component( icnDocument, newItem, (id) ? id : "jk_flipflop" )
00154 {
00155         m_name = i18n("JK-Type Flip-Flop");
00156         m_desc = i18n("The output state is set according to J and K when the clock is pulsed.");
00157         
00158         setSize( -32, -32, 64, 64 );
00159 
00160         init3PinLeft( -16, 0, 16 );
00161         init2PinRight( -16, 16 );
00162         
00163         m_pJ = createLogicIn( m_pNNode[0] );
00164         m_pClock = createLogicIn( m_pNNode[1] );
00165         m_pK = createLogicIn( m_pNNode[2] );
00166         
00167         m_pQ = createLogicOut( m_pPNode[0], false );
00168         m_pQBar = createLogicOut( m_pPNode[1], false );
00169 
00170         setp = createLogicIn( createPin( 0, -40, 90, "set" ) );
00171         rstp = createLogicIn( createPin( 0, 40, 270, "rst" ) );
00172         
00173         addDisplayText( "J",    QRect( -32,     -24,    20, 16 ), "J" );
00174         addDisplayText( ">",    QRect( -32,     -8,             20, 16 ), ">" );
00175         addDisplayText( "K",    QRect( -32,     8,              20, 16 ), "K" ); 
00176         addDisplayText( "Q",    QRect( 12,      -24,    20, 16 ), "Q" );
00177         addDisplayText( "Q'",   QRect( 12,      8,              20, 16 ), "Q'" );
00178         addDisplayText( "Set",  QRect( -16,     -28,    32, 16 ), "Set" );
00179         addDisplayText( "Rst",  QRect( -16,     12,             32, 16 ), "Rst" );
00180                 
00181         m_pClock->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::clockChanged) );
00182         setp->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::asyncChanged) );
00183         rstp->setCallback( this, (CallbackPtr)(&ECJKFlipFlop::asyncChanged) );
00184         
00185         inStateChanged(false);
00186 }
00187 
00188 ECJKFlipFlop::~ECJKFlipFlop()
00189 {
00190 }
00191 
00192 void ECJKFlipFlop::clockChanged(bool newvalue) 
00193 {
00194         bool j = m_pJ->isHigh();
00195         bool k = m_pK->isHigh();
00196         bool set = setp->isHigh();
00197         bool rst = rstp->isHigh();
00198         
00199         if( set || rst ) return;
00200         
00201 // a JK flip-flop change state when clock do 1->0
00202         if (!newvalue && (j || k)) {
00203                 if ( j && k ) {
00204                         m_pQ->setHigh(!prev_state);
00205                         m_pQBar->setHigh(prev_state);
00206                         prev_state = !prev_state;
00207                 } else {
00208                         // (J=1 && K=0) || (J=0 && K=1)
00209                         m_pQ->setHigh(j);
00210                         m_pQBar->setHigh(k);
00211                         prev_state = j;
00212                 }       
00213         }
00214 }
00215 
00216 void ECJKFlipFlop::asyncChanged(bool)
00217 {
00218         bool set = setp->isHigh();
00219         bool rst = rstp->isHigh();
00220         
00221         if (set || rst) {
00222                 m_pQ->setHigh(set);
00223                 m_pQBar->setHigh(rst);
00224                 prev_state = set;
00225         }
00226 }
00227         
00228 void ECJKFlipFlop::inStateChanged(bool)
00229 {
00230         m_pQBar->setHigh(true);
00231         m_pQ->setHigh(false);
00232         prev_state = false;
00233 }
00234 //END class ECJKFlipFlop
00235 
00236 
00237 //BEGIN class ECSRFlipFlop
00238 Item* ECSRFlipFlop::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00239 {
00240         return new ECSRFlipFlop( (ICNDocument*)itemDocument, newItem, id );
00241 }
00242 
00243 LibraryItem* ECSRFlipFlop::libraryItem()
00244 {
00245         return new LibraryItem(
00246                 QString::QString("ec/sr_flipflop"),
00247                 i18n("SR Flip-Flop"),
00248                 i18n("Integrated Circuits"),
00249                 "ic3.png",
00250                 LibraryItem::lit_component,
00251                 ECSRFlipFlop::construct );
00252 }
00253 
00254 ECSRFlipFlop::ECSRFlipFlop( ICNDocument *icnDocument, bool newItem, const char *id )
00255         : Component( icnDocument, newItem, (id) ? id : "sr_flipflop" )
00256 {
00257         m_name = i18n("SR Flip-Flop");
00258         m_desc = i18n("The output is made high by holding <i>set</i> high, and low by holding <i>reset</i> high.");
00259         
00260         setSize( -24, -24, 48, 48 );
00261 
00262         init2PinLeft( -8, 8 );
00263         init2PinRight( -8, 8 );
00264         
00265         m_pS = createLogicIn( m_pNNode[0] );
00266         m_pR = createLogicIn( m_pNNode[1] );
00267         m_pQ = createLogicOut( m_pPNode[0], true );
00268         m_pQBar = createLogicOut( m_pPNode[1], false );
00269         
00270         old_q1 = true;
00271         old_q2 = false;
00272         m_pQ->setHigh(old_q1);
00273         m_pQBar->setHigh(old_q2);
00274         
00275         addDisplayText( "S", QRect( -24, -16, 20, 16 ), "S" );
00276         addDisplayText( "R", QRect( -24, 0, 20, 16 ), "R" );
00277         addDisplayText( "Q", QRect( 4, -16, 20, 16 ), "Q" );
00278         addDisplayText( "Q'", QRect( 4, 0, 20, 16 ), "Q'" );
00279         
00280         m_pS->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
00281         m_pR->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
00282         m_pQ->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
00283         m_pQBar->setCallback( this, (CallbackPtr)(&ECSRFlipFlop::inStateChanged) );
00284 }
00285 
00286 ECSRFlipFlop::~ECSRFlipFlop()
00287 {
00288 }
00289 
00290 void ECSRFlipFlop::inStateChanged(bool)
00291 {
00292         // Q = v_q1, Q-bar = v_q2
00293         bool new_q1 = false;
00294         bool new_q2 = false;
00295         
00296         bool s = m_pS->isHigh();
00297         bool r = m_pR->isHigh();
00298         bool q1 = m_pQ->isHigh();
00299         bool q2 = m_pQBar->isHigh();
00300         
00301         // Easy ones to do :-)
00302         if (!q1) new_q2 = true;
00303         if (!q2) new_q1 = true;
00304         
00305         if ( q1 && q2 )
00306         {
00307                 if ( s && !r )
00308                 {
00309                         new_q1 = true;
00310                         new_q2 = false;
00311                 }
00312                 else if ( !s && r )
00313                 {
00314                         new_q1 = false;
00315                         new_q2 = true;
00316                 }
00317                 else if ( s && r )
00318                 {
00319                         new_q1 = old_q1;
00320                         new_q2 = old_q2;
00321                 }
00322                 else if ( !s && !r )
00323                 {
00324                         new_q1 = false;
00325                         new_q2 = false;
00326                 }
00327         }
00328         else if ( q1 && !q2 )
00329         {
00330                 // Note: We only need to set the value of v_q2
00331                 if ( r && !s ) new_q2 = true;
00332                 else new_q2 = false;
00333         }
00334         else if ( !q1 && q2 )
00335         {
00336                 // Note: We only need to set the value of v_q1
00337                 if ( s && !r ) new_q1 = true;
00338                 else new_q1 = false;
00339         }
00340         
00341         old_q1 = new_q1;
00342         old_q2 = new_q2;
00343         
00344         m_pQ->setHigh(new_q1);
00345         m_pQBar->setHigh(new_q2);
00346 }
00347 //END class ECSRFlipFlop

Generated on Tue May 8 17:05:29 2007 for KTechLab by  doxygen 1.5.1