]> sigrok.org Git - libsigrok.git/commitdiff
rigol-ds: Add DS1000Z series support.
authorMartin Ling <redacted>
Thu, 19 Mar 2015 16:15:52 +0000 (16:15 +0000)
committerUwe Hermann <redacted>
Sat, 21 Mar 2015 00:55:55 +0000 (01:55 +0100)
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
src/hardware/rigol-ds/protocol.c
src/hardware/rigol-ds/protocol.h

index a142a2d8c294455c79faba4bce13390978b7ed38..60d63d5913956f50c20277faba9a2254fa6ba395 100644 (file)
@@ -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);
 
index 3197d1916382795b407284d604dca049774433ee..8a144f1bad24d688eab6491e3aa855fdced1a00a 100644 (file)
@@ -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);
index 7bdf683d341568dfc3a8f05285370ce8de075310..631c81dbb8fab4dbe1a02d8467711b05e5c3975a 100644 (file)
@@ -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;