Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2a17c887a3f8
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6598e9f11352
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Oct 12, 2020

  1. TektronixOscilloscope: initial implementation of Multimeter API. Does…

    …n't do anything but detect presence of the meter option at this point.
    azonenberg committed Oct 12, 2020
    Copy the full SHA
    3e236b0 View commit details
  2. TektronixOscilloscope: continued multimeter implementation, fixed a b…

    …unch of potential hangs if digital probes are connected. Still more bugs.
    azonenberg committed Oct 12, 2020
    Copy the full SHA
    984c49f View commit details
  3. TektronixOscilloscope: seems MSO5/6 are very picky and don't like you…

    … setting gain/offset on disabled spectrum view channels or the whole instrument locks up... Fixes #308.
    azonenberg committed Oct 12, 2020
    Copy the full SHA
    6598e9f View commit details
Showing with 245 additions and 18 deletions.
  1. +216 −17 scopehal/TektronixOscilloscope.cpp
  2. +29 −1 scopehal/TektronixOscilloscope.h
233 changes: 216 additions & 17 deletions scopehal/TektronixOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -48,10 +48,13 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
, m_triggerOffset(0)
, m_rbwValid(false)
, m_rbw(0)
, m_dmmAutorangeValid(false)
, m_dmmAutorange(false)
, m_digitalChannelBase(0)
, m_triggerArmed(false)
, m_triggerOneShot(false)
, m_maxBandwidth(1000)
, m_hasDVM(false)
{
//Figure out what device family we are
if(m_model.find("MSO5") == 0)
@@ -280,7 +283,6 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)

else if(opt == "LIC6-DDU")
{
LogDebug("* LIC6-DDU (6 series distribution demo)\n");
/*
This is a bundle code that unlocks lots of stuff:
* 8 GHZ bandwidth
@@ -317,6 +319,8 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
* Slew rate
* Sequence
*/
LogDebug("* LIC6-DDU (6 series distribution demo)\n");
m_hasDVM = true;
}

else
@@ -341,7 +345,10 @@ string TektronixOscilloscope::GetDriverNameInternal()

unsigned int TektronixOscilloscope::GetInstrumentTypes()
{
return Instrument::INST_OSCILLOSCOPE;
unsigned int mask = Instrument::INST_OSCILLOSCOPE;
if(m_hasDVM)
mask |= Instrument::INST_DMM;
return mask;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -366,9 +373,16 @@ void TektronixOscilloscope::DetectProbes()
if(reply == "DIG")
m_probeTypes[i] = PROBE_TYPE_DIGITAL_8BIT;

//Treat anything else as analog
//Treat anything else as analog. See what type
else
m_probeTypes[i] = PROBE_TYPE_ANALOG;
{
m_transport->SendCommand(m_channels[i]->GetHwname() + ":PROBE:ID:TYP?");
string id = TrimQuotes(m_transport->ReadReply());
if(id == "TPP1000")
m_probeTypes[i] = PROBE_TYPE_ANALOG_250K;
else
m_probeTypes[i] = PROBE_TYPE_ANALOG;
}
}
break;

@@ -393,6 +407,7 @@ void TektronixOscilloscope::FlushConfigCache()
m_sampleDepthValid = false;
m_triggerOffsetValid = false;
m_rbwValid = false;
m_dmmAutorangeValid = false;

delete m_trigger;
m_trigger = NULL;
@@ -422,15 +437,15 @@ bool TektronixOscilloscope::IsChannelEnabled(size_t i)
lock_guard<recursive_mutex> lock(m_cacheMutex);

//If we're an analog channel with a digital probe connected, the analog channel is unusable
if(m_probeTypes[i] != PROBE_TYPE_ANALOG)
if(m_probeTypes[i] == PROBE_TYPE_DIGITAL_8BIT)
return false;
}
else if(IsSpectrum(i))
{
lock_guard<recursive_mutex> lock(m_cacheMutex);

//If we're an analog channel with a digital probe connected, the analog channel is unusable
if(m_probeTypes[i - m_spectrumChannelBase] != PROBE_TYPE_ANALOG)
if(m_probeTypes[i - m_spectrumChannelBase] == PROBE_TYPE_DIGITAL_8BIT)
return false;
}

