From 702f42e8eb33d8d1ffb5b748097428c0f4434c6d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 19 Mar 2015 16:15:52 +0000 Subject: [PATCH] rigol-ds: Add DS1000Z series support. Tested on an MSO1104Z with firmware 00.04.02.SP4. The analog channels are captured correctly. For the MSO series, with digital channels, there are two outstanding issues: 1. Logic data is retrieved per-channel, one byte per sample, with the value in the LSB of each byte. The current datafeed logic format doesn't allow this format to be passed on directly. I suggest we resolve that rather than making the driver buffer and interleave the data. As stands, the code will retrieve data for all channels and pass it onto the datafeed with unitsize=1. Channel D0 can used correctly if selected alone. For other channels, data is passed to the frontend but the API does not provide a way to associate it with the correct channel. 2. Channels CH3 and CH4 are multiplexed with D0-7 and D8-15 respectively, so enabling these is mutually exclusive. We don't currently have a way to express this constraint to the frontend. --- src/hardware/rigol-ds/api.c | 55 +++++++---- src/hardware/rigol-ds/protocol.c | 151 +++++++++++++++++++++---------- src/hardware/rigol-ds/protocol.h | 7 +- 3 files changed, 144 insertions(+), 69 deletions(-) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index a142a2d8..60d63d59 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -175,6 +175,7 @@ enum series { DS2000, DS2000A, DSO1000, + DS1000Z, }; /* short name, full name */ @@ -197,6 +198,8 @@ static const struct rigol_ds_series supported_series[] = { {1000, 1}, {500, 1000000}, 14, 1400, 14000}, [DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2, {50, 1}, {2, 1000}, 12, 600, 20480}, + [DS1000Z] = {VENDOR(RIGOL), "DS1000Z", PROTOCOL_V4, FORMAT_IEEE488_2, + {50, 1}, {1, 1000}, 12, 1200, 12000000}, }; #define SERIES(x) &supported_series[x] @@ -232,6 +235,15 @@ static const struct rigol_ds_model supported_models[] = { {SERIES(DSO1000), "DSO1014A", {2, 1000000000}, 4, false}, {SERIES(DSO1000), "DSO1022A", {2, 1000000000}, 2, false}, {SERIES(DSO1000), "DSO1024A", {2, 1000000000}, 4, false}, + {SERIES(DS1000Z), "DS1054Z", {5, 1000000000}, 4, false}, + {SERIES(DS1000Z), "DS1074Z", {5, 1000000000}, 4, false}, + {SERIES(DS1000Z), "DS1104Z", {5, 1000000000}, 4, false}, + {SERIES(DS1000Z), "DS1074Z-S", {5, 1000000000}, 4, false}, + {SERIES(DS1000Z), "DS1104Z-S", {5, 1000000000}, 4, false}, + {SERIES(DS1000Z), "MSO1074Z", {5, 1000000000}, 4, true}, + {SERIES(DS1000Z), "MSO1104Z", {5, 1000000000}, 4, true}, + {SERIES(DS1000Z), "MSO1074Z-S", {5, 1000000000}, 4, true}, + {SERIES(DS1000Z), "MSO1104Z-S", {5, 1000000000}, 4, true}, }; SR_PRIV struct sr_dev_driver rigol_ds_driver_info; @@ -923,6 +935,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) struct dev_context *devc; struct sr_channel *ch; struct sr_datafeed_packet packet; + gboolean some_digital; GSList *l; if (sdi->status != SR_ST_ACTIVE) @@ -933,13 +946,14 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) devc->num_frames = 0; + some_digital = FALSE; for (l = sdi->channels; l; l = l->next) { ch = l->data; sr_dbg("handling channel %s", ch->name); if (ch->type == SR_CHANNEL_ANALOG) { if (ch->enabled) - devc->enabled_analog_channels = g_slist_append( - devc->enabled_analog_channels, ch); + devc->enabled_channels = g_slist_append( + devc->enabled_channels, ch); if (ch->enabled != devc->analog_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1, @@ -948,19 +962,29 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) devc->analog_channels[ch->index] = ch->enabled; } } else if (ch->type == SR_CHANNEL_LOGIC) { + /* Only one list entry for DS1000D series. All channels are retrieved + * together when this entry is processed. */ + if (ch->enabled && ( + devc->model->series->protocol > PROTOCOL_V2 || + !some_digital)) + devc->enabled_channels = g_slist_append( + devc->enabled_channels, ch); if (ch->enabled) { - devc->enabled_digital_channels = g_slist_append( - devc->enabled_digital_channels, ch); + some_digital = TRUE; /* Turn on LA module if currently off. */ if (!devc->la_enabled) { - if (rigol_ds_config_set(sdi, ":LA:DISP ON") != SR_OK) + if (rigol_ds_config_set(sdi, + devc->model->series->protocol >= PROTOCOL_V4 ? + ":LA:STAT ON" : ":LA:DISP ON") != 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 (rigol_ds_config_set(sdi, ":DIG%d:TURN %s", ch->index, + if (rigol_ds_config_set(sdi, + devc->model->series->protocol >= PROTOCOL_V4 ? + ":LA:DIG%d:DISP %s" : ":DIG%d:TURN %s", ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->digital_channels[ch->index] = ch->enabled; @@ -968,12 +992,14 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) } } - if (!devc->enabled_analog_channels && !devc->enabled_digital_channels) + if (!devc->enabled_channels) return SR_ERR; /* Turn off LA module if on and no digital channels selected. */ - if (devc->la_enabled && !devc->enabled_digital_channels) - if (rigol_ds_config_set(sdi, ":LA:DISP OFF") != SR_OK) + if (devc->la_enabled && !some_digital) + if (rigol_ds_config_set(sdi, + devc->model->series->protocol >= PROTOCOL_V4 ? + ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK) return SR_ERR; /* Set memory mode. */ @@ -1016,10 +1042,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) /* Send header packet to the session bus. */ std_session_send_df_header(cb_data, LOG_PREFIX); - if (devc->enabled_analog_channels) - devc->channel_entry = devc->enabled_analog_channels; - else - devc->channel_entry = devc->enabled_digital_channels; + devc->channel_entry = devc->enabled_channels; if (rigol_ds_capture_start(sdi) != SR_OK) return SR_ERR; @@ -1050,10 +1073,8 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) packet.type = SR_DF_END; sr_session_send(sdi, &packet); - g_slist_free(devc->enabled_analog_channels); - g_slist_free(devc->enabled_digital_channels); - devc->enabled_analog_channels = NULL; - devc->enabled_digital_channels = NULL; + g_slist_free(devc->enabled_channels); + devc->enabled_channels = NULL; scpi = sdi->conn; sr_scpi_source_remove(sdi->session, scpi); diff --git a/src/hardware/rigol-ds/protocol.c b/src/hardware/rigol-ds/protocol.c index 3197d191..8a144f1b 100644 --- a/src/hardware/rigol-ds/protocol.c +++ b/src/hardware/rigol-ds/protocol.c @@ -215,7 +215,7 @@ static int rigol_ds_check_stop(const struct sr_dev_inst *sdi) ch = devc->channel_entry->data; - if (devc->model->series->protocol <= PROTOCOL_V2) + if (devc->model->series->protocol != PROTOCOL_V3) return SR_OK; if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", @@ -261,7 +261,7 @@ static int rigol_ds_block_wait(const struct sr_dev_inst *sdi) if (!(devc = sdi->priv)) return SR_ERR; - if (devc->model->series->protocol >= PROTOCOL_V3) { + if (devc->model->series->protocol == PROTOCOL_V3) { start = time(NULL); @@ -322,6 +322,7 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi) { struct dev_context *devc; gchar *trig_mode; + unsigned int num_channels, i, j; if (!(devc = sdi->priv)) return SR_ERR; @@ -353,15 +354,44 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi) } break; case PROTOCOL_V3: + case PROTOCOL_V4: if (rigol_ds_config_set(sdi, ":WAV:FORM BYTE") != SR_OK) return SR_ERR; if (devc->data_source == DATA_SOURCE_LIVE) { if (rigol_ds_config_set(sdi, ":WAV:MODE NORM") != SR_OK) return SR_ERR; + devc->analog_frame_size = devc->model->series->live_samples; + devc->digital_frame_size = devc->model->series->live_samples; rigol_ds_set_wait_event(devc, WAIT_TRIGGER); } else { - if (rigol_ds_config_set(sdi, ":WAV:MODE RAW") != SR_OK) - return SR_ERR; + if (devc->model->series->protocol == PROTOCOL_V3) { + if (rigol_ds_config_set(sdi, ":WAV:MODE RAW") != SR_OK) + return SR_ERR; + } else if (devc->model->series->protocol == PROTOCOL_V4) { + num_channels = 0; + + /* Channels 3 and 4 are multiplexed with D0-7 and D8-15 */ + for (i = 0; i < devc->model->analog_channels; i++) { + if (devc->analog_channels[i]) { + num_channels++; + } else if (i >= 2 && devc->model->has_digital) { + for (j = 0; j < 8; j++) { + if (devc->digital_channels[8 * (i - 2) + j]) { + num_channels++; + break; + } + } + } + } + + devc->analog_frame_size = devc->digital_frame_size = + num_channels == 1 ? + devc->model->series->buffer_samples : + num_channels == 2 ? + devc->model->series->buffer_samples / 2 : + devc->model->series->buffer_samples / 4; + } + if (rigol_ds_config_set(sdi, ":SING") != SR_OK) return SR_ERR; rigol_ds_set_wait_event(devc, WAIT_STOP); @@ -385,7 +415,10 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) sr_dbg("Starting reading data from channel %d", ch->index + 1); - if (devc->model->series->protocol <= PROTOCOL_V2) { + switch (devc->model->series->protocol) + { + case PROTOCOL_V1: + case PROTOCOL_V2: if (ch->type == SR_CHANNEL_LOGIC) { if (sr_scpi_send(sdi->conn, ":WAV:DATA? DIG") != SR_OK) return SR_ERR; @@ -395,7 +428,8 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) return SR_ERR; } rigol_ds_set_wait_event(devc, WAIT_NONE); - } else { + break; + case PROTOCOL_V3: if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", ch->index + 1) != SR_OK) return SR_ERR; @@ -405,6 +439,31 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) if (rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK) return SR_ERR; } + break; + case PROTOCOL_V4: + if (ch->type == SR_CHANNEL_ANALOG) { + if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", + ch->index + 1) != SR_OK) + return SR_ERR; + } else { + if (rigol_ds_config_set(sdi, ":WAV:SOUR D%d", + ch->index) != SR_OK) + return SR_ERR; + } + + if (rigol_ds_config_set(sdi, + devc->data_source == DATA_SOURCE_LIVE ? + ":WAV:MODE NORM" :":WAV:MODE RAW") != SR_OK) + return SR_ERR; + break; + } + + if (devc->model->series->protocol >= PROTOCOL_V3 && + ch->type == SR_CHANNEL_ANALOG) { + /* Vertical reference. */ + if (sr_scpi_get_int(sdi->conn, ":WAV:YREF?", + &devc->vert_reference[ch->index]) != SR_OK) + return SR_ERR; } rigol_ds_set_wait_event(devc, WAIT_BLOCK); @@ -529,6 +588,16 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) devc->analog_frame_size : devc->digital_frame_size; if (devc->num_block_bytes == 0) { + if (devc->model->series->protocol >= PROTOCOL_V4) { + if (sr_scpi_send(sdi->conn, ":WAV:START %d", + devc->num_channel_bytes + 1) != SR_OK) + return TRUE; + if (sr_scpi_send(sdi->conn, ":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 (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK) return TRUE; @@ -609,7 +678,10 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) g_slist_free(analog.channels); } else { logic.length = len; - logic.unitsize = 2; + // TODO: For the MSO1000Z series, we need a way to express that + // this data is in fact just for a single channel, with the valid + // data for that channel in the LSB of each byte. + logic.unitsize = devc->model->series->protocol == PROTOCOL_V4 ? 1 : 2; logic.data = devc->buffer; packet.type = SR_DF_LOGIC; packet.payload = &logic; @@ -648,7 +720,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) return TRUE; /* End of data for this channel. */ - if (devc->model->series->protocol >= PROTOCOL_V3) { + if (devc->model->series->protocol == PROTOCOL_V3) { /* Signal end of data download to scope */ if (devc->data_source != DATA_SOURCE_LIVE) /* @@ -659,40 +731,27 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) rigol_ds_config_set(sdi, ":WAV:END"); } - if (ch->type == SR_CHANNEL_ANALOG - && devc->channel_entry->next != NULL) { - /* We got the frame for this analog channel, but - * there's another analog channel. */ + if (devc->channel_entry->next) { + /* We got the frame for this channel, now get the next channel. */ devc->channel_entry = devc->channel_entry->next; rigol_ds_channel_start(sdi); } else { - /* Done with all analog channels in this frame. */ - if (devc->enabled_digital_channels - && devc->channel_entry != devc->enabled_digital_channels) { - /* Now we need to get the digital data. */ - devc->channel_entry = devc->enabled_digital_channels; - rigol_ds_channel_start(sdi); - } else { - /* Done with this frame. */ - packet.type = SR_DF_FRAME_END; - sr_session_send(cb_data, &packet); + /* Done with this frame. */ + packet.type = SR_DF_FRAME_END; + sr_session_send(cb_data, &packet); - if (++devc->num_frames == devc->limit_frames) { - /* Last frame, stop capture. */ - sdi->driver->dev_acquisition_stop(sdi, cb_data); - } else { - /* Get the next frame, starting with the first analog channel. */ - if (devc->enabled_analog_channels) - devc->channel_entry = devc->enabled_analog_channels; - else - devc->channel_entry = devc->enabled_digital_channels; + if (++devc->num_frames == devc->limit_frames) { + /* Last frame, stop capture. */ + sdi->driver->dev_acquisition_stop(sdi, cb_data); + } else { + /* Get the next frame, starting with the first channel. */ + devc->channel_entry = devc->enabled_channels; - rigol_ds_capture_start(sdi); + rigol_ds_capture_start(sdi); - /* Start of next frame. */ - packet.type = SR_DF_FRAME_BEGIN; - sr_session_send(cb_data, &packet); - } + /* Start of next frame. */ + packet.type = SR_DF_FRAME_BEGIN; + sr_session_send(cb_data, &packet); } } } @@ -723,13 +782,17 @@ 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, ":LA:DISP?", + if (sr_scpi_get_bool(sdi->conn, + devc->model->series->protocol >= PROTOCOL_V4 ? + ":LA:STAT?" : ":LA:DISP?", &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++) { - cmd = g_strdup_printf(":DIG%d:TURN?", i); + cmd = g_strdup_printf( + devc->model->series->protocol >= PROTOCOL_V4 ? + ":LA:DIG%d:DISP?" : ":DIG%d:TURN?", i); res = sr_scpi_get_bool(sdi->conn, cmd, &devc->digital_channels[i]); g_free(cmd); if (res != SR_OK) @@ -755,18 +818,6 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi) for (i = 0; i < devc->model->analog_channels; i++) sr_dbg("CH%d %g", i + 1, devc->vdiv[i]); - sr_dbg("Current vertical reference:"); - if (devc->model->series->protocol >= PROTOCOL_V3) { - /* Vertical reference - not certain if this is the place to read it. */ - for (i = 0; i < devc->model->analog_channels; i++) { - if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", i + 1) != SR_OK) - return SR_ERR; - if (sr_scpi_get_int(sdi->conn, ":WAV:YREF?", &devc->vert_reference[i]) != SR_OK) - return SR_ERR; - sr_dbg("CH%d %d", i + 1, devc->vert_reference[i]); - } - } - /* Vertical offset. */ for (i = 0; i < devc->model->analog_channels; i++) { cmd = g_strdup_printf(":CHAN%d:OFFS?", i + 1); diff --git a/src/hardware/rigol-ds/protocol.h b/src/hardware/rigol-ds/protocol.h index 7bdf683d..631c81db 100644 --- a/src/hardware/rigol-ds/protocol.h +++ b/src/hardware/rigol-ds/protocol.h @@ -31,6 +31,9 @@ /* Size of acquisition buffers */ #define ACQ_BUFFER_SIZE 32768 +/* Maximum number of samples to retrieve at once. */ +#define ACQ_BLOCK_SIZE 30000 + #define MAX_ANALOG_CHANNELS 4 #define MAX_DIGITAL_CHANNELS 16 @@ -38,6 +41,7 @@ enum protocol_version { PROTOCOL_V1, /* VS5000 */ PROTOCOL_V2, /* DS1000 */ PROTOCOL_V3, /* DS2000, DSO1000 */ + PROTOCOL_V4, /* DS1000Z */ }; enum data_format { @@ -102,8 +106,7 @@ struct dev_context { struct sr_channel_group *digital_group; /* Acquisition settings */ - GSList *enabled_analog_channels; - GSList *enabled_digital_channels; + GSList *enabled_channels; uint64_t limit_frames; void *cb_data; enum data_source data_source; -- 2.30.2