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


//======================================================================
// File:		pcs64i.cpp
// Author:	Matthias Toussaint
// Created:	Mon Jun 10 17:23:31 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 
#include 

#include 
#include 

#include 

Pcs64i::Pcs64i() :
  Dso( Dso::PCS64i, 8 )
{
  m_numSamples = 4096;
  m_preTriggerSize = 1024;
  
  m_outBuffer[0] = new unsigned [m_numSamples];
  m_outBuffer[1] = new unsigned [m_numSamples];
  
  m_buffer[0] = new unsigned [m_numSamples];
  m_buffer[1] = new unsigned [m_numSamples];
  
  int ports = ieee1284_find_ports( &m_list, 0 );
  
  if (E1284_OK == ports)
  {
    if (0 == m_list.portc)
    {
      std::cerr << "Couldn't find ports" << std::endl;
      abort();
    }
    else
    {
      std::cerr << "find ports: " << m_list.portc << " Using first" << std::endl;
      std::cerr << "name: " << m_list.portv[0]->name << std::endl;
      std::cerr << "device: " << m_list.portv[0]->filename << std::endl;
      m_port = m_list.portv[0];
    }
  }
  else
  {
    std::cerr << "ports fucked up!" << std::endl;
    abort();
  }
  
  setTimeBase( Dso::TB1ms );
  setVoltsDiv( 0, Dso::VD5v );
  setVoltsDiv( 1, Dso::VD5v );
  setTriggerEnabled( false );
  setTriggerChannel( 0 );
  setTriggerRaising( true );
  setTriggerLevel( 128 );
  
  m_channelEnable[0] = true;
  m_channelEnable[1] = true;
  
  m_defaultStep = -5;
  
  calibrate();
  
  connectToHardware();
}

Pcs64i::~Pcs64i()
{
  ieee1284_release( m_port );
  ieee1284_free_ports( &m_list );
}

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

bool
Pcs64i::hasVoltsDiv( Dso::VoltsDiv voltsDiv ) const
{
  return (voltsDiv >= Dso::VD5v && voltsDiv <= Dso::VD10mv);
}

void 
Pcs64i::setChannelEnable( int channel, bool on )
{
  m_channelEnable[channel] = on;
}

void
Pcs64i::init()
{
  lockParam();
  
  setLatchData( LATCH_TIMEBASE, m_timeBaseByte );
  setLatchData( LATCH_VOLTS_DIV, m_voltsDivByte[0] | m_voltsDivByte[1] ); 
  setLatchData( LATCH_TRIGGER, m_triggerByte );
  
  unlockParam();
}

void
Pcs64i::reset()
{
  setLatchData( LATCH_RESET, 0 );
}

void
Pcs64i::run()
{
  //while (1)
  {
    readSampledData();

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

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

    m_outTriggerOffset = m_triggerOffset;
    m_hasNewData = true;
    m_triggerOk = true;

    unlock();
  }
  
  //exit();
}

