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: 6a5d675d616f
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 079c789b1e34
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Sep 24, 2020

  1. Copy the full SHA
    079c789 View commit details
Showing with 180 additions and 95 deletions.
  1. +178 −92 scopehal/TektronixOscilloscope.cpp
  2. +2 −3 scopehal/TektronixOscilloscope.h
270 changes: 178 additions & 92 deletions scopehal/TektronixOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -44,8 +44,10 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
, m_triggerOneShot(false)
{
//Figure out what device family we are
if( (m_model.find("MSO5") == 0) || (m_model.find("MSO6") == 0) )
m_family = FAMILY_MSO5_6;
if(m_model.find("MSO5") == 0)
m_family = FAMILY_MSO5;
else if(m_model.find("MSO6") == 0)
m_family = FAMILY_MSO6;
else
m_family = FAMILY_UNKNOWN;

@@ -67,7 +69,8 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
//Device specific initialization
switch(m_family)
{
case FAMILY_MSO5_6:
case FAMILY_MSO5:
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
@@ -84,6 +87,7 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
break;
}

//TODO: get colors for channels 5-8 on wide instruments
const char* colors_default[4] = { "#ffff00", "#32ff00", "#5578ff", "#ff0084" }; //yellow-green-violet-pink
const char* colors_mso56[4] = { "#ffff00", "#20d3d8", "#f23f59", "#f16727" }; //yellow-cyan-pink-orange

@@ -97,12 +101,13 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
string color = "#ffffff";
switch(m_family)
{
case FAMILY_MSO5_6:
color = colors_mso56[i];
case FAMILY_MSO5:
case FAMILY_MSO6:
color = colors_mso56[i % 4];
break;

default:
color = colors_default[i];
color = colors_default[i % 4];
break;
}

@@ -123,15 +128,37 @@ TektronixOscilloscope::TektronixOscilloscope(SCPITransport* transport)
m_analogChannelCount = nchans;

//Add the external trigger input
m_extTrigChannel = new OscilloscopeChannel(
this,
"EX",
OscilloscopeChannel::CHANNEL_TYPE_TRIGGER,
"",
1,
m_channels.size(),
true);
m_channels.push_back(m_extTrigChannel);
switch(m_family)
{
//MSO5 does not appear to have an external trigger input
case FAMILY_MSO5:
m_extTrigChannel = NULL;
break;

case FAMILY_MSO6:
m_extTrigChannel = new OscilloscopeChannel(
this,
"AUX",
OscilloscopeChannel::CHANNEL_TYPE_TRIGGER,
"",
1,
m_channels.size(),
true);
m_channels.push_back(m_extTrigChannel);
break;

default:
m_extTrigChannel = new OscilloscopeChannel(
this,
"EX",
OscilloscopeChannel::CHANNEL_TYPE_TRIGGER,
"",
1,
m_channels.size(),
true);
m_channels.push_back(m_extTrigChannel);
break;
}

//See what options we have
//FIXME: this code is completely broken on MSO5/6
@@ -450,13 +477,13 @@ Oscilloscope::TriggerMode TektronixOscilloscope::PollTrigger()
m_transport->SendCommand("TRIG:STATE?");
string ter = m_transport->ReadReply();

if( (ter == "SAV") || (ter == "SAVE") )
if(ter == "SAV")
{
m_triggerArmed = false;
return TRIGGER_MODE_TRIGGERED;
}

if( (ter == "REA") || (ter == "READY") )
if(ter == "REA")
{
m_triggerArmed = true;
return TRIGGER_MODE_RUN;
@@ -468,7 +495,7 @@ Oscilloscope::TriggerMode TektronixOscilloscope::PollTrigger()

bool TektronixOscilloscope::AcquireData()
{
LogDebug("Acquiring data\n");
//LogDebug("Acquiring data\n");

lock_guard<recursive_mutex> lock(m_mutex);
LogIndenter li;
@@ -478,7 +505,8 @@ bool TektronixOscilloscope::AcquireData()
char tmp[128];
switch(m_family)
{
case FAMILY_MSO5_6:
case FAMILY_MSO5:
case FAMILY_MSO6:
{
m_transport->SendCommand("HOR:RECO?");
string reply = m_transport->ReadReply();
@@ -504,14 +532,15 @@ bool TektronixOscilloscope::AcquireData()
if(!IsChannelEnabled(i))
continue;

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

// Set source & get preamble+data
m_transport->SendCommand(string("DAT:SOU ") + m_channels[i]->GetHwname());
switch(m_family)
{
case FAMILY_MSO5_6:
case FAMILY_MSO5:
case FAMILY_MSO6:
{
//Ask for the waveform preamble
m_transport->SendCommand("WFMO?");
@@ -809,17 +838,28 @@ void TektronixOscilloscope::PullTrigger()
{
lock_guard<recursive_mutex> lock(m_mutex);

//TODO: check trigger types
if(1)
PullEdgeTrigger();

//Unrecognized trigger type
else
switch(m_family)
{
LogWarning("Unknown trigger\n");
delete m_trigger;
m_trigger = NULL;
return;
case FAMILY_MSO5:
case FAMILY_MSO6:
{
m_transport->SendCommand("TRIG:A:TYP?");
string reply = m_transport->ReadReply();

if(reply == "EDG")
PullEdgeTrigger();
else
{
LogWarning("Unknown trigger type %s\n", reply.c_str());
delete m_trigger;
m_trigger = NULL;
}
}
break;

default:
LogWarning("PullTrigger() not implemented for this scope family\n");
break;
}
}

@@ -838,57 +878,90 @@ void TektronixOscilloscope::PullEdgeTrigger()
//Create a new trigger if necessary
if(m_trigger == NULL)
m_trigger = new EdgeTrigger(this);
//EdgeTrigger* et = dynamic_cast<EdgeTrigger*>(m_trigger);
EdgeTrigger* et = dynamic_cast<EdgeTrigger*>(m_trigger);

lock_guard<recursive_mutex> lock(m_mutex);

/*
//Check cache
//No locking, worst case we return a result a few seconds old
if(m_triggerChannelValid)
return m_triggerChannel;
switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
{
//Source channel
m_transport->SendCommand("TRIG:A:EDGE:SOU?");
auto reply = m_transport->ReadReply();
et->SetInput(0, StreamDescriptor(GetChannelByHwName(reply), 0), true);

lock_guard<recursive_mutex> lock(m_mutex);
//Trigger level
m_transport->SendCommand("TRIG:A:LEV?");
et->SetLevel(stof(m_transport->ReadReply()));

//Look it up
m_transport->SendCommand("TRIG:SOUR?");
string ret = m_transport->ReadReply();
//For some reason we get 3 more values after this. Discard them.
for(int i=0; i<3; i++)
m_transport->ReadReply();

if(ret.find("CHAN") == 0)
{
m_triggerChannelValid = true;
m_triggerChannel = atoi(ret.c_str()+4) - 1;
return m_triggerChannel;
}
else if(ret == "EXT")
{
m_triggerChannelValid = true;
m_triggerChannel = m_extTrigChannel->GetIndex();
return m_triggerChannel;
}
else
{
m_triggerChannelValid = false;
LogWarning("Unknown trigger source %s\n", ret.c_str());
return 0;
}
//Edge slope
m_transport->SendCommand("TRIG:A:EDGE:SLO?");
reply = m_transport->ReadReply();
if(reply == "RIS")
et->SetType(EdgeTrigger::EDGE_RISING);
else if(reply == "FALL")
et->SetType(EdgeTrigger::EDGE_FALLING);
else if(reply == "EIT")
et->SetType(EdgeTrigger::EDGE_ANY);
}
break;

//Check cache.
//No locking, worst case we return a just-invalidated (but still fresh-ish) result.
if(m_triggerLevelValid)
return m_triggerLevel;
default:
/*
//Check cache
//No locking, worst case we return a result a few seconds old
if(m_triggerChannelValid)
return m_triggerChannel;
lock_guard<recursive_mutex> lock(m_mutex);
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand("TRIG:LEV?");
string ret = m_transport->ReadReply();
//Look it up
m_transport->SendCommand("TRIG:SOUR?");
string ret = m_transport->ReadReply();
double level;
sscanf(ret.c_str(), "%lf", &level);
m_triggerLevel = level;
m_triggerLevelValid = true;
return level;
*/
if(ret.find("CHAN") == 0)
{
m_triggerChannelValid = true;
m_triggerChannel = atoi(ret.c_str()+4) - 1;
return m_triggerChannel;
}
else if(ret == "EXT")
{
m_triggerChannelValid = true;
m_triggerChannel = m_extTrigChannel->GetIndex();
return m_triggerChannel;
}
else
{
m_triggerChannelValid = false;
LogWarning("Unknown trigger source %s\n", ret.c_str());
return 0;
}
//Check cache.
//No locking, worst case we return a just-invalidated (but still fresh-ish) result.
if(m_triggerLevelValid)
return m_triggerLevel;
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand("TRIG:LEV?");
string ret = m_transport->ReadReply();
double level;
sscanf(ret.c_str(), "%lf", &level);
m_triggerLevel = level;
m_triggerLevelValid = true;
return level;
*/
break;
}
}

void TektronixOscilloscope::PushTrigger()
@@ -908,29 +981,42 @@ void TektronixOscilloscope::PushEdgeTrigger(EdgeTrigger* trig)
{
lock_guard<recursive_mutex> lock(m_mutex);

//TODO: Source
//m_transport->SendCommand(string("TRIG:SOURCE ") + trig->GetInput(0).m_channel->GetHwname());
switch(m_family)
{
case FAMILY_MSO5:
case FAMILY_MSO6:
{
m_transport->SendCommand(string("TRIG:A:EDGE:SOU ") + trig->GetInput(0).m_channel->GetHwname());
m_transport->SendCommand(
string("TRIG:A:LEV:") + trig->GetInput(0).m_channel->GetHwname() + " " +
to_string(trig->GetLevel()));

//Level
char tmp[32];
snprintf(tmp, sizeof(tmp), "TRIG:LEV %.3f", trig->GetLevel());
m_transport->SendCommand(tmp);
switch(trig->GetType())
{
case EdgeTrigger::EDGE_RISING:
m_transport->SendCommand("TRIG:A:EDGE:SLO RIS");
break;

//TODO: Slope
/*
switch(trig->GetType())
{
case EdgeTrigger::EDGE_RISING:
m_transport->SendCommand("TRIG:SLOPE POS");
break;
case EdgeTrigger::EDGE_FALLING:
m_transport->SendCommand("TRIG:SLOPE NEG");
break;
case EdgeTrigger::EDGE_ANY:
m_transport->SendCommand("TRIG:SLOPE EITH");
case EdgeTrigger::EDGE_FALLING:
m_transport->SendCommand("TRIG:A:EDGE:SLO FALL");
break;

case EdgeTrigger::EDGE_ANY:
m_transport->SendCommand("TRIG:A:EDGE:SLO ANY");
break;

default:
break;
}
}
break;

default:
return;
{
char tmp[32];
snprintf(tmp, sizeof(tmp), "TRIG:LEV %.3f", trig->GetLevel());
m_transport->SendCommand(tmp);
}
break;
}
*/
}
Loading