www.pudn.com > qtdso-0.3.1.rar > simulator.cpp


//======================================================================
// File:		simulator.cpp
// Author:	Matthias Toussaint
// Created:	Sat Jul  6 21:07:22 CEST 2002
//----------------------------------------------------------------------
// Permission to use, copy, modify, and distribute this software and its
// documentation  for any  purpose and  without fee is  hereby  granted,
// provided  that below copyright notice appear  in all copies  and that
// both  that  copyright  notice and  this permission  notice  appear in
// supporting documentation.
// 
// This  file is  provided AS IS  with no  warranties  of any kind.  The
// author shall  have no liability  with respect  to the infringement of
// copyrights, trade  secrets  or any patents by  this file  or any part
// thereof.  In no event will the author be liable  for any lost revenue
// or profits or other special, indirect and consequential damages.
//----------------------------------------------------------------------
// (c) 2000-2002 Matthias Toussaint
//======================================================================

#include 
#include 

#include 

Simulator::Simulator() :
  Dso( Dso::Simulator, 8 )
{
  m_outBuffer[0] = new unsigned [4096];
  m_outBuffer[1] = new unsigned [4096];
  
  m_buffer[0] = new unsigned [4096];
  m_buffer[1] = new unsigned [4096];
  
  // use ring buffer to simulate pre-trigger
  // 1024 values pre trigger memory 
  // seems to be what Velleman PCi64 does
  //
  m_ringBuffer[0] = new unsigned [1024];
  m_ringBuffer[1] = new unsigned [1024];
  
  m_freq[0] = 100.;
  m_freq[1] = 100.;
  
  m_waveform[0] = Sine;
  m_waveform[1] = Sine;
  
  m_threshold[0] = 0.0;
  
  m_addNoise[0] = false;
  m_addNoise[1] = false;
  
  m_addJitter[0] = false;
  m_addJitter[1] = false;
  
  m_addPhaseJitter[0] = true;
  m_addPhaseJitter[1] = false;
  
  m_vPp[0] = 0.1;
  m_vPp[1] = 0.1;
  
  m_cnt = 0;
  
  m_acqLength = 4096;
  m_numSamples = 4096;
    
  setTimeBase( Dso::TB1ms );
  setVoltsDiv( 0, Dso::VD5v );
  setVoltsDiv( 1, Dso::VD5v );
  setTriggerEnabled( false );
  setTriggerChannel( 0 );
  setTriggerRaising( true );
  setTriggerLevel( 128 );
  
  m_halfValue = (m_maxValue+1) >> 1;

  for (int i=0; i<4096; ++i)
  {
    m_outBuffer[0][i] = m_outBuffer[1][i] = m_halfValue;
  }
  
  m_defaultStep = -5;
  
  m_preTriggerSize = 1024;
  
  // fill tables
  //
  float w = 0.0f;
  float step = M_PI/8192.0f;
  
  for (int i=0; i<16384; ++i)
  {
    m_sineTable[i] = cos( w );
    w += step;
  }
  
  for (int i=0; i<8192; ++i)
  {
    m_rectTable[i] = 1.0f;
  }  
  for (int i=8192; i<16384; ++i)
  {
    m_rectTable[i] = -1.0f;
  }
  
  w = 1.0f;
  step = 2.0f/8192.0f;
  
  for (int i=0; i<8192; ++i)
  {
    m_sawtoothTable[i] = w;
    w -= step;
  }  
  for (int i=8192; i<16384; ++i)
  {
    w += step;
    m_sawtoothTable[i] = w;
  }
  
  m_counter[0] = m_counter[1] = 0;
  m_counterStep[0][0] = m_counterStep[0][1] = 1;
  m_counterStep[1][0] = m_counterStep[1][1] = 1;
  
  m_dutyCycle[0] = m_dutyCycle[1] = 0.5;
}

Simulator::~Simulator()
{
}

bool
Simulator::hasTimeBase( Dso::TimeBase timeBase ) const
{
  return (timeBase >= Dso::TB100ms && timeBase <= Dso::TB100ns);
}

bool
Simulator::hasVoltsDiv( Dso::VoltsDiv voltsDiv ) const
{
  return (voltsDiv >= Dso::VD10v && voltsDiv <= Dso::VD5mv);
}

void
Simulator::waveformChangedSLOT( unsigned channel, Simulator::Waveform wf )
{
  m_waveform[channel] = wf;
}

void
Simulator::frequencyChangedSLOT( unsigned channel, float freq )
{
  m_freq[channel] = freq;
}

void
Simulator::vppChangedSLOT( unsigned channel, float vpp )
{
  m_vPp[channel] = vpp;
}

void
Simulator::jitterToggledSLOT( unsigned channel, bool on )
{
  m_addJitter[channel] = on;
}

void
Simulator::phaseJitterToggledSLOT( unsigned channel, bool on )
{
  m_addPhaseJitter[channel] = on;
}

void
Simulator::noiseToggledSLOT( unsigned channel, bool on )
{
  m_addNoise[channel] = on;
}

void
Simulator::symetryChangedSLOT( unsigned channel, int sym )
{
  m_dutyCycle[channel] = (10.0+sym)/20.0;
}

void
Simulator::run()
{
  //while (1)
  {
    //if (!m_hasNewData)
    {
      setupSimulator();

      // first fill buffer
      //
      for (int i=0; i<1024; ++i)
      {
        m_ringBuffer[0][i] = sample( 0 );
        m_ringBuffer[1][i] = sample( 1 );

        ++m_cnt;
      }

      // now wait for trigger condition
      // 
      if (m_triggerEnabled)
      {
        if (m_triggerRaising)
        {
          for (int i=0; i<4096; ++i)
          {
            m_ringBuffer[0][m_ringBufferPointer] = sample( 0 );
            m_ringBuffer[1][m_ringBufferPointer] = sample( 1 );

            ++m_cnt;
            ++m_ringBufferPointer;
            m_ringBufferPointer &= 0x3ff;

            if (raisingTrigger())
            {
              break;
            }
          }
        }
        else
        {
          for (int i=0; i<4096; ++i)
          {
            m_ringBuffer[0][m_ringBufferPointer] = sample( 0 );
            m_ringBuffer[1][m_ringBufferPointer] = sample( 1 );

            ++m_cnt;
            ++m_ringBufferPointer;
            m_ringBufferPointer &= 0x3ff;

            if (fallingTrigger())
            {
              break;
            }
          }
        }
      }

      // copy ring buffer into first values
      //
      for (int i=0; i<1024; ++i)
      {
        m_buffer[0][i] = m_ringBuffer[0][m_ringBufferPointer];
        m_buffer[1][i] = m_ringBuffer[1][m_ringBufferPointer];

        ++m_ringBufferPointer;
        m_ringBufferPointer &= 0x3ff;
      }

      // fill remaining samples
      //
      for (int i=1024; i<4096; ++i)
      {
        m_buffer[0][i] = sample( 0 ); 
        m_buffer[1][i] = sample( 1 ); 

        ++m_cnt;
      }

      // synchronize with reading from widget
      //
      m_mutex.lock();

      memcpy( m_outBuffer[0], m_buffer[0], 4096*sizeof(unsigned) );
      memcpy( m_outBuffer[1], m_buffer[1], 4096*sizeof(unsigned) );

      m_hasNewData = true;

      m_mutex.unlock();
    }
    
    //msleep( 20 );
  }
}

