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

Commits on May 3, 2019

  1. Copy the full SHA
    0069d1a View commit details
Showing with 168 additions and 13 deletions.
  1. +6 −1 scopehal/RigolLANOscilloscope.cpp
  2. +1 −0 scopehal/RigolLANOscilloscope.h
  3. +157 −12 scopehal/RigolOscilloscope.cpp
  4. +4 −0 scopehal/RigolOscilloscope.h
7 changes: 6 additions & 1 deletion scopehal/RigolLANOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -78,10 +78,15 @@ string RigolLANOscilloscope::ReadReply()
{
if(!m_socket.RecvLooped((unsigned char*)&tmp, 1))
break;
if(tmp == '\n')
if( (tmp == '\n') || (tmp == ';') )
break;
else
ret += tmp;
}
return ret;
}

void RigolLANOscilloscope::ReadRawData(size_t len, unsigned char* buf)
{
m_socket.RecvLooped(buf, len);
}
1 change: 1 addition & 0 deletions scopehal/RigolLANOscilloscope.h
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ class RigolLANOscilloscope : public RigolOscilloscope

virtual void SendCommand(std::string cmd);
virtual std::string ReadReply();
virtual void ReadRawData(size_t len, unsigned char* buf);
};

#endif
169 changes: 157 additions & 12 deletions scopehal/RigolOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@ using namespace std;
// Construction / destruction

RigolOscilloscope::RigolOscilloscope()
: m_triggerArmed(false)
, m_triggerOneShot(false)
{
//nothing in base class
}
@@ -113,6 +115,10 @@ void RigolOscilloscope::SharedCtorInit()
true));
}
m_analogChannelCount = nchans;

//Configure acquisition modes
SendCommand("WAV:FORM BYTE");
SendCommand("WAV:MODE RAW");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -282,40 +288,168 @@ void RigolOscilloscope::ResetTriggerConditions()

Oscilloscope::TriggerMode RigolOscilloscope::PollTrigger()
{
//FIXME
return Oscilloscope::TRIGGER_MODE_RUN;
lock_guard<recursive_mutex> lock(m_mutex);

SendCommand("TRIG:STAT?");
string stat = ReadReply();

if(stat == "TD")
return TRIGGER_MODE_TRIGGERED;
else if(stat == "RUN")
return TRIGGER_MODE_RUN;
else if(stat == "WAIT")
return TRIGGER_MODE_WAIT;
else if(stat == "AUTO")
return TRIGGER_MODE_AUTO;
else
{
//The "TD" state is not sticky on Rigol scopes, unlike the equivalent LeCroy status register bit.
//The scope will go from "run" to "stop" state on trigger with only a momentary pass through "TD".
//If we armed the trigger recently and we're now stopped, this means we must have triggered.
if(m_triggerArmed)
{
m_triggerArmed = false;
return TRIGGER_MODE_TRIGGERED;
}

//Nope, we're actually stopped
return TRIGGER_MODE_STOP;
}
}

