]> sigrok.org Git - libsigrok.git/blobdiff - hardware/rigol-ds/protocol.c
rigol-ds: On DS1000 with firmware < 0.2.4, use legacy protocol.
[libsigrok.git] / hardware / rigol-ds / protocol.c
index 1d2302f60c4bb949a99b7d9e0ea6b27e855fc7db..446534b9966d7bcf948cbc54e7c6a1e3ebc4c443 100644 (file)
@@ -64,9 +64,6 @@
  * Each data block has a trailing linefeed too.
  */
 
-static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply, size_t maxlen);
-static int get_cfg_int(const struct sr_dev_inst *sdi, char *cmd, int *i);
-
 static int parse_int(const char *str, int *ret)
 {
        char *e;
@@ -107,7 +104,7 @@ static void rigol_ds_set_wait_event(struct dev_context *devc, enum wait_events e
  */
 static int rigol_ds_event_wait(const struct sr_dev_inst *sdi, char status1, char status2)
 {
-       char buf[20];
+       char *buf;
        struct dev_context *devc;
        time_t start;
 
@@ -132,7 +129,7 @@ static int rigol_ds_event_wait(const struct sr_dev_inst *sdi, char status1, char
                                return SR_ERR_TIMEOUT;
                        }
 
-                       if (get_cfg(sdi, ":TRIG:STAT?", buf, sizeof(buf)) != SR_OK)
+                       if (sr_scpi_get_string(sdi->conn, ":TRIG:STAT?", &buf) != SR_OK)
                                return SR_ERR;
                } while (buf[0] == status1 || buf[0] == status2);
 
@@ -145,7 +142,7 @@ static int rigol_ds_event_wait(const struct sr_dev_inst *sdi, char status1, char
                                return SR_ERR_TIMEOUT;
                        }
 
-                       if (get_cfg(sdi, ":TRIG:STAT?", buf, sizeof(buf)) != SR_OK)
+                       if (sr_scpi_get_string(sdi->conn, ":TRIG:STAT?", &buf) != SR_OK)
                                return SR_ERR;
                } while (buf[0] != status1 && buf[0] != status2);
 
@@ -224,7 +221,7 @@ static int rigol_ds_check_stop(const struct sr_dev_inst *sdi)
        /* Check that the number of samples will be accepted */
        if (sr_scpi_send(sdi->conn, ":WAV:POIN %d;*OPC", devc->analog_frame_size) != SR_OK)
                return SR_ERR;
-       if (get_cfg_int(sdi, "*ESR?", &tmp) != SR_OK)
+       if (sr_scpi_get_int(sdi->conn, "*ESR?", &tmp) != SR_OK)
                return SR_ERR;
        /*
         * If we get an "Execution error" the scope went from "Single" to
@@ -253,7 +250,7 @@ static int rigol_ds_check_stop(const struct sr_dev_inst *sdi)
 /* Wait for enough data becoming available in scope output buffer */
 static int rigol_ds_block_wait(const struct sr_dev_inst *sdi)
 {
-       char buf[30];
+       char *buf;
        struct dev_context *devc;
        time_t start;
        int len;
@@ -278,7 +275,7 @@ static int rigol_ds_block_wait(const struct sr_dev_inst *sdi)
                g_usleep(devc->analog_frame_size < 15000 ? 100000 : 1000000);
 
                /* "READ,nnnn" (still working) or "IDLE,nnnn" (finished) */
-               if (get_cfg(sdi, ":WAV:STAT?", buf, sizeof(buf)) != SR_OK)
+               if (sr_scpi_get_string(sdi->conn, ":WAV:STAT?", &buf) != SR_OK)
                        return SR_ERR;
 
                if (parse_int(buf + 5, &len) != SR_OK)
@@ -331,7 +328,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
 
        sr_dbg("Starting reading data from channel %d", probe->index + 1);
 
-       if (devc->model->protocol == PROTOCOL_LEGACY) {
+       if (devc->model->series < RIGOL_DS1000Z) {
                if (probe->type == SR_PROBE_LOGIC) {
                        if (sr_scpi_send(sdi->conn, ":WAV:DATA? DIG") != SR_OK)
                                return SR_ERR;
@@ -354,7 +351,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
                        rigol_ds_set_wait_event(devc, WAIT_NONE);
        }
 
-       devc->num_frame_samples = 0;
+       devc->num_channel_bytes = 0;
        devc->num_block_bytes = 0;
 
        return SR_OK;
@@ -407,6 +404,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
        double vdiv, offset;
        int len, i, vref;
        struct sr_probe *probe;
+       gsize expected_data_bytes;
 
        (void)fd;
 
@@ -419,8 +417,8 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
        scpi = sdi->conn;
 
        if (revents == G_IO_IN || revents == 0) {
-               if (devc->model->protocol == PROTOCOL_IEEE488_2) {
-                       switch (devc->wait_event) {
+               if (devc->model->series >= RIGOL_DS1000Z) {
+                       switch(devc->wait_event) {
                        case WAIT_NONE:
                                break;
                        case WAIT_TRIGGER:
@@ -447,17 +445,22 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                }
 
                probe = devc->channel_entry->data;
-               
+
+               expected_data_bytes = probe->type == SR_PROBE_ANALOG ?
+                               devc->analog_frame_size : devc->digital_frame_size;
+
                if (devc->num_block_bytes == 0 &&
-                   devc->model->protocol == PROTOCOL_IEEE488_2) {
+                   devc->model->series >= RIGOL_DS1000Z) {
                                if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK)
                                        return TRUE;
                }
 
                if (devc->num_block_bytes == 0) {
+
                        if (sr_scpi_read_begin(scpi) != SR_OK)
                                return TRUE;
-                       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+
+                       if (devc->protocol == PROTOCOL_IEEE488_2) {
                                sr_dbg("New block header expected");
                                len = rigol_ds_read_header(scpi);
                                if (len == -1)
@@ -469,18 +472,14 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                                 * appear eventually.
                                 */
                                if (devc->data_source == DATA_SOURCE_LIVE
-                                               && (unsigned)len < devc->num_frame_samples) {
+                                               && (unsigned)len < expected_data_bytes) {
                                        sr_dbg("Discarding short data block");
                                        sr_scpi_read_data(scpi, (char *)devc->buffer, len + 1);
                                        return TRUE;
                                }
                                devc->num_block_bytes = len;
                        } else {
-                               devc->num_block_bytes = probe->type == SR_PROBE_ANALOG ?
-                                       (devc->model->series == RIGOL_VS5000 ?
-                                               VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
-                                               DS1000_ANALOG_LIVE_WAVEFORM_SIZE) :
-                                       DIGITAL_WAVEFORM_SIZE;
+                               devc->num_block_bytes = expected_data_bytes;
                        }
                        devc->num_block_read = 0;
                }
@@ -495,17 +494,11 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 
                devc->num_block_read += len;
 
-               if (devc->num_frame_samples == 0) {
-                       /* Start of a new frame. */
-                       packet.type = SR_DF_FRAME_BEGIN;
-                       sr_session_send(sdi, &packet);
-               }
-
                if (probe->type == SR_PROBE_ANALOG) {
                        vref = devc->vert_reference[probe->index];
                        vdiv = devc->vdiv[probe->index] / 25.6;
                        offset = devc->vert_offset[probe->index];
-                       if (devc->model->protocol == PROTOCOL_IEEE488_2)
+                       if (devc->model->series >= RIGOL_DS1000Z)
                                for (i = 0; i < len; i++)
                                        devc->data[i] = ((int)devc->buffer[i] - vref) * vdiv - offset;
                        else
@@ -522,9 +515,9 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                        sr_session_send(cb_data, &packet);
                        g_slist_free(analog.probes);
                } else {
-                       logic.length = len - 10;
+                       logic.length = len;
                        logic.unitsize = 2;
-                       logic.data = devc->buffer + 10;
+                       logic.data = devc->buffer;
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
                        sr_session_send(cb_data, &packet);
@@ -532,31 +525,34 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 
                if (devc->num_block_read == devc->num_block_bytes) {
                        sr_dbg("Block has been completed");
-                       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
-                               /* Discard the terminating linefeed and prepare for
-                                  possible next block */
+                       if (devc->model->series >= RIGOL_DS1000Z) {
+                               /* Discard the terminating linefeed */
                                sr_scpi_read_data(scpi, (char *)devc->buffer, 1);
+                       }
+                       if (devc->protocol == PROTOCOL_IEEE488_2) {
+                               /* Prepare for possible next block */
                                devc->num_block_bytes = 0;
                                if (devc->data_source != DATA_SOURCE_LIVE)
                                        rigol_ds_set_wait_event(devc, WAIT_BLOCK);
                        }
+                       if (!sr_scpi_read_complete(scpi)) {
+                               sr_err("Read should have been completed");
+                               sdi->driver->dev_acquisition_stop(sdi, cb_data);
+                               return TRUE;
+                       }
                        devc->num_block_read = 0;
                } else {
                        sr_dbg("%d of %d block bytes read", devc->num_block_read, devc->num_block_bytes);
                }
 
-               devc->num_frame_samples += len;
+               devc->num_channel_bytes += len;
 
-               if (devc->num_frame_samples < (probe->type == SR_PROBE_ANALOG ?
-                                       devc->analog_frame_size : DIGITAL_WAVEFORM_SIZE))
-                       /* Don't have the whole frame yet. */
+               if (devc->num_channel_bytes < expected_data_bytes)
+                       /* Don't have the full data for this channel yet, re-run. */
                        return TRUE;
 
-               /* End of the frame. */
-               sr_dbg("Frame completed, %d samples", devc->num_frame_samples);
-               packet.type = SR_DF_FRAME_END;
-               sr_session_send(sdi, &packet);
-               if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+               /* End of data for this channel. */
+               if (devc->model->series >= RIGOL_DS1000Z) {
                        /* Signal end of data download to scope */
                        if (devc->data_source != DATA_SOURCE_LIVE)
                                /*
@@ -580,19 +576,30 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                                /* Now we need to get the digital data. */
                                devc->channel_entry = devc->enabled_digital_probes;
                                rigol_ds_channel_start(sdi);
-                       } else if (++devc->num_frames == devc->limit_frames) {
-                               sdi->driver->dev_acquisition_stop(sdi, cb_data);
                        } else {
-                               /* Get the next frame, starting with the first analog channel. */
-                               if (devc->enabled_analog_probes)
-                                       devc->channel_entry = devc->enabled_analog_probes;
-                               else
-                                       devc->channel_entry = devc->enabled_digital_probes;
-
-                               if (devc->model->protocol == PROTOCOL_LEGACY)
-                                       rigol_ds_channel_start(sdi);
-                               else
-                                       rigol_ds_capture_start(sdi);
+                               /* 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_probes)
+                                               devc->channel_entry = devc->enabled_analog_probes;
+                                       else
+                                               devc->channel_entry = devc->enabled_digital_probes;
+
+                                       if (devc->model->series < RIGOL_DS1000Z)
+                                               rigol_ds_channel_start(sdi);
+                                       else
+                                               rigol_ds_capture_start(sdi);
+
+                                       /* Start of next frame. */
+                                       packet.type = SR_DF_FRAME_BEGIN;
+                                       sr_session_send(cb_data, &packet);
+                               }
                        }
                }
        }
@@ -600,70 +607,6 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
        return TRUE;
 }
 
-static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply, size_t maxlen)
-{
-       int len;
-       struct dev_context *devc = sdi->priv;
-       struct sr_scpi_dev_inst *scpi = sdi->conn;
-       char *response;
-
-       if (sr_scpi_get_string(scpi, cmd, &response) != SR_OK)
-               return SR_ERR;
-
-       g_strlcpy(reply, response, maxlen);
-       g_free(response);
-       len = strlen(reply);
-
-       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
-               /* get rid of trailing linefeed */
-               if (len >= 1 && reply[len-1] == '\n')
-                       reply[len-1] = '\0';
-       }
-
-       sr_spew("Received '%s'.", reply);
-
-       return SR_OK;
-}
-
-static int get_cfg_int(const struct sr_dev_inst *sdi, char *cmd, int *i)
-{
-       char buf[32];
-
-       if (get_cfg(sdi, cmd, buf, sizeof(buf)) != SR_OK)
-               return SR_ERR;
-
-       if (parse_int(buf, i) != SR_OK)
-               return SR_ERR;
-
-       return SR_OK;
-}
-
-static int get_cfg_float(const struct sr_dev_inst *sdi, char *cmd, float *f)
-{
-       char buf[32], *e;
-
-       if (get_cfg(sdi, cmd, buf, sizeof(buf)) != SR_OK)
-               return SR_ERR;
-       *f = strtof(buf, &e);
-       if (e == buf || (fpclassify(*f) & (FP_ZERO | FP_NORMAL)) == 0) {
-               sr_dbg("failed to parse response to '%s': '%s'", cmd, buf);
-               return SR_ERR;
-       }
-
-       return SR_OK;
-}
-
-static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf)
-{
-       if (!(*buf = g_try_malloc0(256)))
-               return SR_ERR_MALLOC;
-
-       if (get_cfg(sdi, cmd, *buf, 256) != SR_OK)
-               return SR_ERR;
-
-       return SR_OK;
-}
-
 SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
@@ -676,7 +619,7 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
        /* Analog channel state. */
        for (i = 0; i < devc->model->analog_channels; i++) {
                cmd = g_strdup_printf(":CHAN%d:DISP?", i + 1);
-               res = get_cfg_string(sdi, cmd, &t_s);
+               res = sr_scpi_get_string(sdi->conn, cmd, &t_s);
                g_free(cmd);
                if (res != SR_OK)
                        return SR_ERR;
@@ -688,14 +631,14 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
 
        /* Digital channel state. */
        if (devc->model->has_digital) {
-               if (get_cfg_string(sdi, ":LA:DISP?", &t_s) != SR_OK)
+               if (sr_scpi_get_string(sdi->conn, ":LA:DISP?", &t_s) != SR_OK)
                        return SR_ERR;
                devc->la_enabled = !strcmp(t_s, "ON") ? TRUE : FALSE;
                sr_dbg("Logic analyzer %s, current digital channel state:",
                                devc->la_enabled ? "enabled" : "disabled");
                for (i = 0; i < 16; i++) {
                        cmd = g_strdup_printf(":DIG%d:TURN?", i);
-                       res = get_cfg_string(sdi, cmd, &t_s);
+                       res = sr_scpi_get_string(sdi->conn, cmd, &t_s);
                        g_free(cmd);
                        if (res != SR_OK)
                                return SR_ERR;
@@ -706,14 +649,14 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
        }
 
        /* Timebase. */
-       if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK)
+       if (sr_scpi_get_float(sdi->conn, ":TIM:SCAL?", &devc->timebase) != SR_OK)
                return SR_ERR;
        sr_dbg("Current timebase %g", devc->timebase);
 
        /* Vertical gain. */
        for (i = 0; i < devc->model->analog_channels; i++) {
                cmd = g_strdup_printf(":CHAN%d:SCAL?", i + 1);
-               res = get_cfg_float(sdi, cmd, &devc->vdiv[i]);
+               res = sr_scpi_get_float(sdi->conn, cmd, &devc->vdiv[i]);
                g_free(cmd);
                if (res != SR_OK)
                        return SR_ERR;
@@ -723,12 +666,12 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
                sr_dbg("CH%d %g", i + 1, devc->vdiv[i]);
 
        sr_dbg("Current vertical reference:");
-       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+       if (devc->model->series >= RIGOL_DS1000Z) {
                /* Vertical reference - not certain if this is the place to read it. */
                for (i = 0; i < devc->model->analog_channels; i++) {
                        if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN%d", i + 1) != SR_OK)
                                return SR_ERR;
-                       if (get_cfg_int(sdi, ":WAV:YREF?", &devc->vert_reference[i]) != SR_OK)
+                       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]);
                }
@@ -737,7 +680,7 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
        /* Vertical offset. */
        for (i = 0; i < devc->model->analog_channels; i++) {
                cmd = g_strdup_printf(":CHAN%d:OFFS?", i + 1);
-               res = get_cfg_float(sdi, cmd, &devc->vert_offset[i]);
+               res = sr_scpi_get_float(sdi->conn, cmd, &devc->vert_offset[i]);
                g_free(cmd);
                if (res != SR_OK)
                        return SR_ERR;
@@ -749,7 +692,7 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
        /* Coupling. */
        for (i = 0; i < devc->model->analog_channels; i++) {
                cmd = g_strdup_printf(":CHAN%d:COUP?", i + 1);
-               res = get_cfg_string(sdi, cmd, &devc->coupling[i]);
+               res = sr_scpi_get_string(sdi->conn, cmd, &devc->coupling[i]);
                g_free(cmd);
                if (res != SR_OK)
                        return SR_ERR;
@@ -759,17 +702,17 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
                sr_dbg("CH%d %s", i + 1, devc->coupling[i]);
 
        /* Trigger source. */
-       if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
+       if (sr_scpi_get_string(sdi->conn, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
                return SR_ERR;
        sr_dbg("Current trigger source %s", devc->trigger_source);
 
        /* Horizontal trigger position. */
-       if (get_cfg_float(sdi, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
+       if (sr_scpi_get_float(sdi->conn, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
                return SR_ERR;
        sr_dbg("Current horizontal trigger position %g", devc->horiz_triggerpos);
 
        /* Trigger slope. */
-       if (get_cfg_string(sdi, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
+       if (sr_scpi_get_string(sdi->conn, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
                return SR_ERR;
        sr_dbg("Current trigger slope %s", devc->trigger_slope);