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

Commits on Sep 15, 2020

  1. Copy the full SHA
    59ed1a8 View commit details
  2. Copy the full SHA
    b8eb887 View commit details
  3. LeCroyOscilloscope: initial LabMaster 10Zi support. Only tested again…

    …st MAUI Studio simulator, may not work on real hardware. Anybody have a LabMaster I can borrow to test? ;)
    azonenberg committed Sep 15, 2020
    Copy the full SHA
    9ae2b90 View commit details
8 changes: 8 additions & 0 deletions scopehal/AgilentEdgeTrigger.cpp
Original file line number Diff line number Diff line change
@@ -45,3 +45,11 @@ AgilentEdgeTrigger::~AgilentEdgeTrigger()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors

string AgilentEdgeTrigger::GetTriggerName()
{
return "Edge (Agilent)";
}
3 changes: 3 additions & 0 deletions scopehal/AgilentEdgeTrigger.h
Original file line number Diff line number Diff line change
@@ -53,6 +53,9 @@ class AgilentEdgeTrigger : public EdgeTrigger

void SetTypeExt(AgilentEdgeType type)
{ m_parameters[m_typename].SetIntVal(type); }

static std::string GetTriggerName();
TRIGGER_INITPROC(AgilentEdgeTrigger);
};

#endif
8 changes: 8 additions & 0 deletions scopehal/AgilentOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -779,3 +779,11 @@ void AgilentOscilloscope::PushEdgeTrigger(EdgeTrigger* trig)
return;
}
}

vector<string> AgilentOscilloscope::GetTriggerTypes()
{
vector<string> ret;
ret.push_back(AgilentEdgeTrigger::GetTriggerName());
return ret;
}

1 change: 1 addition & 0 deletions scopehal/AgilentOscilloscope.h
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@ class AgilentOscilloscope : public SCPIOscilloscope
virtual bool IsTriggerArmed();
virtual void PushTrigger();
virtual void PullTrigger();
virtual std::vector<std::string> GetTriggerTypes();

virtual std::vector<uint64_t> GetSampleRatesNonInterleaved();
virtual std::vector<uint64_t> GetSampleRatesInterleaved();
8 changes: 8 additions & 0 deletions scopehal/EdgeTrigger.cpp
Original file line number Diff line number Diff line change
@@ -52,6 +52,14 @@ EdgeTrigger::~EdgeTrigger()

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors

string EdgeTrigger::GetTriggerName()
{
return "Edge";
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Input validation

3 changes: 3 additions & 0 deletions scopehal/EdgeTrigger.h
Original file line number Diff line number Diff line change
@@ -59,6 +59,9 @@ class EdgeTrigger : public Trigger

virtual bool ValidateChannel(size_t i, StreamDescriptor stream);

static std::string GetTriggerName();
TRIGGER_INITPROC(EdgeTrigger);

protected:
std::string m_typename;
};
2 changes: 0 additions & 2 deletions scopehal/Filter.cpp
Original file line number Diff line number Diff line change
@@ -53,8 +53,6 @@ Gdk::Color Filter::m_standardColors[STANDARD_COLOR_COUNT] =
Gdk::Color("#404040") //COLOR_IDLE
};



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

140 changes: 116 additions & 24 deletions scopehal/LeCroyOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -46,6 +46,9 @@ LeCroyOscilloscope::LeCroyOscilloscope(SCPITransport* transport)
, m_hasDVM(false)
, m_hasFunctionGen(false)
, m_hasFastSampleRate(false)
, m_hasI2cTrigger(false)
, m_hasSpiTrigger(false)
, m_hasUartTrigger(false)
, m_triggerArmed(false)
, m_triggerOneShot(false)
, m_sampleRateValid(false)
@@ -137,6 +140,8 @@ void LeCroyOscilloscope::IdentifyHardware()
m_modelid = MODEL_WAVERUNNER_8K;
else if(m_model.find("SDA3") == 0)
m_modelid = MODEL_SDA_3K;
else if(m_model == "MCM-ZI-A")
m_modelid = MODEL_LABMASTER_ZI_A;
else if (m_vendor.compare("SIGLENT") == 0)
{
// TODO: if LeCroy and Siglent classes get split, then this should obviously
@@ -219,10 +224,36 @@ void LeCroyOscilloscope::DetectOptions()
LogDebug("* -M (extra sample rate and memory)\n");
}

