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

Commits on Sep 25, 2020

  1. Copy the full SHA
    7c8d12a View commit details
  2. Copy the full SHA
    ed06fdd View commit details
  3. TektronixOscilloscope: fixed rounding error in sample rate calculatio…

    …n. Added tables for sample rates/depths. See #13.
    azonenberg committed Sep 25, 2020
    Copy the full SHA
    299e602 View commit details
Showing with 157 additions and 33 deletions.
  1. +146 −32 scopehal/TektronixOscilloscope.cpp
  2. +11 −1 scopehal/Unit.cpp
178 changes: 146 additions & 32 deletions scopehal/TektronixOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -545,6 +545,7 @@ int TektronixOscilloscope::GetChannelBandwidthLimit(size_t i)

void TektronixOscilloscope::SetChannelBandwidthLimit(size_t i, unsigned int limit_mhz)
{
//Update cache
{
lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelBandwidthLimits[i] = limit_mhz;
@@ -581,56 +582,90 @@ double TektronixOscilloscope::GetChannelVoltageRange(size_t i)
return m_channelVoltageRanges[i];
}

lock_guard<recursive_mutex> lock2(m_mutex);

m_transport->SendCommand(m_channels[i]->GetHwname() + ":SCA?");
string reply = m_transport->ReadReply();
double vdiv;
sscanf(reply.c_str(), "%lf", &vdiv);

double range = vdiv * 10;
//We want total range, not per division
double range;
{
lock_guard<recursive_mutex> lock2(m_mutex);
m_transport->SendCommand(m_channels[i]->GetHwname() + ":SCA?");
range = stof(m_transport->ReadReply()) * 10;
}

lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelVoltageRanges[i] = range;
return range;
}

void TektronixOscilloscope::SetChannelVoltageRange(size_t /*i*/, double /*range*/)
void TektronixOscilloscope::SetChannelVoltageRange(size_t i, double range)
{
//FIXME
//Update cache
{
lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelVoltageRanges[i] = range;
}

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
m_transport->SendCommand(m_channels[i]->GetHwname() + ":SCA " + to_string(range/10));
break;

default:
break;
}
}

OscilloscopeChannel* TektronixOscilloscope::GetExternalTrigger()
{
//FIXME
return NULL;
return m_extTrigChannel;
}

double TektronixOscilloscope::GetChannelOffset(size_t i)
{
//Check cache
{
lock_guard<recursive_mutex> lock(m_cacheMutex);

if(m_channelOffsets.find(i) != m_channelOffsets.end())
return m_channelOffsets[i];
}

lock_guard<recursive_mutex> lock2(m_mutex);
m_transport->SendCommand(m_channels[i]->GetHwname() + ":OFFS?");
string reply = m_transport->ReadReply();

//Read offset
double offset;
sscanf(reply.c_str(), "%lf", &offset);
offset = -offset;
{
lock_guard<recursive_mutex> lock2(m_mutex);
m_transport->SendCommand(m_channels[i]->GetHwname() + ":OFFS?");
string reply = m_transport->ReadReply();
offset = -stof(m_transport->ReadReply());
}

//Update cache
lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelOffsets[i] = offset;
return offset;
}

void TektronixOscilloscope::SetChannelOffset(size_t /*i*/, double /*offset*/)
void TektronixOscilloscope::SetChannelOffset(size_t i, double offset)
{
//FIXME
//Update cache
{
lock_guard<recursive_mutex> lock(m_cacheMutex);
m_channelOffsets[i] = offset;
}

lock_guard<recursive_mutex> lock(m_mutex);

switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
m_transport->SendCommand(m_channels[i]->GetHwname() + ":OFFS " + to_string(-offset));
break;

default:
break;
}
}