void
Simulator::setupSimulator()
{
  float ts = 1./160e3;
  float perDiv = m_halfValue/8.0f;
  
  m_ringBufferPointer = 0;

  switch (m_timeBase)
  {
  case TB100ns:
    ts = 32.0*1e7;
    break;  
  case TB200ns:
    ts = 32.0*5e6;
    break;  
  case TB500ns:
    ts = 32.0*2e6;
    break;  
  case TB1us:
    ts = 32.0*1e6;
    break;  
  case TB2us:
    ts = 32.0*5e5;
    break;  
  case TB5us:
    ts = 32.0*2e5;
    break;  
  case TB10us:
    ts = 32.0*1e5;
    break;
  case TB20us:
    ts = 32.0*5e4;
    break;  
  case TB50us:
    ts = 32.0*2e4;
    break;  
  case TB100us:
    ts = 32.0*1e4;
    break;  
  case TB200us:
    ts = 32.0*5e3;
    break;  
  case TB500us:
    ts = 32.0*2e3;
    break;  
  case TB1ms:
    ts = 32.0*1e3;
    break;  
  case TB2ms:
    ts = 32.0*5e2;
    break;  
  case TB5ms:
    ts = 32.0*2e2;
    break;  
  case TB10ms:
    ts = 32.0*1e2;
    break;  
  case TB20ms:
    ts = 32.0*5e1;
    break;  
  case TB50ms:
    ts = 32.0*2e1;
    break;  
  case TB100ms:
    ts = 32.0*1e1;
    break;  
  default:
    ts = 1.;
    break;  
  }

  for (int i=0; i<2; ++i)
  {
    switch (m_voltsDiv[i])
    {
    case VD10v:
      m_vScale[i] = m_vPp[i] * perDiv / 10.0f;  
      break;
    case VD5v:
      m_vScale[i] = m_vPp[i] * perDiv / 5.0f;   
      break;
    case VD2v:
      m_vScale[i] = m_vPp[i] * perDiv / 2.0f;  
      break;
    case VD1v:
      m_vScale[i] = m_vPp[i] * perDiv;
      break;
    case VD500mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.5f;  
      break;
    case VD200mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.2f;  
      break;
    case VD100mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.1f;  
      break;
    case VD50mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.05f;  
      break;
    case VD20mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.02f;  
      break;
    case VD10mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.01f;  
      break;
    case VD5mv:
      m_vScale[i] = m_vPp[i] * perDiv / 0.005f;  
      break;
    default:
      m_vScale[i] = m_vPp[i] * perDiv;  
      break;
    }
  }
  
 // m_vScale[0] *= (float)m_maxValue / 2.0f / m_halfValue;
 // m_vScale[1] *= (float)m_maxValue / 2.0f / m_halfValue;

  double t1 = 2.0/(double)m_freq[0];
  
  m_counterStep[0][0] = (unsigned)((double)(1.0/t1/m_dutyCycle[0])/ts*16384.0/5.0 *
                                  (double)0x40000);
  
  m_counterStep[1][0] = (unsigned)((double)(1.0/t1/(1.0-m_dutyCycle[0]))/ts*16384.0/5.0 *
                                  (double)0x40000);
  
  double t2 = 2.0/(double)m_freq[1];
  
  m_counterStep[0][1] = (unsigned)((double)(1.0/t2/m_dutyCycle[1])/ts*16384.0/5.0 *
                                  (double)0x40000);
  
  m_counterStep[1][1] = (unsigned)((double)(1.0/t2/(1.0-m_dutyCycle[1]))/ts*16384.0/5.0 *
                                  (double)0x40000);
}

unsigned 
Simulator::sample( int channel )
{
  // it's a dds generator
  // the table is 14 bit -> 18bit for the divider
  //
  unsigned addr = (m_counter[channel] >> 18) & 0x3fff;
  const int raise = (addr >= 8192 ? 1 : 0);
  m_counter[channel] += m_counterStep[raise][channel];
  
  addr = (m_counter[channel] >> 18) & 0x3fff;
  
  float ret;
  
  switch (m_waveform[channel])
  {
  case Sine:
    ret = m_sineTable[addr]*m_vScale[channel];
    break;
  case Square:
    ret = m_rectTable[addr]*m_vScale[channel];
    break;
  case Sawtooth:
    ret = m_sawtoothTable[addr]*m_vScale[channel];
    break;
  }
  
  if (m_addNoise[channel])
  {
    ret += ((float)random()/(float)RAND_MAX-0.5) / 50.0;
  }
  
  ret += m_halfValue;
  
  if (ret < 0.0f) return 0;
  if (ret > m_maxValue) return (unsigned)m_maxValue;
  
  return (unsigned)ret;
  //return (unsigned)(ret* (float)m_maxValue + m_halfValue);
}

bool
Simulator::raisingTrigger() const
{
  const unsigned level = (int)((float)(m_triggerLevel & triggerBits()) * 
                            (float)maxValue() / 255.0 );

  if (m_ringBuffer[m_triggerChannel][m_ringBufferPointer] >= level)
  {
    int pointer = m_ringBufferPointer;
    pointer += 1022;
    pointer &= 0x3ff;
    
    if (m_ringBuffer[m_triggerChannel][pointer] < level)
    { 
      return true;
    }
  }
  
  return false;
}

