Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rigol function generator #511

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 230 additions & 1 deletion scopehal/RigolOscilloscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ RigolOscilloscope::RigolOscilloscope(SCPITransport* transport)
m_bandwidth = 70;
}
}
// test if function generator functionality is available
// TODO looking at the commands above, we probably need a more hacky detection method
// m_transport->SendCommand(":SYST:OPT:STAT? AWG\n");
// reply = Trim(m_transport->ReadReply());
// reply == "1" ? true : false;
m_hasFunctionGen = true; //reply == "1" ? true : false;
}
}
else
Expand Down Expand Up @@ -186,7 +192,10 @@ RigolOscilloscope::~RigolOscilloscope()

unsigned int RigolOscilloscope::GetInstrumentTypes()
{
return Instrument::INST_OSCILLOSCOPE;
unsigned int type = INST_OSCILLOSCOPE;
if(m_hasFunctionGen)
type |= INST_FUNCTION;
return type;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1257,3 +1266,223 @@ void RigolOscilloscope::PushEdgeTrigger(EdgeTrigger* trig)
return;
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function generator mode

int RigolOscilloscope::GetFunctionChannelCount()
{
if(m_hasFunctionGen)
return 2;
else
return 0;
}

string RigolOscilloscope::GetFunctionChannelName(int chan)
{
return chan==0 ? "GI" : "GII";
}

bool RigolOscilloscope::GetFunctionChannelActive(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:OUTP:STAT?");
} else {
m_transport->SendCommand(":SOUR2:OUTP:STAT?");
}

auto reply = Trim(m_transport->ReadReply());
return reply=="1" ? true : false;
}

void RigolOscilloscope::SetFunctionChannelActive(int chan, bool on)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
if (on) {
m_transport->SendCommand(":SOUR1:OUTP:STAT ON");
} else {
m_transport->SendCommand(":SOUR1:OUTP:STAT OF");
}
} else {
if (on) {
m_transport->SendCommand(":SOUR2:OUTP:STAT ON");
} else {
m_transport->SendCommand(":SOUR2:OUTP:STAT OF");
}
}
}

float RigolOscilloscope::GetFunctionChannelDutyCycle(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:PULS:DCYC?");
} else {
m_transport->SendCommand(":SOUR2:PULS:DCYC?");
}
auto reply = Trim(m_transport->ReadReply());
double duty;
sscanf(reply.c_str(), "%lf", &duty);
return duty;
}

void RigolOscilloscope::SetFunctionChannelDutyCycle(int chan, float duty)
{
char buf[64];
snprintf(buf, 64, ":SOUR%d:PULS:DCYC %f", chan+1, duty);
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand(buf);
}

float RigolOscilloscope::GetFunctionChannelAmplitude(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:VOLT:LEV:IMM:AMPL?");
} else {
m_transport->SendCommand(":SOUR2:VOLT:LEV:IMM:AMPL?");
}
auto reply = Trim(m_transport->ReadReply());
double duty;
sscanf(reply.c_str(), "%lf", &duty);
return duty;
}

void RigolOscilloscope::SetFunctionChannelAmplitude(int chan, float amplitude)
{
char buf[64];
snprintf(buf, 64, ":SOUR%d:VOLT:LEV:IMM:AMPL %f", chan+1, amplitude);
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand(buf);
}

float RigolOscilloscope::GetFunctionChannelOffset(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:VOLT:LEV:IMM:OFFS?");
} else {
m_transport->SendCommand(":SOUR2:VOLT:LEV:IMM:OFFS?");
}
auto reply = Trim(m_transport->ReadReply());
double duty;
sscanf(reply.c_str(), "%lf", &duty);
return duty;
}

void RigolOscilloscope::SetFunctionChannelOffset(int chan, float offset)
{
char buf[64];
snprintf(buf, 64, ":SOUR%d:VOLT:LEV:IMM:OFFS %f", chan+1, offset);
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand(buf);
}

float RigolOscilloscope::GetFunctionChannelFrequency(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:FREQ:FIX?");
} else {
m_transport->SendCommand(":SOUR2:FREQ:FIX?");
}
auto reply = Trim(m_transport->ReadReply());
double duty;
sscanf(reply.c_str(), "%lf", &duty);
return duty;
}

void RigolOscilloscope::SetFunctionChannelFrequency(int chan, float hz)
{
char buf[64];
snprintf(buf, 64, ":SOUR%d:FREQ:FIX %f", chan+1, hz);
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand(buf);
}

