Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ stamp-h?
/tests/*.log
/tests/*.trs
/tests/main
.vscode/
9 changes: 9 additions & 0 deletions contrib/60-libsigrok.rules
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@ ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0e11", ENV{ID_SIGROK}="1"
# Rigol MSO5000 series
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0515", ENV{ID_SIGROK}="1"

# Rigol DHO800 series
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044d", ENV{ID_SIGROK}="1"

# Rigol DHO800 and DHO900 series
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044c", ENV{ID_SIGROK}="1"

# Rigol DHO1000 series
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0610", ENV{ID_SIGROK}="1"

# Rohde&Schwarz HMO series mixed-signal oscilloscope (previously branded Hameg) VCP/USBTMC mode
ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0117", ENV{ID_SIGROK}="1"
ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", ENV{ID_SIGROK}="1"
Expand Down
132 changes: 114 additions & 18 deletions src/hardware/rigol-ds/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ static const uint64_t timebases[][2] = {

static const uint64_t vdivs[][2] = {
/* microvolts */
{ 200, 1000000 },
{ 500, 1000000 },
/* millivolts */
{ 1, 1000 },
Expand Down Expand Up @@ -185,6 +186,10 @@ enum series {
DS4000,
MSO5000,
MSO7000A,
DHO800,
DHO900,
DHO1000,
DHO4000,
};

/* short name, full name */
Expand Down Expand Up @@ -217,6 +222,14 @@ static const struct rigol_ds_series supported_series[] = {
{1000, 1}, {500, 1000000}, 10, 1000, 0},
[MSO7000A] = {VENDOR(AGILENT), "MSO7000A", PROTOCOL_V4, FORMAT_IEEE488_2,
{50, 1}, {2, 1000}, 10, 1000, 8000000},
[DHO800] = {VENDOR(RIGOL), "DHO800", PROTOCOL_V6, FORMAT_IEEE488_2,
{500, 1}, {500, 1000000}, 10, 1000, 0},
[DHO900] = {VENDOR(RIGOL), "DHO900", PROTOCOL_V6, FORMAT_IEEE488_2,
{500, 1}, {200, 1000000}, 10, 1000, 0},
[DHO1000] = {VENDOR(RIGOL), "DHO1000", PROTOCOL_V6, FORMAT_IEEE488_2,
{500, 1}, {500, 1000000}, 10, 1000, 0},
[DHO4000] = {VENDOR(RIGOL), "DHO4000", PROTOCOL_V6, FORMAT_IEEE488_2,
{500, 1}, {100, 1000000}, 10, 1000, 0},
};

#define SERIES(x) &supported_series[x]
Expand Down Expand Up @@ -291,6 +304,24 @@ static const struct rigol_ds_model supported_models[] = {
{SERIES(MSO5000), "MSO5354", {1, 1000000000}, CH_INFO(4, true), std_cmd},
/* TODO: Digital channels are not yet supported on MSO7000A. */
{SERIES(MSO7000A), "MSO7034A", {2, 1000000000}, CH_INFO(4, false), mso7000a_cmd},
{SERIES(DHO800), "DHO802", {5, 1000000000}, CH_INFO(2, false), std_cmd},
{SERIES(DHO800), "DHO804", {5, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO800), "DHO812", {5, 1000000000}, CH_INFO(2, false), std_cmd},
{SERIES(DHO800), "DHO814", {5, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO800), "DHO824", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO900), "DHO914", {2, 1000000000}, CH_INFO(4, true), std_cmd},
{SERIES(DHO900), "DHO914S", {2, 1000000000}, CH_INFO(4, true), std_cmd},
{SERIES(DHO900), "DHO924", {2, 1000000000}, CH_INFO(4, true), std_cmd},
{SERIES(DHO900), "DHO924S", {2, 1000000000}, CH_INFO(4, true), std_cmd},
{SERIES(DHO1000), "DHO1072", {2, 1000000000}, CH_INFO(2, false), std_cmd},
{SERIES(DHO1000), "DHO1074", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO1000), "DHO1102", {2, 1000000000}, CH_INFO(2, false), std_cmd},
{SERIES(DHO1000), "DHO1104", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO1000), "DHO1202", {2, 1000000000}, CH_INFO(2, false), std_cmd},
{SERIES(DHO1000), "DHO1204", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO4000), "DHO4204", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO4000), "DHO4404", {2, 1000000000}, CH_INFO(4, false), std_cmd},
{SERIES(DHO4000), "DHO4804", {2, 1000000000}, CH_INFO(4, false), std_cmd},
};