bool RigolOscilloscope::AcquireData(bool toQueue)
{
//FIXME
return false;
//workaround for high latency links to let the UI thread get the mutex
usleep(1000);

lock_guard<recursive_mutex> lock(m_mutex);

LogDebug("Acquiring data\n");
LogIndenter li;

//Grab the analog waveform data
int unused1;
int unused2;
int npoints;
int unused3;
double sec_per_sample;
double xorigin;
double unused4;
double yincrement;
double yreference;
size_t maxpoints = 250*1000;
unsigned char* temp_buf = new unsigned char[maxpoints];
for(size_t i=0; i<m_analogChannelCount; i++)
{
LogDebug("Channel %zu\n", i);

SendCommand(string("WAV:SOUR ") + m_channels[i]->GetHwname());

//This is basically the same function as a LeCroy WAVEDESC, but much less detailed
SendCommand("WAV:PRE?");
string reply = ReadReply();
sscanf(reply.c_str(), "%d,%d,%d,%d,%lf,%lf,%lf,%lf,%lf,%lf",
&unused1,
&unused2,
&npoints,
&unused3,
&sec_per_sample,
&xorigin,
&unused4,
&yincrement,
&yreference);
int64_t ps_per_sample = round(sec_per_sample * 1e12f);
LogDebug("%ld ps per sample\n", ps_per_sample);
LogDebug("%d points\n", npoints);

//Downloading the waveform is a pain in the butt, because we can only pull 250K points at a time!
for(size_t npoint=0; npoint < maxpoints; npoint += maxpoints)
{
//Ask for the data
char tmp[128];
snprintf(tmp, sizeof(tmp), "WAV:STAR %zu", npoint + 1); //ONE based indexing WTF
SendCommand(tmp);
size_t end = npoint + maxpoints;
if(end > npoints)
end = npoints;
snprintf(tmp, sizeof(tmp), "WAV:STOP %zu", end + 1);
SendCommand(tmp);

//Read the data block
size_t blocksize = end - npoints;
SendCommand("WAV:DATA?");
ReadRawData(blocksize, temp_buf);

LogDebug("%02x %02x %02x %02x",
temp_buf[0],
temp_buf[1],
temp_buf[2],
temp_buf[3]);
}
}

//Clean up
delete[] temp_buf;

//TODO: support digital channels

//Re-arm the trigger if not in one-shot mode
if(!m_triggerOneShot)
{
SendCommand("TRIG_MODE SINGLE");
m_triggerArmed = true;
}

return true;
}

void RigolOscilloscope::Start()
{
//FIXME
LogDebug("Start single trigger\n");
lock_guard<recursive_mutex> lock(m_mutex);
SendCommand("SING");
m_triggerArmed = true;
m_triggerOneShot = false;
}

void RigolOscilloscope::StartSingleTrigger()
{
//FIXME
lock_guard<recursive_mutex> lock(m_mutex);
SendCommand("SING");
m_triggerArmed = true;
m_triggerOneShot = true;
}

void RigolOscilloscope::Stop()
{
//FIXME
lock_guard<recursive_mutex> lock(m_mutex);
SendCommand("STOP");
m_triggerArmed = false;
m_triggerOneShot = true;
}

bool RigolOscilloscope::IsTriggerArmed()
{
//FIXME
return true;
return m_triggerArmed;
}

size_t RigolOscilloscope::GetTriggerChannelIndex()
{
//FIXME
lock_guard<recursive_mutex> lock(m_mutex);

//This is nasty because there are separate commands to see what the trigger source is
//depending on what the trigger type is!!!
//FIXME: For now assume edge
SendCommand("TRIG:EDG:SOUR?");
string ret = ReadReply();

for(size_t i=0; i<m_channels.size(); i++)
{
if(m_channels[i]->GetHwname() == ret)
return i;
}

LogWarning("Unknown trigger source %s\n", ret.c_str());
return 0;
}

@@ -326,8 +460,19 @@ void RigolOscilloscope::SetTriggerChannelIndex(size_t i)

float RigolOscilloscope::GetTriggerVoltage()
{
//FIXME
return 0;
lock_guard<recursive_mutex> lock(m_mutex);

//This is nasty because there are separate commands to see what the trigger source is
//depending on what the trigger type is!!!
//FIXME: For now assume edge
SendCommand("TRIG:EDG:LEV?");
string ret = ReadReply();

double level;
sscanf(ret.c_str(), "%lf", &level);
//lock_guard<recursive_mutex> lock(m_cacheMutex);
//m_channelOffsets[i] = offset;
return level;
}

void RigolOscilloscope::SetTriggerVoltage(float v)
4 changes: 4 additions & 0 deletions scopehal/RigolOscilloscope.h
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ class RigolOscilloscope : public Oscilloscope

virtual void SendCommand(std::string cmd) =0;
virtual std::string ReadReply() =0;
virtual void ReadRawData(size_t len, unsigned char* buf) =0;

protected:
std::string m_vendor;
@@ -104,6 +105,9 @@ class RigolOscilloscope : public Oscilloscope

std::map<size_t, double> m_channelOffsets;
std::map<size_t, double> m_channelVoltageRanges;

bool m_triggerArmed;
bool m_triggerOneShot;
};

#endif