FunctionGenerator::WaveShape RigolOscilloscope::GetFunctionChannelShape(int chan)
{
lock_guard<recursive_mutex> lock(m_mutex);
if (chan==0) {
m_transport->SendCommand(":SOUR1:FUNC:SHAP?");
} else {
m_transport->SendCommand(":SOUR2:FUNC:SHAP?");
}
auto reply = Trim(m_transport->ReadReply());
if (reply == "SIN")
return WaveShape::SHAPE_SINE;
else if (reply == "SQU")
return WaveShape::SHAPE_SQUARE;
else if (reply == "RAMP")
return WaveShape::SHAPE_TRIANGLE;
else if (reply == "PULS")
return WaveShape::SHAPE_PULSE;
else if (reply == "NOIS")
return WaveShape::SHAPE_NOISE;
else if (reply == "DC")
return WaveShape::SHAPE_DC;
else if (reply == "ARB")
return WaveShape::SHAPE_ARB;

LogWarning("RigolOscilloscope::GetFunctionChannelShape unsupported shape\n");
return WaveShape::SHAPE_SINE;
}

void RigolOscilloscope::SetFunctionChannelShape(int chan, WaveShape shape)
{
std::string shape_str;
switch (shape)
{
case WaveShape::SHAPE_SINE:
shape_str = "SIN";
break;
case WaveShape::SHAPE_SQUARE:
shape_str = "SQU";
break;
case WaveShape::SHAPE_TRIANGLE:
shape_str = "RAMP";
break;
case WaveShape::SHAPE_PULSE:
shape_str = "PULS";
break;
case WaveShape::SHAPE_NOISE:
shape_str = "NOIS";
break;
case WaveShape::SHAPE_DC:
shape_str = "DC";
break;
case WaveShape::SHAPE_ARB:
shape_str = "ARB";
break;
}
char buf[64];
snprintf(buf, 64, ":SOUR%d:FUNC:SHAP %s", chan+1, shape_str.c_str());
lock_guard<recursive_mutex> lock(m_mutex);
m_transport->SendCommand(buf);
}

float RigolOscilloscope::GetFunctionChannelRiseTime(int /*chan*/)
{
//app.wavesource.risetime
LogWarning("RigolOscilloscope::GetFunctionChannelRiseTime unimplemented\n");
return 0;
}

void RigolOscilloscope::SetFunctionChannelRiseTime(int /*chan*/, float /*sec*/)
{
LogWarning("RigolOscilloscope::SetFunctionChannelRiseTime unimplemented\n");
}

float RigolOscilloscope::GetFunctionChannelFallTime(int /*chan*/)
{
//app.wavesource.falltime
LogWarning("RigolOscilloscope::GetFunctionChannelFallTime unimplemented\n");
return 0;
}

void RigolOscilloscope::SetFunctionChannelFallTime(int /*chan*/, float /*sec*/)
{
LogWarning("RigolOscilloscope::SetFunctionChannelFallTime unimplemented\n");
}
26 changes: 25 additions & 1 deletion scopehal/RigolOscilloscope.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@

class EdgeTrigger;

class RigolOscilloscope : public SCPIOscilloscope
class RigolOscilloscope
: public SCPIOscilloscope
, public FunctionGenerator
{
public:
RigolOscilloscope(SCPITransport* transport);
Expand Down Expand Up @@ -92,6 +94,27 @@ class RigolOscilloscope : public SCPIOscilloscope
virtual bool IsInterleaving();
virtual bool SetInterleaving(bool combine);

//Function generator
virtual int GetFunctionChannelCount();
virtual std::string GetFunctionChannelName(int chan);
virtual bool GetFunctionChannelActive(int chan);
virtual void SetFunctionChannelActive(int chan, bool on);
virtual float GetFunctionChannelDutyCycle(int chan);
virtual void SetFunctionChannelDutyCycle(int chan, float duty);
virtual float GetFunctionChannelAmplitude(int chan);
virtual void SetFunctionChannelAmplitude(int chan, float amplitude);
virtual float GetFunctionChannelOffset(int chan);
virtual void SetFunctionChannelOffset(int chan, float offset);
virtual float GetFunctionChannelFrequency(int chan);
virtual void SetFunctionChannelFrequency(int chan, float hz);
virtual FunctionGenerator::WaveShape GetFunctionChannelShape(int chan);
virtual void SetFunctionChannelShape(int chan, WaveShape shape);
virtual float GetFunctionChannelRiseTime(int chan);
virtual void SetFunctionChannelRiseTime(int chan, float sec);
virtual float GetFunctionChannelFallTime(int chan);
virtual void SetFunctionChannelFallTime(int chan, float sec);


protected:
enum protocol_version
{
Expand Down Expand Up @@ -128,6 +151,7 @@ class RigolOscilloscope : public SCPIOscilloscope

int m_modelNumber;
unsigned int m_bandwidth;
bool m_hasFunctionGen;
bool m_opt200M;
protocol_version m_protocol;

Expand Down