bool
Simulator::fallingTrigger() const
{
  const unsigned level = (int)((float)(m_triggerLevel & triggerBits()) * 
                            (float)maxValue() / 255.0);

  if (m_ringBuffer[m_triggerChannel][m_ringBufferPointer] <= level)
  {
    int pointer = m_ringBufferPointer;
    pointer += 1022;
    pointer &= 0x3ff;
    
    if (m_ringBuffer[m_triggerChannel][pointer] > level)
    { 
      return true;
    }
  }
  
  return false;
}
void
Simulator::setTimeBase( Dso::TimeBase tb )
{
  //lockParam();
  
  m_timeBase = tb;
  m_step = -5;
  m_samplingFrequency = 32000000.;
  
  switch (tb)
  {
  case Dso::TB100ns:
    m_timeBaseSec = 0.0000001;
    m_samplingFrequency = 1600000000.;
    break;
  case Dso::TB200ns:
    m_timeBaseSec = 0.0000002;
    m_samplingFrequency = 800000000.;
    break;
  case Dso::TB500ns:
    m_timeBaseSec = 0.0000005;
    m_samplingFrequency = 320000000.;
    break;
  case Dso::TB1us:
    m_timeBaseSec = 0.000001;
    m_samplingFrequency = 160000000.;
    break;
  case Dso::TB2us:
    m_timeBaseSec = 0.000002;
    m_samplingFrequency = 80000000.;
    break;
  case Dso::TB5us:
    m_timeBaseSec = 0.000005;
    m_samplingFrequency = 32000000.;
    break;
  case Dso::TB10us:
    m_samplingFrequency = 16000000.;
    m_timeBaseSec = 0.00001;
    break;
  case Dso::TB20us:
    m_samplingFrequency = 8000000.;
    m_timeBaseSec = 0.00002;
    break;
  case Dso::TB50us:
    m_samplingFrequency = 3200000.;
    m_timeBaseSec = 0.00005;
    break;
  case Dso::TB100us:
    m_samplingFrequency = 1600000.;
    m_timeBaseSec = 0.0001;
    break;
  case Dso::TB200us:
    m_samplingFrequency = 800000.;
    m_timeBaseSec = 0.0002;
    break;
  case Dso::TB500us:
    m_samplingFrequency = 320000.;
    m_timeBaseSec = 0.0005;
    break;
  case Dso::TB1ms:
    m_samplingFrequency = 160000.;
    m_timeBaseSec = 0.001;
    break;
  case Dso::TB2ms:
    m_samplingFrequency = 80000.;
    m_timeBaseSec = 0.002;
    break;
  case Dso::TB5ms:
    m_samplingFrequency = 32000.;
    m_timeBaseSec = 0.005;
    break;
  case Dso::TB10ms:
    m_samplingFrequency = 16000.;
    m_timeBaseSec = 0.01;
    break;
  case Dso::TB20ms:
    m_samplingFrequency = 8000.;
    m_timeBaseSec = 0.02;
    break;
  case Dso::TB50ms:
    m_samplingFrequency = 3200.;
    m_timeBaseSec = 0.05;
    break;
  case Dso::TB100ms:
    m_samplingFrequency = 1600.;
    m_timeBaseSec = 0.1;
    break;
  }
  
  //unlockParam();
}

void
Simulator::setVoltsDiv( int channel, Dso::VoltsDiv vd )
{
  //lockParam();
  
  m_voltsDiv[channel] = vd;
  
  switch (vd)
  {
  case Dso::VD5mv:
    m_voltsDivVolts[channel] = 0.005;
    break;
  case Dso::VD10mv:
    m_voltsDivVolts[channel] = 0.01;
    break;
  case Dso::VD20mv:
    m_voltsDivVolts[channel] = 0.02;
    break;
  case Dso::VD50mv:
    m_voltsDivVolts[channel] = 0.05;
    break;
  case Dso::VD100mv:
    m_voltsDivVolts[channel] = 0.1;
    break;
  case Dso::VD200mv:
    m_voltsDivVolts[channel] = 0.2;
    break;
  case Dso::VD500mv:
    m_voltsDivVolts[channel] = 0.5;
    break;
  case Dso::VD1v:
    m_voltsDivVolts[channel] = 1.0;
    break;
  case Dso::VD2v:
    m_voltsDivVolts[channel] = 2.0;
    break;
  case Dso::VD5v:
    m_voltsDivVolts[channel] = 5.0;
    break;
  case Dso::VD10v:
    m_voltsDivVolts[channel] = 10.0;
    break;
  } 
  
  //unlockParam();
}