static struct sr_dev_driver rigol_ds_driver_info;
Expand Down Expand Up @@ -913,20 +944,45 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
some_digital = TRUE;
/* Turn on LA module if currently off. */
if (!devc->la_enabled) {
if (rigol_ds_config_set(sdi, protocol >= PROTOCOL_V3 ?
":LA:STAT ON" : ":LA:DISP ON") != SR_OK)
switch (protocol) {
case PROTOCOL_V1:
case PROTOCOL_V2:
cmd = ":LA:DISP ON";
break;
case PROTOCOL_V3:
case PROTOCOL_V4:
case PROTOCOL_V5:
cmd = ":LA:STAT ON";
break;
case PROTOCOL_V6:
default:
cmd = ":LA:ENAB ON";
break;
}
if (rigol_ds_config_set(sdi, cmd) != SR_OK)
return SR_ERR;
devc->la_enabled = TRUE;
}
}
if (ch->enabled != devc->digital_channels[ch->index]) {
/* Enabled channel is currently disabled, or vice versa. */
if (protocol >= PROTOCOL_V5)
cmd = ":LA:DISP D%d,%s";
else if (protocol >= PROTOCOL_V3)
cmd = ":LA:DIG%d:DISP %s";
else
cmd = ":DIG%d:TURN %s";
switch (protocol) {
case PROTOCOL_V1:
case PROTOCOL_V2:
cmd = ":DIG%d:TURN %s";
break;
case PROTOCOL_V3:
case PROTOCOL_V4:
cmd = ":LA:DIG%d:DISP %s";
break;
case PROTOCOL_V5:
cmd = ":LA:DISP D%d,%s";
break;
case PROTOCOL_V6:
default:
cmd = ":LA:DIG:ENAB D%d,%s";
break;
}

if (rigol_ds_config_set(sdi, cmd, ch->index,
ch->enabled ? "ON" : "OFF") != SR_OK)
Expand All @@ -940,10 +996,29 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
return SR_ERR;

/* Turn off LA module if on and no digital channels selected. */
if (devc->la_enabled && !some_digital)
if (rigol_ds_config_set(sdi,
devc->model->series->protocol >= PROTOCOL_V3 ?
":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK)
if (devc->la_enabled && !some_digital) {
switch (protocol) {
case PROTOCOL_V1:
case PROTOCOL_V2:
cmd = ":LA:DISP OFF";
break;
case PROTOCOL_V3:
case PROTOCOL_V4:
case PROTOCOL_V5:
cmd = ":LA:STAT OFF";
break;
case PROTOCOL_V6:
default:
cmd = ":LA:ENAB OFF";
break;
}
if (rigol_ds_config_set(sdi, cmd) != SR_OK)
return SR_ERR;
}

/* For DHO scopes, trigger must be in stop mode to start memory or segmented acquisition */
if((protocol == PROTOCOL_V6)&&((devc->data_source == DATA_SOURCE_SEGMENTED)||(devc->data_source == DATA_SOURCE_MEMORY)))
if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
return SR_ERR;

/* Set memory mode. */
Expand All @@ -969,10 +1044,30 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc->num_frames_segmented = frames;
break;
}
case PROTOCOL_V6:
{
/* DHO scopes need to be in UltraAcquire mode for segmented acquisoton */
/* This command is not working as for firmware version v00.01.02.00.02 of 2023/12/28
the scope has to be put manually in UltraAcquire mode for segmented acquisition to work */
//if (rigol_ds_config_set(sdi, ":ACQ:TYPE ULTR") != SR_OK)
// return SR_ERR; */

int frames = 0;
//if (sr_scpi_get_int(sdi->conn, ":REC:FRAM?", &frames) != SR_OK)
if (sr_scpi_get_int(sdi->conn, ":ACQ:ULTR:MAXF?", &frames) != SR_OK)
return SR_ERR;
if (frames <= 0) {
sr_err("No segmented data available");
return SR_ERR;
}
devc->num_frames_segmented = frames;
/* Continue with REC:CURR command */
}
// fall through
case PROTOCOL_V5:
/* The frame limit has to be read on the fly, just set up
* reading of the first frame */
if (rigol_ds_config_set(sdi, "REC:CURR 1") != SR_OK)
if (rigol_ds_config_set(sdi, ":REC:CURR 1") != SR_OK)
return SR_ERR;
break;
default:
Expand All @@ -984,7 +1079,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc->analog_frame_size = analog_frame_size(sdi);
devc->digital_frame_size = digital_frame_size(sdi);

switch (devc->model->series->protocol) {
switch (protocol) {
case PROTOCOL_V2:
if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK)
return SR_ERR;
Expand Down Expand Up @@ -1021,7 +1116,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
(devc->timebase * devc->model->series->num_horizontal_divs);
} else {
float xinc;
if (devc->model->series->protocol < PROTOCOL_V3) {
if (protocol < PROTOCOL_V3) {
sr_err("Cannot get samplerate (below V3).");
return SR_ERR;
}
Expand All @@ -1037,8 +1132,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc->sample_rate = 1. / xinc;
}

if (rigol_ds_capture_start(sdi) != SR_OK)
return SR_ERR;
ret = rigol_ds_capture_start(sdi);
if (ret != SR_OK)
return ret;

/* Start of first frame. */
std_session_send_df_frame_begin(sdi);
Expand All @@ -1065,7 +1161,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)

static struct sr_dev_driver rigol_ds_driver_info = {
.name = "rigol-ds",
.longname = "Rigol DS",
.longname = "Rigol DS/DHO",
.api_version = 1,
.init = std_init,
.cleanup = std_cleanup,
Expand Down
77 changes: 61 additions & 16 deletions src/hardware/rigol-ds/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,13 @@ SR_PRIV int rigol_ds_config_set(const struct sr_dev_inst *sdi, const char *forma
return SR_ERR;

if (devc->model->series->protocol == PROTOCOL_V2) {
/* The DS1000 series needs this stupid delay, *OPC? doesn't work. */
/* The DS1000 series needs this stupid delay, *OPC? doesn't work.*/
sr_spew("delay %dms", 100);
g_usleep(100 * 1000);
return SR_OK;
} else if (devc->model->series->protocol == PROTOCOL_V6) {
/* Same goes for DHO series but they can handle faster response...*/
return SR_OK;
} else {
return sr_scpi_get_opc(sdi->conn);
}
Expand Down Expand Up @@ -385,6 +388,7 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
case PROTOCOL_V3:
case PROTOCOL_V4:
case PROTOCOL_V5:
case PROTOCOL_V6:
if (first_frame && rigol_ds_config_set(sdi, ":WAV:FORM BYTE") != SR_OK)
return SR_ERR;
if (devc->data_source == DATA_SOURCE_LIVE) {
Expand Down Expand Up @@ -417,13 +421,23 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
buffer_samples = devc->model->series->buffer_samples;
if (first_frame && buffer_samples == 0)
{
/* The DS4000 series does not have a fixed memory depth, it
/* The DS4000 and DHO series does not have a fixed memory depth, it
* can be chosen from the menu and also varies with number
* of active channels. Retrieve the actual number with the
* ACQ:MDEP command. */
sr_scpi_get_int(sdi->conn, "ACQ:MDEP?", &buffer_samples);
/* TODO : what about digital channels ? */
devc->analog_frame_size = devc->digital_frame_size =
buffer_samples;

/* For some reason, as for DHO firmware version v00.01.02.00.02 of 2023/12/28,
* segmented acquisition does not work over multiple data blocks : DATA? command on a frame
* portion results in a header, declaring an empty content, of the form '#9000000000'. */
if(devc->data_source == DATA_SOURCE_SEGMENTED && devc->analog_frame_size > ACQ_BLOCK_SIZE) {
sr_err("Data source 'Segmented' not supported for memory depth > %d points.",ACQ_BLOCK_SIZE);
return SR_ERR_NA;
}

}
else if (first_frame)
{
Expand Down Expand Up @@ -499,6 +513,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
break;
case PROTOCOL_V4:
case PROTOCOL_V5:
case PROTOCOL_V6:
if (ch->type == SR_CHANNEL_ANALOG) {
if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d",
ch->index + 1) != SR_OK)
Expand All @@ -514,7 +529,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
":WAV:MODE NORM" :":WAV:MODE RAW") != SR_OK)
return SR_ERR;

if (devc->data_source != DATA_SOURCE_LIVE) {
if ((devc->data_source != DATA_SOURCE_LIVE) && (devc->model->series->protocol != PROTOCOL_V6)) {
if (rigol_ds_config_set(sdi, ":WAV:RES") != SR_OK)
return SR_ERR;
}
Expand Down Expand Up @@ -669,17 +684,17 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)

if (devc->num_block_bytes == 0) {
if (devc->model->series->protocol >= PROTOCOL_V4) {
if (first_frame && rigol_ds_config_set(sdi, ":WAV:START %d",
if ((first_frame || (devc->model->series->protocol == PROTOCOL_V6)) && rigol_ds_config_set(sdi, ":WAV:START %d",
devc->num_channel_bytes + 1) != SR_OK)
return TRUE;
if (first_frame && rigol_ds_config_set(sdi, ":WAV:STOP %d",
if ((first_frame || (devc->model->series->protocol == PROTOCOL_V6)) && rigol_ds_config_set(sdi, ":WAV:STOP %d",
MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE,
devc->analog_frame_size)) != SR_OK)
return TRUE;
}

if (devc->model->series->protocol >= PROTOCOL_V3) {
if (rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK)
if ((devc->model->series->protocol != PROTOCOL_V6) && rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK)
return TRUE;
if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK)
return TRUE;
Expand Down Expand Up @@ -846,6 +861,13 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
/* Get the next frame, starting with the first channel. */
devc->channel_entry = devc->enabled_channels;

if (devc->data_source == DATA_SOURCE_SEGMENTED &&
devc->model->series->protocol == PROTOCOL_V6) {
/* Move to next frame in segmented mode*/
if (rigol_ds_config_set(sdi, ":REC:CURR %d", devc->num_frames + 1) != SR_OK)
return SR_ERR;
}

rigol_ds_capture_start(sdi);

/* Start of next frame. */
Expand Down Expand Up @@ -882,20 +904,43 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)

/* Digital channel state. */
if (devc->model->has_digital) {
if (sr_scpi_get_bool(sdi->conn,
devc->model->series->protocol >= PROTOCOL_V3 ?
":LA:STAT?" : ":LA:DISP?",
&devc->la_enabled) != SR_OK)
switch (devc->model->series->protocol) {
case PROTOCOL_V1:
case PROTOCOL_V2:
cmd = ":LA:DISP?";
break;
case PROTOCOL_V3:
case PROTOCOL_V4:
case PROTOCOL_V5:
cmd = ":LA:STAT?";
break;
case PROTOCOL_V6:
default:
cmd = ":LA:ENAB?";
break;
}
if (sr_scpi_get_bool(sdi->conn, cmd, &devc->la_enabled) != SR_OK)
return SR_ERR;
sr_dbg("Logic analyzer %s, current digital channel state:",
devc->la_enabled ? "enabled" : "disabled");
for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) {
if (devc->model->series->protocol >= PROTOCOL_V5)
cmd = g_strdup_printf(":LA:DISP? D%d", i);
else if (devc->model->series->protocol >= PROTOCOL_V3)
cmd = g_strdup_printf(":LA:DIG%d:DISP?", i);
else
cmd = g_strdup_printf(":DIG%d:TURN?", i);
switch (devc->model->series->protocol) {
case PROTOCOL_V1:
case PROTOCOL_V2:
cmd = g_strdup_printf(":DIG%d:TURN?", i);
break;
case PROTOCOL_V3:
case PROTOCOL_V4:
cmd = g_strdup_printf(":LA:DIG%d:DISP?", i);
break;
case PROTOCOL_V5:
cmd = g_strdup_printf(":LA:DISP? D%d", i);
break;
case PROTOCOL_V6:
default:
cmd = g_strdup_printf(":LA:DIG:ENAB? D%d", i);
break;
}
res = sr_scpi_get_bool(sdi->conn, cmd, &devc->digital_channels[i]);
g_free(cmd);
if (res != SR_OK)
Expand Down
Loading