//Ignore protocol decodes, we do those ourselves
else if( (o == "I2C") || (o == "UART") || (o == "SPI") )
//Protocol decode options are mostly ignored, but enable hardware trigger if we have it
else if(o == "I2C")
{
LogDebug("* %s (protocol decode, ignoring)\n", o.c_str());
m_hasI2cTrigger = true;
LogDebug("* I2C (I2C trigger/decode)\n");
}
else if(o == "I2C_TDME")
{
m_hasI2cTrigger = true;
LogDebug("* I2C_TDME (I2C trigger/decode/measure/eye)\n");
}
else if(o == "SPI")
{
m_hasSpiTrigger = true;
LogDebug("* SPI (SPI trigger/decode)\n");
}
else if(o == "SPI_TDME")
{
m_hasSpiTrigger = true;
LogDebug("* SPI (SPI trigger/decode/measure/eye)\n");
}
else if(o == "UART")
{
m_hasUartTrigger = true;
LogDebug("* UART (UART trigger/decode)\n");
}
else if(o == "UART_TDME")
{
m_hasUartTrigger = true;
LogDebug("* UART (UART trigger/decode/measure/eye)\n");
}

//Ignore UI options
@@ -282,35 +313,71 @@ void LeCroyOscilloscope::AddDigitalChannels(unsigned int count)
* WAVERUNNER8104-MS has 4 channels (plus 16 digital)
* DDA5005 / DDA5005A have 4 channels
* SDA3010 have 4 channels
* LabMaster just calls itself "MCM-Zi-A" and there's no information on the number of modules!
*/
void LeCroyOscilloscope::DetectAnalogChannels()
{
//General model format is family, number, suffix. Not all are always present.
//Trim off alphabetic characters from the start of the model number
size_t pos;
for(pos=0; pos < m_model.length(); pos++)
int nchans = 1;

switch(m_modelid)
{
if(isalpha(m_model[pos]))
continue;
else if(isdigit(m_model[pos]))
//DDA5005 and similar have 4 channels despite a model number ending in 5
//SDA3010 have 4 channels despite a model number ending in 0
case MODEL_DDA_5K:
case MODEL_SDA_3K:
nchans = 4;
break;
else
{
LogError("Unrecognized character (not alphanumeric) in model number %s\n", m_model.c_str());
return;
}
}

//Now we should be able to read the model number
int modelNum = atoi(m_model.c_str() + pos);
//LabMaster MCM could have any number of channels.
//This is ugly and produces errors in the remote log each time we start up, but does work.
case MODEL_LABMASTER_ZI_A:
{
char tmp[128];
for(int i=1; i<80; i++)
{
snprintf(tmp, sizeof(tmp), "VBS? 'return=IsObject(app.Acquisition.C%d)'", i);

//Last digit of the model number is normally the number of channels (WAVESURFER3022, HDO8108)
int nchans = modelNum % 10;
m_transport->SendCommand(tmp);
string reply = m_transport->ReadReply();

//DDA5005 and similar have 4 channels despite a model number ending in 5
//SDA3010 have 4 channels despite a model number ending in 0
if(m_modelid == MODEL_DDA_5K || m_modelid == MODEL_SDA_3K)
nchans = 4;
//All good
if(Trim(reply) == "-1")
nchans = i;

//Anything else is probably an error:
//Object doesn't support this property or method: 'app.Acquisition.C5'
else
break;
}
}
break;

//General model format is family, number, suffix. Not all are always present.
default:
{
//Trim off alphabetic characters from the start of the model number
size_t pos;
for(pos=0; pos < m_model.length(); pos++)
{
if(isalpha(m_model[pos]))
continue;
else if(isdigit(m_model[pos]))
break;
else
{
LogError("Unrecognized character (not alphanumeric) in model number %s\n", m_model.c_str());
return;
}
}

//Now we should be able to read the model number
int modelNum = atoi(m_model.c_str() + pos);

//Last digit of the model number is normally the number of channels (WAVESURFER3022, HDO8108)
nchans = modelNum % 10;
}
break;
}