Oscilloscope::TriggerMode TektronixOscilloscope::PollTrigger()
@@ -818,7 +853,7 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<AnalogWaveform*> >&
if(j == 11)
{
xincrements[i] = stof(reply) * 1e12; //scope gives sec, not ps
//LogDebug("xincrement = %s\n", Unit(Unit::UNIT_PS).PrettyPrint(xincrement).c_str());
//LogDebug("xincrement = %s\n", Unit(Unit::UNIT_PS).PrettyPrint(xincrements[i]).c_str());
}
else if(j == 15)
{
@@ -868,7 +903,7 @@ bool TektronixOscilloscope::AcquireDataMSO56(map<int, vector<AnalogWaveform*> >&
//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 = xincrements[i];
cap->m_timescale = round(xincrements[i]);
cap->m_triggerPhase = 0;
cap->m_startTimestamp = time(NULL);
double t = GetTime();
@@ -929,37 +964,114 @@ bool TektronixOscilloscope::IsTriggerArmed()

vector<uint64_t> TektronixOscilloscope::GetSampleRatesNonInterleaved()
{
//FIXME
vector<uint64_t> ret;

const int64_t k = 1000;
const int64_t m = k*k;
const int64_t g = k*m;

uint64_t bases[] = { 1000, 1250, 2500, 3125, 5000, 6250 };
uint64_t scales_mso6[] = {1, 10, 100, 1*k, 10*k};

switch(m_family)
{
case FAMILY_MSO5:
break;

case FAMILY_MSO6:
{
for(auto b : bases)
ret.push_back(b / 10);

for(auto scale : scales_mso6)
{
for(auto b : bases)
ret.push_back(b * scale);
}

//We break with the pattern on the upper end of the frequency range
ret.push_back(125 * m);
ret.push_back(250 * m);
ret.push_back(312500 * k);
ret.push_back(625 * m);
ret.push_back(1250 * m);
ret.push_back(1562500 * k);
ret.push_back(3125 * m);
ret.push_back(6250 * m);
ret.push_back(12500 * m);
ret.push_back(25 * g); //8 bits, not 12.
//TODO: we can save bandwidth by using 8 bit waveform download for this
}
break;

default:
break;
}

return ret;
}

vector<uint64_t> TektronixOscilloscope::GetSampleRatesInterleaved()
{
//FIXME
vector<uint64_t> ret;
return ret;
//MSO5/6 have no interleaving
return GetSampleRatesNonInterleaved();
}

set<Oscilloscope::InterleaveConflict> TektronixOscilloscope::GetInterleaveConflicts()
{
//FIXME
//MSO5/6 have no interleaving
set<Oscilloscope::InterleaveConflict> ret;
return ret;
}

vector<uint64_t> TektronixOscilloscope::GetSampleDepthsNonInterleaved()
{
//FIXME
vector<uint64_t> ret;

const int64_t k = 1000;
const int64_t m = k*k;

switch(m_family)
{
case FAMILY_MSO5:
break;

//The scope allows extremely granular specification of memory depth.
//For our purposes, only show a bunch of common step values.
//No need for super fine granularity since record length isn't tied to the UI display width.
case FAMILY_MSO6:
{
ret.push_back(500);
ret.push_back(1 * k);
ret.push_back(2 * k);
ret.push_back(5 * k);
ret.push_back(10 * k);
ret.push_back(20 * k);
ret.push_back(50 * k);
ret.push_back(100 * k);
ret.push_back(200 * k);
ret.push_back(500 * k);
ret.push_back(1 * m);
ret.push_back(2 * m);
ret.push_back(5 * m);
ret.push_back(10 * m);
ret.push_back(20 * m);
ret.push_back(50 * m);
ret.push_back(62500 * k);
}
break;

default:
break;
}

return ret;
}

vector<uint64_t> TektronixOscilloscope::GetSampleDepthsInterleaved()
{
//FIXME
vector<uint64_t> ret;
return ret;
//MSO5/6 have no interleaving
return GetSampleDepthsNonInterleaved();
}

uint64_t TektronixOscilloscope::GetSampleRate()
@@ -997,11 +1109,13 @@ int64_t TektronixOscilloscope::GetTriggerOffset()

bool TektronixOscilloscope::IsInterleaving()
{
//MSO5/6 have no interleaving
return false;
}

bool TektronixOscilloscope::SetInterleaving(bool /*combine*/)
{
//MSO5/6 have no interleaving
return false;
}

12 changes: 11 additions & 1 deletion scopehal/Unit.cpp
Original file line number Diff line number Diff line change
@@ -196,7 +196,17 @@ string Unit::PrettyPrint(double value)
break;

case UNIT_SAMPLERATE:
snprintf(tmp, sizeof(tmp), "%.0f %s%s", value_rescaled, scale, unit);
{
//If sample rate isn't a round number, add more digits (up to 3)
if( fabs(round(value_rescaled) - value_rescaled) < 0.1 )
snprintf(tmp, sizeof(tmp), "%.0f %s%s", value_rescaled, scale, unit);
else if(fabs(round(value_rescaled*10) - value_rescaled*10) < 0.1)
snprintf(tmp, sizeof(tmp), "%.1f %s%s", value_rescaled, scale, unit);
else if(fabs(round(value_rescaled*100) - value_rescaled*100) < 0.1 )
snprintf(tmp, sizeof(tmp), "%.2f %s%s", value_rescaled, scale, unit);
else
snprintf(tmp, sizeof(tmp), "%.3f %s%s", value_rescaled, scale, unit);
}
break;

case UNIT_SAMPLEDEPTH: