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: d42ccc80a312
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b2abc4c446ea
Choose a head ref
  • 2 commits
  • 1 file changed
  • 1 contributor

Commits on Sep 27, 2020

  1. TektronixOscilloscope: very early support for spectrum view. Can disp…

    …lay waveforms but not change frequencies etc. Cannot query gain/offset yet. See #269.
    azonenberg committed Sep 27, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a34c06e View commit details
  2. Copy the full SHA
    b2abc4c View commit details
Showing with 120 additions and 37 deletions.
  1. +120 −37 scopehal/TektronixOscilloscope.cpp
157 changes: 120 additions & 37 deletions scopehal/TektronixOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -81,7 +81,6 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
case FAMILY_MSO6:
m_transport->SendCommand("ACQ:MOD SAM"); //actual sampled data, no averaging etc
m_transport->SendCommand("VERB OFF"); //Disable verbose mode (send shorter commands)
m_transport->SendCommand("DAT:ENC SRI"); //signed, little endian binary
m_transport->SendCommand("ACQ:STOPA SEQ"); //Stop after acquiring a single waveform
m_transport->SendCommand("CONFIG:ANALO:BANDW?"); //Figure out what bandwidth we have
m_bandwidth = stof(m_transport->ReadReply()) * 1e-6; //(so we know what probe bandwidth is)
@@ -143,7 +142,7 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
m_channels.push_back(
new OscilloscopeChannel(
this,
string("CH") + to_string(i+1), //same hwname as the base channel
string("CH") + to_string(i+1) + "_SPECTRUM",
OscilloscopeChannel::CHANNEL_TYPE_ANALOG,
colors_mso56[i % 4],
Unit(Unit::UNIT_HZ),
@@ -390,7 +389,7 @@ bool TektronixOscilloscope::IsChannelEnabled(size_t i)

//Undocumented command to toggle spectrum view state
if(IsSpectrum(i))
m_transport->SendCommand(m_channels[i]->GetHwname() + ":SV:STATE?");
m_transport->SendCommand(m_channels[i - m_spectrumChannelBase]->GetHwname() + ":SV:STATE?");
else
m_transport->SendCommand(string("DISP:WAVEV:") + m_channels[i]->GetHwname() + ":STATE?");
break;
@@ -451,7 +450,7 @@ void TektronixOscilloscope::EnableChannel(size_t i)
case FAMILY_MSO5:
case FAMILY_MSO6:
if(IsSpectrum(i))
m_transport->SendCommand(m_channels[i]->GetHwname() + ":SV:STATE ON");
m_transport->SendCommand(m_channels[i - m_spectrumChannelBase]->GetHwname() + ":SV:STATE ON");
else
m_transport->SendCommand(string("DISP:WAVEV:") + m_channels[i]->GetHwname() + ":STATE ON");
break;
@@ -483,7 +482,7 @@ void TektronixOscilloscope::DisableChannel(size_t i)
case FAMILY_MSO5:
case FAMILY_MSO6:
if(IsSpectrum(i))
m_transport->SendCommand(m_channels[i]->GetHwname() + ":SV:STATE OFF");
m_transport->SendCommand(m_channels[i - m_spectrumChannelBase]->GetHwname() + ":SV:STATE OFF");
else
m_transport->SendCommand(string("DISP:WAVEV:") + m_channels[i]->GetHwname() + ":STATE OFF");
break;
@@ -508,7 +507,7 @@ OscilloscopeChannel::CouplingType TektronixOscilloscope::GetChannelCoupling(size
}

//If not analog, return default
if(i >= m_analogChannelCount)
if(!IsAnalog(i))
return OscilloscopeChannel::COUPLE_DC_50;

OscilloscopeChannel::CouplingType coupling = OscilloscopeChannel::COUPLE_DC_1M;
@@ -573,6 +572,9 @@ OscilloscopeChannel::CouplingType TektronixOscilloscope::GetChannelCoupling(size

void TektronixOscilloscope::SetChannelCoupling(size_t i, OscilloscopeChannel::CouplingType type)
{
if(!IsAnalog(i))
return;

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
@@ -638,7 +640,7 @@ double TektronixOscilloscope::GetChannelAttenuation(size_t i)
}

//If not analog, return default
if(i >= m_analogChannelCount)
if(!IsAnalog(i))
return 1;

lock_guard<recursive_mutex> lock(m_mutex);
@@ -684,6 +686,9 @@ double TektronixOscilloscope::GetChannelAttenuation(size_t i)

void TektronixOscilloscope::SetChannelAttenuation(size_t i, double atten)
{
if(!IsAnalog(i))
return;

{
lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelAttenuations[i] = atten;
@@ -715,16 +720,16 @@ void TektronixOscilloscope::SetChannelAttenuation(size_t i, double atten)

int TektronixOscilloscope::GetChannelBandwidthLimit(size_t i)
{
//If not analog, return default
if(!IsAnalog(i))
return 0;

{
lock_guard<recursive_mutex> lock(m_cacheMutex);
if(m_channelBandwidthLimits.find(i) != m_channelBandwidthLimits.end())
return m_channelBandwidthLimits[i];
}

//If not analog, return default
if(i >= m_analogChannelCount)
return 0;

int bwl = 0;
{
lock_guard<recursive_mutex> lock(m_mutex);
@@ -768,6 +773,9 @@ int TektronixOscilloscope::GetChannelBandwidthLimit(size_t i)

void TektronixOscilloscope::SetChannelBandwidthLimit(size_t i, unsigned int limit_mhz)
{
if(!IsAnalog(i))
return;

//Update cache
{
lock_guard<recursive_mutex> lock(m_cacheMutex);
@@ -1080,11 +1088,12 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<WaveformBase*> >& p
m_transport->SendCommand("DAT:START 0");
m_transport->SendCommand(string("DAT:STOP ") + to_string(length));

map<size_t, double> ymults;
map<size_t, double> yoffs;
double ymult = 0;
double yoff = 0;

//Ask for the analog preambles
//Ask for the analog data
m_transport->SendCommand("DAT:WID 2"); //16-bit data
m_transport->SendCommand("DAT:ENC SRI"); //signed, little endian binary
size_t timebase = 0;
for(size_t i=0; i<m_analogChannelCount; i++)
{
@@ -1111,32 +1120,23 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<WaveformBase*> >& p
}
else if(j == 15)
{
ymults[i] = stof(reply);
ymult = stof(reply);
//LogDebug("ymult = %s\n", Unit(Unit::UNIT_VOLTS).PrettyPrint(ymult).c_str());
}
else if(j == 17)
{
yoffs[i] = stof(reply);
m_channelOffsets[i] = -yoffs[i];
yoff = stof(reply);
m_channelOffsets[i] = -yoff;
//LogDebug("yoff = %s\n", Unit(Unit::UNIT_VOLTS).PrettyPrint(yoff).c_str());
}

//TODO: xzero is trigger time
}
}

//Ask for and get the analog data
//(seems like batching here doesn't work)
for(size_t i=0; i<m_analogChannelCount; i++)
{
if(!IsChannelEnabled(i))
continue;

//LogDebug("Channel %zu (%s)\n", i, m_channels[i]->GetHwname().c_str());
LogIndenter li2;

//Read the data blocks
m_transport->SendCommand(string("DAT:SOU ") + m_channels[i]->GetHwname());
m_transport->SendCommand("CURV?");

//Read length of the actual data
@@ -1167,8 +1167,6 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<WaveformBase*> >& p
cap->Resize(nsamples);

//Convert to volts
float ymult = ymults[i];
float yoff = yoffs[i];
for(size_t j=0; j<nsamples; j++)
{
cap->m_offsets[j] = j;
@@ -1186,12 +1184,103 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<WaveformBase*> >& p
m_transport->ReadReply();
}

//TODO: RF stuff
//CHx_SV_NORMAL,
//CHx_SV_BASEBAND_IQ
//Get the spectrum stuff
m_transport->SendCommand("DAT:WID 8"); //double precision floating point data
m_transport->SendCommand("DAT:ENC SFPB"); //IEEE754 float
for(size_t i=0; i<m_analogChannelCount; i++)
{
auto nchan = m_spectrumChannelBase + i;
if(!IsChannelEnabled(nchan))
continue;

// Set source & get preamble+data
m_transport->SendCommand(string("DAT:SOU ") + m_channels[i]->GetHwname() + "_SV_NORMAL");

//Ask for the waveform preamble
m_transport->SendCommand("WFMO?");

//LogDebug("Channel %zu (%s)\n", nchan, m_channels[nchan]->GetHwname().c_str());
//LogIndenter li2;

//Process it
double hzbase = 0;
for(int j=0; j<22; j++)
{
string reply = m_transport->ReadReply();

//LogDebug("preamble block %d = %s\n", j, reply.c_str());

if(j == 11)
{
hzbase = round(stof(reply));
//LogDebug("xincrement = %s\n", Unit(Unit::UNIT_HZ).PrettyPrint(hzbase).c_str());
}
else if(j == 15)
{
ymult = stof(reply);
//LogDebug("ymult = %s\n", Unit(Unit::UNIT_DBM).PrettyPrint(ymult).c_str());
}
else if(j == 17)
{
yoff = stof(reply);
m_channelOffsets[i] = -yoff;
//LogDebug("yoff = %s\n", Unit(Unit::UNIT_DBM).PrettyPrint(yoff).c_str());
}

//TODO: xzero is trigger time
}

//Read the data block
m_transport->SendCommand("CURV?");

//Read length of the actual data
char tmplen[3] = {0};
m_transport->ReadRawData(2, (unsigned char*)tmplen); //expect #n
int ndigits = atoi(tmplen+1);

char digits[10] = {0};
m_transport->ReadRawData(ndigits, (unsigned char*)digits);
int msglen = atoi(digits);

//Read the actual data
char* rxbuf = new char[msglen];
m_transport->ReadRawData(msglen, (unsigned char*)rxbuf);

//convert bytes to samples
size_t nsamples = msglen/8;
double* samples = (double*)rxbuf;

//Set up the capture we're going to store our data into
//(no TDC data or fine timestamping available on Tektronix scopes?)
AnalogWaveform* cap = new AnalogWaveform;
cap->m_timescale = hzbase;
cap->m_triggerPhase = 0;
cap->m_startTimestamp = time(NULL);
double t = GetTime();
cap->m_startPicoseconds = (t - floor(t)) * 1e12f;
cap->Resize(nsamples);

//We get dBm from the instrument, so just have to convert double to single precision
for(size_t j=0; j<nsamples; j++)
{
cap->m_offsets[j] = j;
cap->m_durations[j] = 1;
cap->m_samples[j] = ymult*samples[j] + yoff;
}

//Done, update the data
pending_waveforms[nchan].push_back(cap);

//Done
delete[] rxbuf;

//Throw out garbage at the end of the message (why is this needed?)
m_transport->ReadReply();
}

//Get the digital stuff
m_transport->SendCommand("DAT:WID 1"); //8 data bits per channel
m_transport->SendCommand("DAT:ENC SRI"); //signed, little endian binary
for(size_t i=0; i<m_analogChannelCount; i++)
{
//Skip anything without a digital probe connected
@@ -1281,12 +1370,6 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<WaveformBase*> >& p
m_transport->ReadReply();
}

//Get the spectrum stuff
for(size_t i=0; i<m_analogChannelCount; i++)
{
pending_waveforms[m_spectrumChannelBase + i].push_back(NULL);
}

return true;
}