void
Pcs64i::readSampledData()
{
  if (m_equivalentSampling)
  {
    unsigned buffer0[4096];
    unsigned buffer1[4096];
    
    setTriggerDelay( false );

    init();    
    reset();
    
    readData();
    
    // copy even samples
    //
    /*for (int i=0; i<2048; ++i)
    {
      buffer0[2*i+1] = m_buffer[0][i+2+512];
      buffer1[2*i+1] = m_buffer[1][i+2+512];
  }*/
    
    for (int i=0; i<4096; ++i)
    {
      buffer0[i] = m_buffer[0][i];
    }
    
    // do it again with delay switched on
    //
    setTriggerDelay( true );
    init();    
    reset();

    if (readData())
    {  
      // copy even samples
      //
      /*for (int i=0; i<2048; ++i)
      {
        buffer0[2*i] = m_buffer[0][i+512];
        buffer1[2*i] = m_buffer[1][i+512];
    }*/
      
      for (int i=0; i<4096; ++i)
      {
        m_buffer[1][i] = m_buffer[0][i];
        m_buffer[0][i] = buffer0[i];
      }
      
      // copy back
      //
      //memcpy( m_buffer[0], buffer0, 4096*sizeof(unsigned) );
      //memcpy( m_buffer[1], buffer1, 4096*sizeof(unsigned) );
    
    }
  }
  else
  {
    setTriggerDelay( false );

    init();    
    reset();
    
    readData();
    
    int level = triggerLevel();
    m_triggerOffset = 0;
    int tc = triggerChannel();
    //std::cerr << "LEVEL=" << level << " CHANNEL=" << tc << std::endl;
    
    std::cerr << "step=" << m_step << std::endl;
    // interpolating only
    // Assumption: Trigger is too late. Look back to find the offset
    //             starting at pretrigger index
    if (m_step > 0)
    {   
      if (triggerRaising())
      {
        for (int i=1024; i>800; --i)
        {
          int delta = m_buffer[tc][i]-m_buffer[tc][i-1];
          
          if (delta > 0 && m_buffer[tc][i] > level && m_buffer[tc][i-1] < level)
          {
            if (i <= 800) 
            {
              std::cerr << "FUCKUP: " << i-1024 << std::endl;
              sleep(2);
            }
            
            m_triggerOffset = m_step*(i-1024);
                      
            //std::cerr << "off=" << m_triggerOffset;
            float fac = (float)(level-m_buffer[tc][i-1]) / (float)delta;
            int dx = (int)qRound((float)m_step * fac);
            m_triggerOffset += dx;
            //std::cerr << " delta=" << delta << " dx=" << dx << " fac=" << fac 
            //          << " step=" << m_step << std::endl;
            break;
          }
        }
      }
      else
      {
        for (int i=1024; i>800; --i)
        {
          int delta = m_buffer[tc][i]-m_buffer[tc][i-1];
          
          if (delta < 0 && m_buffer[tc][i] < level && m_buffer[tc][i-1] > level)
          {
            if (i <= 800) 
            {
              std::cerr << "FUCKUP: " << i-1024 << std::endl;
              sleep(2);
            }
            
            m_triggerOffset = m_step*(i-1023);
                      
            std::cerr << "off=" << m_triggerOffset;
            float fac = (float)(m_buffer[tc][i-1]-level) / (float)delta;
            int dx = (int)qRound((float)m_step * fac);
            m_triggerOffset += dx;
            std::cerr << " delta=" << delta << " dx=" << dx << " fac=" << fac 
                << " step=" << m_step << std::endl;
            break;
          }
        }
      }
    }
  }
}

bool
Pcs64i::readData()
{
  struct timeval timeout;
    
  // juice to the optocoupler before reading
  //
  ieee1284_write_data( m_port, 0xf8 );

  // timeout is time needed for sampling + 0.5s
  //
  unsigned long usecs = (unsigned long)((4096. / m_samplingFrequency) * 1000000. + 500000.);
  unsigned long secs = usecs / 1000000L;
  usecs %= 1000000L;

  timeout.tv_sec = secs;
  timeout.tv_usec = usecs;

  if (E1284_TIMEDOUT != 
      ieee1284_wait_status( m_port, 0x80, 0, &timeout )) // if not timeout
  {
    const int lengthPlus = m_acqOffset+m_acqLength;
    
    // forewind (writing as fast as we can seems no problem)
    //
    for (int i=0; i> 3) & 0x0f;
      }
      
      if (m_channelEnable[1])
      {
        ieee1284_write_data( m_port, 0xfd ); // 11111101
        ieee1284_write_data( m_port, 0xfd ); // 11111101
        
        ieee1284_read_status( m_port );
        m_buffer[1][i] = (ieee1284_read_status( m_port ) << 1) & 0xf0;
        
        ieee1284_write_data( m_port, 0xfc ); // 11111100
        ieee1284_write_data( m_port, 0xfc ); // 11111100
        
        ieee1284_read_status( m_port );
        m_buffer[1][i] |= (ieee1284_read_status( m_port ) >> 3) & 0x0f;
      }
      
      ieee1284_write_data( m_port, 0xf8 ); // 11111000
      ieee1284_write_data( m_port, 0xf8 ); // 11111000
    }   
      
    // go to the end 
    // (It's my impression that the PCS64i gives more stable
    // results if we forewind to the end. Maybe a bug in QtDSO
    // or a proerty of the scope)
    for (int i=lengthPlus; i