for(int i=0; i<nchans; i++)
{
@@ -2019,6 +2086,18 @@ vector<uint64_t> LeCroyOscilloscope::GetSampleRatesNonInterleaved()
ret.push_back(20 * g);
break;

case MODEL_LABMASTER_ZI_A:
ret.push_back(5 * g);
ret.push_back(10 * g);
ret.push_back(20 * g); //FIXME: 20 and 40 Gsps give garbage data in the MAUI Studio simulator.
ret.push_back(40 * g); //Data looks wrong in MAUI as well as glscopeclient so doesn't seem to be something
//that we did. Looks like bits and pieces of waveform with gaps or overlap.
//Unclear if sim bug or actual issue, no testing on actual LabMaster hardware
//has been performed to date.
ret.push_back(80 * g);
//TODO: exact sample rates may depend on the acquisition module(s) connected
break;

default:
break;
}
@@ -2087,6 +2166,10 @@ vector<uint64_t> LeCroyOscilloscope::GetSampleDepthsNonInterleaved()
}
break;

//standard memory
case MODEL_LABMASTER_ZI_A:
ret.push_back(20 * m);

//TODO: add more models here
default:
break;
@@ -2644,3 +2727,12 @@ string LeCroyOscilloscope::Trim(string str)

return ret;
}

vector<string> LeCroyOscilloscope::GetTriggerTypes()
{
vector<string> ret;
ret.push_back(EdgeTrigger::GetTriggerName());

//TODO m_hasI2cTrigger m_hasSpiTrigger m_hasUartTrigger
return ret;
}
5 changes: 5 additions & 0 deletions scopehal/LeCroyOscilloscope.h
Original file line number Diff line number Diff line change
@@ -92,6 +92,7 @@ class LeCroyOscilloscope
virtual void PushTrigger();
virtual void PullTrigger();
virtual void EnableTriggerOutput();
virtual std::vector<std::string> GetTriggerTypes();

//DMM acquisition
virtual double GetVoltage();
@@ -143,6 +144,7 @@ class LeCroyOscilloscope
MODEL_DDA_5K,
MODEL_SDA_3K,
MODEL_SIGLENT_SDS2000X,
MODEL_LABMASTER_ZI_A,

MODEL_UNKNOWN
};
@@ -222,6 +224,9 @@ class LeCroyOscilloscope
bool m_hasDVM;
bool m_hasFunctionGen;
bool m_hasFastSampleRate; //-M models
bool m_hasI2cTrigger;
bool m_hasSpiTrigger;
bool m_hasUartTrigger;

bool m_triggerArmed;
bool m_triggerOneShot;
12 changes: 12 additions & 0 deletions scopehal/Oscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -42,6 +42,8 @@
#include <sys/types.h>
#include <dirent.h>

#include "EdgeTrigger.h"

using namespace std;

Oscilloscope::CreateMapType Oscilloscope::m_createprocs;
@@ -436,3 +438,13 @@ void Oscilloscope::SetDigitalHysteresis(size_t /*channel*/, float /*level*/)
void Oscilloscope::SetDigitalThreshold(size_t /*channel*/, float /*level*/)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Trigger configuration

vector<string> Oscilloscope::GetTriggerTypes()
{
vector<string> ret;
ret.push_back(EdgeTrigger::GetTriggerName());
return ret;
}
7 changes: 6 additions & 1 deletion scopehal/Oscilloscope.h
Original file line number Diff line number Diff line change
@@ -294,13 +294,18 @@ class Oscilloscope : public virtual Instrument
Ownership of the trigger object is retained by the Oscilloscope. This pointer may be invalidated by any future
call to GetTrigger() or PullTrigger().
*/
Trigger* GetTrigger(bool sync = true)
Trigger* GetTrigger(bool sync = false)
{
if(sync || (m_trigger == NULL) )
PullTrigger();
return m_trigger;
}

/**
@brief Gets a list of triggers this instrument supports
*/
virtual std::vector<std::string> GetTriggerTypes();

/**
@brief Updates m_trigger with any changes made from the instrument side
*/
25 changes: 25 additions & 0 deletions scopehal/Trigger.cpp
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@

using namespace std;

Trigger::CreateMapType Trigger::m_createprocs;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

@@ -45,3 +47,26 @@ Trigger::~Trigger()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Enumeration

void Trigger::DoAddTriggerClass(string name, CreateProcType proc)
{
m_createprocs[name] = proc;
}

void Trigger::EnumTriggers(vector<string>& names)
{
for(CreateMapType::iterator it=m_createprocs.begin(); it != m_createprocs.end(); ++it)
names.push_back(it->first);
}

Trigger* Trigger::CreateTrigger(string name, Oscilloscope* scope)
{
if(m_createprocs.find(name) != m_createprocs.end())
return m_createprocs[name](scope);

LogError("Invalid trigger name: %s\n", name.c_str());
return NULL;
}
Loading