Logo Search packages:      
Sourcecode: ktechlab version File versions

logic.cpp

/***************************************************************************
 *   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 <vector>
#include "circuit.h"
#include "elementset.h"
#include "logic.h"
#include "matrix.h"
#include "simulator.h"
#include "src/core/ktlconfig.h"

LogicIn::LogicIn( LogicConfig config )
      : Element::Element()
{
      m_config = config;
      m_pCallbackFunction = 0l;
      m_numCNodes = 1;
      m_bLastState = false;
      m_pNextLogic = 0l;
      setLogic(getConfig());
}

LogicIn::~LogicIn()
{
      Simulator::self()->removeLogicInReferences(this);
}


00036 void LogicIn::setCallback( CallbackClass * object, CallbackPtr func )
{
      m_pCallbackFunction = func;
      m_pCallbackObject = object;
}


00043 void LogicIn::check()
{
      if (!b_status)
            return;
      
      bool newState;
      if (m_bLastState)
      {
            // Was high, will still be high unless voltage is less than falling trigger
            newState = p_cnode[0]->v > m_config.fallingTrigger;
      }
      else
      {
            // Was low, will still be low unless voltage is more than rising trigger
            newState = p_cnode[0]->v > m_config.risingTrigger;
      }
      
      if ( m_pCallbackFunction && (newState != m_bLastState) )
      {
            m_bLastState = newState;
            (m_pCallbackObject->*m_pCallbackFunction)(newState);
      }
      m_bLastState = newState;
}


00069 void LogicIn::setLogic( LogicConfig config )
{
      m_config = config;
      check();
}


00076 void LogicIn::setElementSet( ElementSet *c )
{
      if (c)
            m_pNextLogic = 0l;
      else
            m_cnodeI[0] = 0.;
      
      Element::setElementSet(c);
}


00087 void LogicIn::add_initial_dc()
{
}


00092 void LogicIn::updateCurrents()
{
}


00097 LogicConfig LogicIn::getConfig()
{
      LogicConfig c;
      c.risingTrigger = KTLConfig::logicRisingTrigger();
      c.fallingTrigger = KTLConfig::logicFallingTrigger();
      c.output = KTLConfig::logicOutputHigh();
      c.highImpedance = KTLConfig::logicOutputHighImpedance();
      c.lowImpedance = KTLConfig::logicOutputLowImpedance();
      return c;
}


LogicOut::LogicOut( LogicConfig config, bool _high )
      : LogicIn(config)
{
      m_bCanAddChanged = true;
      m_bOutputHighConductanceConst = false;
      m_bOutputLowConductanceConst = false;
      m_bOutputHighVoltageConst = false;
      m_pNextChanged[0] = m_pNextChanged[1] = 0l;
      m_pSimulator = 0l;
      m_bUseLogicChain = false;
      b_state = false;
      m_numCNodes = 1;
      m_vHigh = m_gHigh = m_gLow = 0.0;
      m_old_g_out = m_g_out = 0.0;
      m_old_v_out = m_v_out = 0.0;
      setHigh(_high);
      
      // Although we already call this function in LogicIn's constructor, our
      // virtual function will not have got called, so we have to call it again.
      setLogic(getConfig());
}

LogicOut::~LogicOut()
{
      if (!m_pSimulator)
            m_pSimulator = Simulator::self();
      
      // Note that although this function will get called in the destructor of
      // LogicIn, we must call it here as well as it needs to be called before
      // removeLogicOutReferences(this) is called.
      m_pSimulator->removeLogicInReferences(this);
      
      m_pSimulator->removeLogicOutReferences(this);
}


00145 void LogicOut::setUseLogicChain( bool use )
{
      if (!m_pSimulator)
            m_pSimulator = Simulator::self();
      
      m_bUseLogicChain = use;
      if (use)
            setElementSet(0l);
}


00156 void LogicOut::setElementSet( ElementSet *c )
{
      if (!m_pSimulator)
            m_pSimulator = Simulator::self();
      
      if (c)
      {
            m_bUseLogicChain = false;
            m_pNextChanged[0] = m_pNextChanged[1] = 0l;
      }
      
      // NOTE Make sure that the next two lines are the same as those in setHigh and setLogic
      m_g_out = b_state ? m_gHigh : m_gLow;
      m_v_out = b_state ? m_vHigh : 0.0;
      
      LogicIn::setElementSet(c);
}


00175 void LogicOut::setOutputHighConductance( double g )
{
      m_bOutputHighConductanceConst = true;
      if ( g == m_gHigh )
            return;
      m_gHigh = g;
      configChanged();
}


00185 void LogicOut::setOutputLowConductance( double g )
{
      m_bOutputLowConductanceConst = true;
      if ( g == m_gLow )
            return;
      m_gLow = g;
      configChanged();
}


00195 void LogicOut::setOutputHighVoltage( double v )
{
      m_bOutputHighVoltageConst = true;
      if ( v == m_vHigh )
            return;
      m_vHigh = v;
      configChanged();
}


00205 void LogicOut::setLogic( LogicConfig config )
{
      m_config = config;
      
      if (!m_bOutputHighConductanceConst)
            m_gHigh = 1.0/config.highImpedance;
      
      if (!m_bOutputLowConductanceConst)
            m_gLow = (config.lowImpedance == 0.0) ? 0.0 : 1.0/config.lowImpedance;
      
      if (!m_bOutputHighVoltageConst)
            m_vHigh = config.output;
      
      configChanged();
}


void LogicOut::configChanged()
{
      if (m_bUseLogicChain)
            return;
      
      if (p_eSet)
            p_eSet->setCacheInvalidated();
      
      // Re-add the DC stuff using the new values
      
      m_old_g_out = m_g_out;
      m_old_v_out = m_v_out;
      
      // NOTE Make sure that the next two lines are the same as those in setElementSet and setHigh
      m_g_out = b_state ? m_gHigh : m_gLow;
      m_v_out = b_state ? m_vHigh : 0.0;
      
      add_initial_dc();
      
      m_old_g_out = 0.;
      m_old_v_out = 0.;
      
      check();
}


00248 void LogicOut::add_map()
{
      if (!b_status) return;
      
      p_A->setUse( p_cnode[0]->n(), p_cnode[0]->n(), Map::et_variable, false );
}


00256 void LogicOut::add_initial_dc()
{
      if (!b_status)
            return;
      
      A_g( 0, 0 ) += m_g_out-m_old_g_out;
      b_i( 0 ) += m_g_out*m_v_out-m_old_g_out*m_old_v_out;
}

00265 void LogicOut::updateCurrents()
{
      if (m_bUseLogicChain)
      {
            m_cnodeI[0] = 0.;
            return;
      }
      if (!b_status) {
            return;
      }
      m_cnodeI[0] = (p_cnode[0]->v-m_v_out)*m_g_out;
}

00278 void LogicOut::setHigh( bool high )
{
      if ( high == b_state )
            return;
      
      if (m_bUseLogicChain)
      {
            b_state = high;
            
            for ( LogicIn * logic = this; logic; logic = logic->nextLogic() )
                  logic->setLastState(high);
            
            if (m_bCanAddChanged)
            {
                  m_pSimulator->addChangedLogic(this);
                  m_bCanAddChanged = false;
            }
      
            return;
      }
      
      m_old_g_out = m_g_out;
      m_old_v_out = m_v_out;
      
      // NOTE Make sure that the next two lines are the same as those in setElementSet and setLogic
      m_g_out = high ? m_gHigh : m_gLow;
      m_v_out = high ? m_vHigh : 0.0;
      
      add_initial_dc();
      
      m_old_g_out = 0.;
      m_old_v_out = 0.;
      
      b_state = high;
      
      if ( p_eSet && p_eSet->circuit()->canAddChanged() )
      {
            m_pSimulator->addChangedCircuit( p_eSet->circuit() );
            p_eSet->circuit()->setCanAddChanged(false);
      }
}


Generated by  Doxygen 1.6.0   Back to index