@@ -482,7 +497,7 @@ void TektronixOscilloscope::EnableChannel(size_t i)
lock_guard<recursive_mutex> lock(m_cacheMutex);

//If we're an analog channel with a digital probe connected, the analog channel is unusable
if( IsAnalog(i) && (m_probeTypes[i] != PROBE_TYPE_ANALOG) )
if( IsAnalog(i) && (m_probeTypes[i] == PROBE_TYPE_DIGITAL_8BIT) )
return;

//If we're a digital channel with an analog probe connected, we're unusable
@@ -513,7 +528,17 @@ void TektronixOscilloscope::EnableChannel(size_t i)
if(IsSpectrum(i))
m_transport->SendCommand(m_channels[i - m_spectrumChannelBase]->GetHwname() + ":SV:STATE ON");
else
{
//Make sure the digital group is on
if(IsDigital(i))
{
size_t parent = m_flexChannelParents[m_channels[i]];
m_transport->SendCommand(
string("DISP:WAVEV:") + m_channels[parent]->GetHwname() + "_DALL:STATE ON");
}

m_transport->SendCommand(string("DISP:WAVEV:") + m_channels[i]->GetHwname() + ":STATE ON");
}
break;

default:
@@ -530,13 +555,13 @@ bool TektronixOscilloscope::CanEnableChannel(size_t i)
lock_guard<recursive_mutex> lock(m_cacheMutex);

//If we're an analog channel with a digital probe connected, the analog channel is unusable
if(IsAnalog(i) && (m_probeTypes[i] != PROBE_TYPE_ANALOG) )
if(IsAnalog(i) && (m_probeTypes[i] == PROBE_TYPE_DIGITAL_8BIT) )
return false;

//Can't use spectrum view if the parent channel has a digital channel connected
if(IsSpectrum(i))
{
if(m_probeTypes[i - m_spectrumChannelBase] != PROBE_TYPE_ANALOG)
if(m_probeTypes[i - m_spectrumChannelBase] == PROBE_TYPE_DIGITAL_8BIT)
return false;
}

@@ -557,7 +582,7 @@ void TektronixOscilloscope::DisableChannel(size_t i)
lock_guard<recursive_mutex> lock(m_cacheMutex);

//If we're an analog channel with a digital probe connected, the analog channel is unusable
if( IsAnalog(i) && (m_probeTypes[i] != PROBE_TYPE_ANALOG) )
if( IsAnalog(i) && (m_probeTypes[i] == PROBE_TYPE_DIGITAL_8BIT) )
return;
}

@@ -676,13 +701,18 @@ void TektronixOscilloscope::SetChannelCoupling(size_t i, OscilloscopeChannel::Co
break;

case OscilloscopeChannel::COUPLE_AC_1M:
m_transport->SendCommand(m_channels[i]->GetHwname() + ":TERM 1E+6");
if(m_probeTypes[i] == PROBE_TYPE_ANALOG_250K)
m_transport->SendCommand(m_channels[i]->GetHwname() + ":TERM 250E3");
else
m_transport->SendCommand(m_channels[i]->GetHwname() + ":TERM 1E+6");
m_transport->SendCommand(m_channels[i]->GetHwname() + ":COUP AC");
break;

case OscilloscopeChannel::COUPLE_DC_1M:
m_transport->SendCommand(m_channels[i]->GetHwname() + ":TERM 1E+6");
m_transport->SendCommand(m_channels[i]->GetHwname() + ":COUP DC");
if(m_probeTypes[i] == PROBE_TYPE_ANALOG_250K)
m_transport->SendCommand(m_channels[i]->GetHwname() + ":TERM 250E3");
else
m_transport->SendCommand(m_channels[i]->GetHwname() + ":COUP DC");
break;

default:
@@ -956,6 +986,10 @@ double TektronixOscilloscope::GetChannelVoltageRange(size_t i)
if(!IsAnalog(i) && !IsSpectrum(i))
return 1;

//If unusable, return a placeholder value
if(!CanEnableChannel(i) || !IsChannelEnabled(i))
return 1;

//We want total range, not per division
double range;
{
@@ -995,6 +1029,10 @@ void TektronixOscilloscope::SetChannelVoltageRange(size_t i, double range)
if(!IsAnalog(i) && !IsSpectrum(i))
return;

//If unusable or disabled do nothing
if(!CanEnableChannel(i) || !IsChannelEnabled(i))
return;

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
@@ -1043,13 +1081,17 @@ string TektronixOscilloscope::GetChannelDisplayName(size_t i)
return m_channelDisplayNames[chan];
}

lock_guard<recursive_mutex> lock(m_mutex);

//Spectrum channels don't have separate names from the time domain ones.
//Store our own nicknames clientside for them.
string name;
if(!IsSpectrum(i))

//If we can't use the channel return the hwname as a placeholder
if(!CanEnableChannel(i))
name = chan->GetHwname();

else if(!IsSpectrum(i))
{
lock_guard<recursive_mutex> lock(m_mutex);
switch(m_family)
{
//What a shocker!
@@ -1132,6 +1174,10 @@ double TektronixOscilloscope::GetChannelOffset(size_t i)
if(!IsAnalog(i) && !IsSpectrum(i))
return 0;

//If unusable, return a placeholder value
if(!CanEnableChannel(i) || !IsChannelEnabled(i))
return 0;

//Read offset
double offset = 0;
{
@@ -1179,6 +1225,10 @@ void TektronixOscilloscope::SetChannelOffset(size_t i, double offset)
if(!IsAnalog(i) && !IsSpectrum(i))
return;

//If unusable, do nothing
if(!CanEnableChannel(i) || !IsChannelEnabled(i))
return;

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
@@ -2320,7 +2370,7 @@ void TektronixOscilloscope::SetDigitalThreshold(size_t channel, float level)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Spectrum analyzer configuration
// Spectrum analyzer mode

bool TektronixOscilloscope::HasFrequencyControls()
{
@@ -2440,3 +2490,152 @@ int64_t TektronixOscilloscope::GetResolutionBandwidth()
return 1;
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Multimeter mode

unsigned int TektronixOscilloscope::GetMeasurementTypes()
{
switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
if(m_hasDVM)
return DC_VOLTAGE | DC_RMS_AMPLITUDE | AC_RMS_AMPLITUDE | FREQUENCY;
else
return 0;

default:
return 0;
}
}

int TektronixOscilloscope::GetMeterChannelCount()
{
return m_analogChannelCount;
}

string TektronixOscilloscope::GetMeterChannelName(int chan)
{
return GetChannel(chan)->GetDisplayName();
}

int TektronixOscilloscope::GetCurrentMeterChannel()
{
return 0;
}

void TektronixOscilloscope::SetCurrentMeterChannel(int chan)
{
}

Multimeter::MeasurementTypes TektronixOscilloscope::GetMeterMode()
{
return DC_VOLTAGE;
}

void TektronixOscilloscope::SetMeterMode(MeasurementTypes type)
{
}

void TektronixOscilloscope::SetMeterAutoRange(bool enable)
{
lock_guard<recursive_mutex> lock(m_mutex);

m_dmmAutorange = enable;
m_dmmAutorangeValid = true;

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
if(enable)
m_transport->SendCommand("DVM:AUTOR ON");
else
m_transport->SendCommand("DVM:AUTOR OFF");
break;

default:
break;
}
}

bool TektronixOscilloscope::GetMeterAutoRange()
{
if(m_dmmAutorangeValid)
return m_dmmAutorange;

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
m_transport->SendCommand("DVM:AUTOR?");
m_dmmAutorange = (stoi(m_transport->ReadReply()) == 1);
break;

default:
break;
}

m_dmmAutorangeValid = true;
return m_dmmAutorange;
}

void TektronixOscilloscope::StartMeter()
{
lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
m_transport->SendCommand("DVM:MOD DC"); //TODO: use saved operating mode
break;

default:
break;
}
}

void TektronixOscilloscope::StopMeter()
{
lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
m_transport->SendCommand("DVM:MOD OFF");
break;

default:
break;
}
}

double TektronixOscilloscope::GetVoltage()
{
return 0;
}

double TektronixOscilloscope::GetPeakToPeak()
{
return 0;
}

double TektronixOscilloscope::GetFrequency()
{
return 0;
}

double TektronixOscilloscope::GetCurrent()
{
return 0;
}

double TektronixOscilloscope::GetTemperature()
{
return 0;
}
Loading