Hi Martin,

Martin Ling writes:
[...]
> Now I am looking and it seems I am missing some commits somewhere. The
> patches you have posted here do not apply against my current
> rigol_ds_unified branch. It fails at the first hunk of the second patch,
> where it appears that the version you're patching against already has an
> extra field in struct rigol_ds_model ("number of horizontal divs") which
> I don't have.
> 
> Am I missing another patch series? I'm not seeing anything from you
> between the last standalone version of the driver, and this latest set
> of patches.

I'm sorry, I seem to have done something wrong with git.

I had the initial "sleeping in trigger wait" stuff in a separate branch,
which I merged into the branch that I created for the sample memory
stuff.

Although I can still see that in gitk, it didn't come out correctly in
the patches generated by git.

I have created a plain old patch between my final version and your
version that I started with, please find that below. I even tested it
actually applies against your version - lessons learned I guess. ;-)

> I can answer one thing from your comments though:
> 
> > The driver has now "gained" dependencies between settings, i.e. we can
> > only set sample memory depth after we know how many channels are
> > active.  The same is true for the DS1xx2 series as far as I
> > understand. No idea if this may cause problems for pulseview later.
> 
> The planned approach, in future at least, is that frontends should
> always re-call sr_config_list() after making configuration changes, so
> that they get the settings which are now "reachable" from the current
> configuration.

Ah, I see.

A nastier case might be the optional features of devices, e.g. the
larger sample memory option. I'm not sure this can even be tested except
actually trying to configure it and failing. Hmm.


I hope the patch below works out,

MGri


diff -urNx .git libsigrok-mling/hardware/rigol-ds/api.c 
libsigrok-tmp/hardware/rigol-ds/api.c
--- libsigrok-mling/hardware/rigol-ds/api.c     2013-11-28 20:51:22.716915060 
+0100
+++ libsigrok-tmp/hardware/rigol-ds/api.c       2013-11-28 20:41:18.000000000 
+0100
@@ -42,6 +42,7 @@
        SR_CONF_COUPLING,
        SR_CONF_NUM_TIMEBASE,
        SR_CONF_NUM_VDIV,
+       SR_CONF_DATA_SOURCE,
 };
 
 static const uint64_t timebases[][2] = {
@@ -138,17 +139,27 @@
        "GND",
 };
 
-/* name, series, min timebase, max timebase, min vdiv, digital channels */
+/* Do not change the order of entries */
+static const char *data_sources[] = {
+       "Live",
+       "Memory",
+       "Segmented",
+};
+
+/* 
+ * name, series, protocol flavor, min timebase, max timebase, min vdiv,
+ * digital channels, number of horizontal divs
+ */
 static const struct rigol_ds_model supported_models[] = {
-       {"DS1052E", 1, {5, 1000000000}, {50, 1}, {2, 1000}, false},
-       {"DS1102E", 1, {2, 1000000000}, {50, 1}, {2, 1000}, false},
-       {"DS1152E", 1, {2, 1000000000}, {50, 1}, {2, 1000}, false},
-       {"DS1052D", 1, {5, 1000000000}, {50, 1}, {2, 1000}, true},
-       {"DS1102D", 1, {2, 1000000000}, {50, 1}, {2, 1000}, true},
-       {"DS1152D", 1, {2, 1000000000}, {50, 1}, {2, 1000}, true},
-       {"DS2072", 2, {5, 1000000000}, {500, 1}, {500, 1000000}, false},
-       {"DS2102", 2, {5, 1000000000}, {500, 1}, {500, 1000000}, false},
-       {"DS2202", 2, {2, 1000000000}, {500, 1}, {500, 1000000}, false},
+       {"DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, 
{2, 1000}, false, 12},
+       {"DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, 
{2, 1000}, false, 12},
+       {"DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, 
{2, 1000}, false, 12},
+       {"DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, 
{2, 1000}, true, 12},
+       {"DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, 
{2, 1000}, true, 12},
+       {"DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, 
{2, 1000}, true, 12},
+       {"DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, 
{500, 1000000}, false, 14},
+       {"DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, 
{500, 1000000}, false, 14},
+       {"DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, 
{500, 1000000}, false, 14},
 };
 
 SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
@@ -160,6 +171,8 @@
 
        devc = priv;
 
+       g_free(devc->data);
+       g_free(devc->buffer);
        g_free(devc->coupling[0]);
        g_free(devc->coupling[1]);
        g_free(devc->trigger_source);
@@ -252,7 +265,7 @@
        }
 
        if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
-               manufacturer, model_name, version))) {
+                                             manufacturer, model_name, 
version))) {
                g_strfreev(tokens);
                return SR_ERR_NA;
        }
@@ -271,7 +284,7 @@
 
        for (i = 0; i < 2; i++) {
                if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
-                               i == 0 ? "CH1" : "CH2")))
+                                          i == 0 ? "CH1" : "CH2")))
                        return SR_ERR_MALLOC;
                sdi->probes = g_slist_append(sdi->probes, probe);
        }
@@ -302,6 +315,13 @@
                }
        }
 
+       if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
+               return SR_ERR_MALLOC;
+       if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
+               return SR_ERR_MALLOC;
+
+       devc->data_source = DATA_SOURCE_LIVE;
+
        sdi->priv = devc;
 
        *devices = g_slist_append(NULL, sdi);
@@ -406,6 +426,14 @@
        case SR_CONF_NUM_VDIV:
                *data = g_variant_new_int32(devc->num_vdivs);
                break;
+       case SR_CONF_DATA_SOURCE:
+               if (devc->data_source == DATA_SOURCE_LIVE)
+                       *data = g_variant_new_string("Live");
+               else if (devc->data_source == DATA_SOURCE_MEMORY)
+                       *data = g_variant_new_string("Memory");
+               else
+                       *data = g_variant_new_string("Segmented");
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -513,6 +541,18 @@
                if (i == ARRAY_SIZE(coupling))
                        ret = SR_ERR_ARG;
                break;
+       case SR_CONF_DATA_SOURCE:
+               tmp_str = g_variant_get_string(data, NULL);
+               if (!strcmp(tmp_str, "Live"))
+                       devc->data_source = DATA_SOURCE_LIVE;
+               else if (!strcmp(tmp_str, "Memory"))
+                       devc->data_source = DATA_SOURCE_MEMORY;
+               else if (devc->model->protocol == PROTOCOL_IEEE488_2
+                        && !strcmp(tmp_str, "Segmented"))
+                       devc->data_source = DATA_SOURCE_SEGMENTED;
+               else
+                       return SR_ERR;
+               break;
        default:
                ret = SR_ERR_NA;
                break;
@@ -576,6 +616,16 @@
                *data = g_variant_new_strv(trigger_sources,
                                devc->model->has_digital ? 
ARRAY_SIZE(trigger_sources) : 4);
                break;
+       case SR_CONF_DATA_SOURCE:
+               if (!devc)
+                       /* Can't know this until we have the exact model. */
+                       return SR_ERR_ARG;
+               /* This needs tweaking by series/model! */
+               if (devc->model->series == RIGOL_DS2000)
+                       *data = g_variant_new_strv(data_sources, 
ARRAY_SIZE(data_sources));
+               else
+                       *data = g_variant_new_strv(data_sources, 
ARRAY_SIZE(data_sources) - 1);
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -597,6 +647,19 @@
        serial = sdi->conn;
        devc = sdi->priv;
 
+       if (devc->data_source == DATA_SOURCE_LIVE) {
+               if (rigol_ds_send(sdi, ":RUN") != SR_OK)
+                       return SR_ERR;
+       } else if (devc->data_source == DATA_SOURCE_MEMORY) {
+               if (devc->model->series != RIGOL_DS2000) {
+                       sr_err("Data source 'Memory' not supported for this 
device");
+                       return SR_ERR;
+               }
+       } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
+               sr_err("Data source 'Segmented' not yet supported");
+               return SR_ERR;
+       }
+
        for (l = sdi->probes; l; l = l->next) {
                probe = l->data;
                sr_dbg("handling probe %s", probe->name);
@@ -632,9 +695,10 @@
        /* Send header packet to the session bus. */
        std_session_send_df_header(cb_data, LOG_PREFIX);
 
-       if (devc->model->series == 1) {
+       if (devc->model->protocol == PROTOCOL_LEGACY) {
                /* Fetch the first frame. */
                if (devc->enabled_analog_probes) {
+                       devc->analog_frame_size = 
DS1000_ANALOG_LIVE_WAVEFORM_SIZE;
                        devc->channel_frame = devc->enabled_analog_probes->data;
                        if (rigol_ds_send(sdi, ":WAV:DATA? CHAN%d",
                                        devc->channel_frame->index + 1) != 
SR_OK)
@@ -648,9 +712,25 @@
                devc->num_frame_bytes = 0;
        } else {
                if (devc->enabled_analog_probes) {
+                       if (devc->data_source == DATA_SOURCE_MEMORY)
+                       {
+                               if (g_slist_length(devc->enabled_analog_probes) 
== 1)
+                                       devc->analog_frame_size = 
DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
+                               else
+                                       devc->analog_frame_size = 
DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
+                               /* Apparently for the DS2000 the memory
+                                * depth can only be set in Running state -
+                                * this matches the behaviour of the UI. */
+                               if (rigol_ds_send(sdi, ":RUN") != SR_OK)
+                                       return SR_ERR;
+                               if (rigol_ds_send(sdi, "ACQ:MDEP %d", 
devc->analog_frame_size) != SR_OK)
+                                       return SR_ERR;
+                               if (rigol_ds_send(sdi, ":STOP") != SR_OK)
+                                       return SR_ERR;
+                       } else
+                               devc->analog_frame_size = 
DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
                        devc->channel_frame = devc->enabled_analog_probes->data;
-                       /* Assume there already was a trigger event - don't 
wait */
-                       if (rigol_ds2xx2_acquisition_start(sdi, FALSE) != SR_OK)
+                       if (rigol_ds_capture_start(sdi) != SR_OK)
                                return SR_ERR;
                }
        }
diff -urNx .git libsigrok-mling/hardware/rigol-ds/protocol.c 
libsigrok-tmp/hardware/rigol-ds/protocol.c
--- libsigrok-mling/hardware/rigol-ds/protocol.c        2013-11-28 
20:51:22.716915060 +0100
+++ libsigrok-tmp/hardware/rigol-ds/protocol.c  2013-11-28 20:41:18.000000000 
+0100
@@ -91,12 +91,21 @@
        return SR_OK;
 }
 
+/* Set the next event to wait for in rigol_ds_receive */
+static void rigol_ds_set_wait_event(struct dev_context *devc, enum wait_events 
event)
+{
+       if (event == WAIT_STOP)
+               devc->wait_status = 2;
+       else
+               devc->wait_status = 1;
+       devc->wait_event = event;
+}
+
 /*
- * Waiting for a trigger event will return a timeout after 2, 3 seconds in
- * order to not block the application.
+ * Waiting for a event will return a timeout after 2 to 3 seconds in order
+ * to not block the application.
  */
-
-static int rigol_ds2xx2_trigger_wait(const struct sr_dev_inst *sdi)
+static int rigol_ds_event_wait(const struct sr_dev_inst *sdi, char status1, 
char status2)
 {
        char buf[20];
        struct dev_context *devc;
@@ -109,14 +118,14 @@
 
        /*
         * Trigger status may return:
-        * "TD"   - triggered
-        * "AUTO" - autotriggered
-        * "RUN"  - running
-        * "WAIT" - waiting for trigger
-        * "STOP" - stopped
+        * "TD" or "T'D" - triggered
+        * "AUTO"        - autotriggered
+        * "RUN"         - running
+        * "WAIT"        - waiting for trigger
+        * "STOP"        - stopped
         */
 
-       if (devc->trigger_wait_status == 1) {
+       if (devc->wait_status == 1) {
                do {
                        if (time(NULL) - start >= 3) {
                                sr_dbg("Timeout waiting for trigger");
@@ -125,11 +134,11 @@
 
                        if (get_cfg(sdi, ":TRIG:STAT?", buf, sizeof(buf)) != 
SR_OK)
                                return SR_ERR;
-               } while (buf[0] == 'T' || buf[0] == 'A');
+               } while (buf[0] == status1 || buf[0] == status2);
 
-               devc->trigger_wait_status = 2;
+               devc->wait_status = 2;
        }
-       if (devc->trigger_wait_status == 2) {
+       if (devc->wait_status == 2) {
                do {
                        if (time(NULL) - start >= 3) {
                                sr_dbg("Timeout waiting for trigger");
@@ -138,63 +147,206 @@
 
                        if (get_cfg(sdi, ":TRIG:STAT?", buf, sizeof(buf)) != 
SR_OK)
                                return SR_ERR;
-               } while (buf[0] != 'T' && buf[0] != 'A');
+               } while (buf[0] != status1 && buf[0] != status2);
 
-               devc->trigger_wait_status = 0;
+               rigol_ds_set_wait_event(devc, WAIT_NONE);
        }
 
        return SR_OK;
 }
 
 /*
- * This needs to wait for a new trigger event to ensure that sample data is
- * not returned twice.
+ * For live capture we need to wait for a new trigger event to ensure that
+ * sample data is not returned twice.
  *
  * Unfortunately this will never really work because for sufficiently fast
- * timebases it just can't catch the status changes.
+ * timebases and trigger rates it just can't catch the status changes.
  *
  * What would be needed is a trigger event register with autoreset like the
  * Agilents have. The Rigols don't seem to have anything like this.
  *
  * The workaround is to only wait for the trigger when the timebase is slow
  * enough. Of course this means that for faster timebases sample data can be
- * returned multiple times.
+ * returned multiple times, this effect is mitigated somewhat by sleeping
+ * for about one sweep time in that case.
  */
-
-SR_PRIV int rigol_ds2xx2_acquisition_start(const struct sr_dev_inst *sdi,
-                                          gboolean wait_for_trigger)
+static int rigol_ds_trigger_wait(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
+       long s;
 
        if (!(devc = sdi->priv))
                return SR_ERR;
 
-       sr_dbg("Starting acquisition on channel %d",
-                  devc->channel_frame->index + 1);
+       /* 
+        * If timebase < 50 msecs/DIV just sleep about one sweep time except
+        * for really fast sweeps.
+        */
+       if (devc->timebase < 0.0499)
+       {
+               if (devc->timebase > 0.99e-6) {
+                       /*
+                        * Timebase * num hor. divs * 85(%) * 1e6(usecs) / 100
+                        * -> 85 percent of sweep time
+                        */
+                       s = (devc->timebase * devc->model->num_horizontal_divs
+                            * 85e6) / 100L;
+                       sr_spew("Sleeping for %ld usecs instead of 
trigger-wait", s);
+                       g_usleep(s);
+               }
+               rigol_ds_set_wait_event(devc, WAIT_NONE);
+               return SR_OK;
+       } else {
+               return rigol_ds_event_wait(sdi, 'T', 'A');
+       }
+}
 
-       if (rigol_ds_send(sdi, ":WAV:FORM BYTE") != SR_OK)
+/* Wait for scope to got to "Stop" in single shot mode */
+static int rigol_ds_stop_wait(const struct sr_dev_inst *sdi)
+{
+       return rigol_ds_event_wait(sdi, 'S', 'S');
+}
+
+/* Check that a single shot acquisition actually succeeded on the DS2000 */
+static int rigol_ds_check_stop(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+       int tmp;
+
+       if (!(devc = sdi->priv))
                return SR_ERR;
+
        if (rigol_ds_send(sdi, ":WAV:SOUR CHAN%d",
-                                 devc->channel_frame->index + 1) != SR_OK)
+                         devc->channel_frame->index + 1) != SR_OK)
+               return SR_ERR;
+       /* Check that the number of samples will be accepted */
+       if (rigol_ds_send(sdi, ":WAV:POIN %d;*OPC", devc->analog_frame_size) != 
SR_OK)
+               return SR_ERR;
+       if (get_cfg_int(sdi, "*ESR?", &tmp) != SR_OK)
                return SR_ERR;
-       if (rigol_ds_send(sdi, ":WAV:MODE NORM") != SR_OK)
+       /*
+        * If we get an "Execution error" the scope went from "Single" to
+        * "Stop" without actually triggering. There is no waveform
+        * displayed and trying to download one will fail - the scope thinks
+        * it has 1400 samples (like display memory) and the driver thinks
+        * it has a different number of samples.
+        *
+        * In that case just try to capture something again. Might still
+        * fail in interesting ways.
+        *
+        * Ain't firmware fun?
+        */
+       if (tmp & 0x10) {
+               sr_warn("Single shot acquisition failed, retrying...");
+               /* Sleep a bit, otherwise the single shot will often fail */
+               g_usleep(500000);
+               rigol_ds_send(sdi, ":SING");
+               rigol_ds_set_wait_event(devc, WAIT_STOP);
                return SR_ERR;
+       }
 
-       devc->num_frame_bytes = 0;
-       devc->num_block_bytes = 0;
+       return SR_OK;
+}
 
-       /* only wait for trigger if timbase 50 msecs/DIV or slower */
-       if (wait_for_trigger && devc->timebase > 0.0499)
-       {
-               devc->trigger_wait_status = 1;
+/* 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];
+       struct dev_context *devc;
+       time_t start;
+       int len;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR;
+
+       start = time(NULL);
+
+       do {
+               if (time(NULL) - start >= 3) {
+                       sr_dbg("Timeout waiting for data block");
+                       return SR_ERR_TIMEOUT;
+               }
+
+               /*
+                * The scope copies data really slowly from sample
+                * memory to its output buffer, so try not to bother
+                * it too much with SCPI requests but don't wait too
+                * long for short sample frame sizes.
+                */
+               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)
+                       return SR_ERR;
+
+               if (parse_int(buf + 5, &len) != SR_OK)
+                       return SR_ERR;
+       } while (buf[0] == 'R' && len < 1000000);
+
+       rigol_ds_set_wait_event(devc, WAIT_NONE);
+
+       return SR_OK;
+}
+
+/* Start capturing a new frameset */
+SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR;
+
+       sr_dbg("Starting data capture for frameset %lu of %lu",
+              devc->num_frames + 1, devc->limit_frames);
+
+       if (rigol_ds_send(sdi, ":WAV:FORM BYTE") != SR_OK)
+               return SR_ERR;
+       if (devc->data_source == DATA_SOURCE_LIVE) {
+               if (rigol_ds_send(sdi, ":WAV:MODE NORM") != SR_OK)
+                       return SR_ERR;
+               rigol_ds_set_wait_event(devc, WAIT_TRIGGER);
        } else {
-               devc->trigger_wait_status = 0;
+               if (rigol_ds_send(sdi, ":WAV:MODE RAW") != SR_OK)
+                       return SR_ERR;
+               if (rigol_ds_send(sdi, ":SING", devc->analog_frame_size) != 
SR_OK)
+                       return SR_ERR;          
+               rigol_ds_set_wait_event(devc, WAIT_STOP);
        }
 
        return SR_OK;
 }
 
-static int rigol_ds2xx2_read_header(struct sr_serial_dev_inst *serial)
+/* Start reading data from the current channel */
+SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR;
+
+       sr_dbg("Starting reading data from channel %d",
+              devc->channel_frame->index + 1);
+
+       if (rigol_ds_send(sdi, ":WAV:SOUR CHAN%d",
+                         devc->channel_frame->index + 1) != SR_OK)
+               return SR_ERR;
+       if (devc->data_source != DATA_SOURCE_LIVE) {
+               if (rigol_ds_send(sdi, ":WAV:RES") != SR_OK)
+                       return SR_ERR;
+               if (rigol_ds_send(sdi, ":WAV:BEG") != SR_OK)
+                       return SR_ERR;
+               rigol_ds_set_wait_event(devc, WAIT_BLOCK);
+       } else
+               rigol_ds_set_wait_event(devc, WAIT_NONE);
+
+       devc->num_frame_bytes = 0;
+       devc->num_block_bytes = 0;
+
+       return SR_OK;
+}
+
+/* Read the header of a data block */
+static int rigol_ds_read_header(struct sr_serial_dev_inst *serial)
 {
        char start[3], length[10];
        int len, tmp;
@@ -241,9 +393,7 @@
        struct sr_datafeed_packet packet;
        struct sr_datafeed_analog analog;
        struct sr_datafeed_logic logic;
-       unsigned char buf[DS2000_ANALOG_WAVEFORM_SIZE];
        double vdiv, offset;
-       float data[DS2000_ANALOG_WAVEFORM_SIZE];
        int len, i, waveform_size, vref;
        struct sr_probe *probe;
 
@@ -258,41 +408,69 @@
        serial = sdi->conn;
 
        if (revents == G_IO_IN) {
-               if (devc->trigger_wait_status > 0) {
-                       if (rigol_ds2xx2_trigger_wait(sdi) != SR_OK)
-                               return TRUE;
-               }
+               if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+                       switch(devc->wait_event) {
+                       case WAIT_NONE:
+                               break;
 
-               if (devc->model->series == 2 && devc->num_block_bytes == 0) {
-                       sr_dbg("New block header expected");
-                       if (rigol_ds_send(sdi, ":WAV:DATA?") != SR_OK)
-                               return TRUE;
-                       len = rigol_ds2xx2_read_header(serial);
-                       if (len == -1)
-                               return TRUE;
-                       /* At slow timebases the scope sometimes returns
-                        * "short" data blocks, with apparently no way to
-                        * get the rest of the data. Discard these, the
-                        * complete data block will appear eventually.
-                        */
-                       if (len < DS2000_ANALOG_WAVEFORM_SIZE) {
-                               sr_dbg("Discarding short data block");
-                               serial_read(serial, buf, len + 1);
+                       case WAIT_TRIGGER:
+                               if (rigol_ds_trigger_wait(sdi) != SR_OK)
+                                       return TRUE;
+                               if (rigol_ds_channel_start(sdi) != SR_OK)
+                                       return TRUE;
+                               break;
+
+                       case WAIT_BLOCK:
+                               if (rigol_ds_block_wait(sdi) != SR_OK)
+                                       return TRUE;
+                               break;
+
+                       case WAIT_STOP:
+                               if (rigol_ds_stop_wait(sdi) != SR_OK)
+                                       return TRUE;
+                               if (rigol_ds_check_stop(sdi) != SR_OK)
+                                       return TRUE;
+                               if (rigol_ds_channel_start(sdi) != SR_OK)
+                                       return TRUE;
                                return TRUE;
+
+                       default:
+                               sr_err("BUG: Unknown event target encountered");
+                       }
+               
+                       if (devc->num_block_bytes == 0) {
+                               sr_dbg("New block header expected");
+                               if (rigol_ds_send(sdi, ":WAV:DATA?") != SR_OK)
+                                       return TRUE;
+                               len = rigol_ds_read_header(serial);
+                               if (len == -1)
+                                       return TRUE;
+                               /* At slow timebases in live capture the DS2072
+                                * sometimes returns "short" data blocks, with
+                                * apparently no way to get the rest of the 
data.
+                                * Discard these, the complete data block will
+                                * appear eventually.
+                                */
+                               if (devc->data_source == DATA_SOURCE_LIVE
+                                   && (unsigned)len < devc->num_frame_bytes) {
+                                       sr_dbg("Discarding short data block");
+                                       serial_read(serial, devc->buffer, len + 
1);
+                                       return TRUE;
+                               }
+                               devc->num_block_bytes = len;
+                               devc->num_block_read = 0;
                        }
-                       devc->num_block_bytes = len;
-                       devc->num_block_read = 0;
                }
 
                probe = devc->channel_frame;
-               if (devc->model->series == 2) {
+               if (devc->model->protocol == PROTOCOL_IEEE488_2) {
                        len = devc->num_block_bytes - devc->num_block_read;
-                       len = serial_read(serial, buf,
-                                       len < DS2000_ANALOG_WAVEFORM_SIZE ? len 
: DS2000_ANALOG_WAVEFORM_SIZE);
+                       len = serial_read(serial, devc->buffer,
+                                       len < ACQ_BUFFER_SIZE ? len : 
ACQ_BUFFER_SIZE);
                } else {
                        waveform_size = probe->type == SR_PROBE_ANALOG ?
-                                       DS1000_ANALOG_WAVEFORM_SIZE : 
DIGITAL_WAVEFORM_SIZE;
-                       len = serial_read(serial, buf, waveform_size - 
devc->num_frame_bytes);
+                                       DS1000_ANALOG_LIVE_WAVEFORM_SIZE : 
DIGITAL_WAVEFORM_SIZE;
+                       len = serial_read(serial, devc->buffer, waveform_size - 
devc->num_frame_bytes);
                }
                sr_dbg("Received %d bytes.", len);
                if (len == -1)
@@ -305,20 +483,20 @@
                }
 
                if (probe->type == SR_PROBE_ANALOG) {
-                       if (devc->model->series == 2)
+                       if (devc->model->protocol == PROTOCOL_IEEE488_2)
                                devc->num_block_read += len;
                        vref = devc->vert_reference[probe->index];
                        vdiv = devc->vdiv[probe->index] / 25.6;
                        offset = devc->vert_offset[probe->index];
-                       if (devc->model->series == 2)
+                       if (devc->model->protocol == PROTOCOL_IEEE488_2)
                                for (i = 0; i < len; i++)
-                                       data[i] = ((int)buf[i] - vref) * vdiv - 
offset;
+                                       devc->data[i] = ((int)devc->buffer[i] - 
vref) * vdiv - offset;
                        else
                                for (i = 0; i < len; i++)
-                                       data[i] = (128 - buf[i]) * vdiv - 
offset;
+                                       devc->data[i] = (128 - devc->buffer[i]) 
* vdiv - offset;
                        analog.probes = g_slist_append(NULL, probe);
                        analog.num_samples = len;
-                       analog.data = data;
+                       analog.data = devc->data;
                        analog.mq = SR_MQ_VOLTAGE;
                        analog.unit = SR_UNIT_VOLT;
                        analog.mqflags = 0;
@@ -327,23 +505,34 @@
                        sr_session_send(cb_data, &packet);
                        g_slist_free(analog.probes);
 
-                       if (devc->model->series == 2) {
+                       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+                               if (devc->num_block_read == 
devc->num_block_bytes) {
+                                       sr_dbg("Block has been completed");
+                                       /* Discard the terminating linefeed and 
prepare for
+                                          possible next block */
+                                       serial_read(serial, devc->buffer, 1);
+                                       devc->num_block_bytes = 0;
+                                       if (devc->data_source != 
DATA_SOURCE_LIVE)
+                                               rigol_ds_set_wait_event(devc, 
WAIT_BLOCK);
+                               } else
+                                       sr_dbg("%d of %d block bytes read", 
devc->num_block_read, devc->num_block_bytes);
+
                                devc->num_frame_bytes += len;
 
-                               if (devc->num_frame_bytes < 
DS2000_ANALOG_WAVEFORM_SIZE)
+                               if (devc->num_frame_bytes < 
devc->analog_frame_size)
                                        /* Don't have the whole frame yet. */
                                        return TRUE;
 
                                sr_dbg("Frame completed, %d samples", 
devc->num_frame_bytes);
                        } else {
-                               if (len != DS1000_ANALOG_WAVEFORM_SIZE)
+                               if (len != DS1000_ANALOG_LIVE_WAVEFORM_SIZE)
                                        /* Don't have the whole frame yet. */
                                        return TRUE;
                        }
                } else {
                        logic.length = len - 10;
                        logic.unitsize = 2;
-                       logic.data = buf + 10;
+                       logic.data = devc->buffer + 10;
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
                        sr_session_send(cb_data, &packet);
@@ -356,8 +545,18 @@
                /* End of the frame. */
                packet.type = SR_DF_FRAME_END;
                sr_session_send(sdi, &packet);
-               if (devc->model->series == 1)
+               if (devc->model->protocol == PROTOCOL_LEGACY)
                        devc->num_frame_bytes = 0;
+               else {
+                       /* Signal end of data download to scope */
+                       if (devc->data_source != DATA_SOURCE_LIVE)
+                               /*
+                                * This causes a query error, without it 
switching
+                                * to the next channel causes an error. Fun with
+                                * firmware...
+                                */
+                               rigol_ds_send(sdi, ":WAV:END");
+               }
 
                if (devc->enabled_analog_probes
                                && devc->channel_frame == 
devc->enabled_analog_probes->data
@@ -365,9 +564,8 @@
                        /* We got the frame for the first analog channel, but
                         * there's a second analog channel. */
                        devc->channel_frame = 
devc->enabled_analog_probes->next->data;
-                       if (devc->model->series == 2) {
-                               /* Do not wait for trigger to try and keep 
channel data related. */
-                               rigol_ds2xx2_acquisition_start(sdi, FALSE);
+                       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
+                               rigol_ds_channel_start(sdi);
                        } else {
                                rigol_ds_send(sdi, ":WAV:DATA? CHAN%c",
                                                devc->channel_frame->name[2]);
@@ -384,13 +582,10 @@
                                sdi->driver->dev_acquisition_stop(sdi, cb_data);
                        } else {
                                /* Get the next frame, starting with the first 
analog channel. */
-                               if (devc->model->series == 2) {
+                               if (devc->model->protocol == 
PROTOCOL_IEEE488_2) {
                                        if (devc->enabled_analog_probes) {
                                                devc->channel_frame = 
devc->enabled_analog_probes->data;
-                                               /* Must wait for trigger 
because at
-                                                * slow timebases the scope will
-                                                * return old data otherwise. */
-                                               
rigol_ds2xx2_acquisition_start(sdi, TRUE);
+                                               rigol_ds_capture_start(sdi);
                                        }
                                } else {
                                        if (devc->enabled_analog_probes) {
@@ -445,7 +640,7 @@
                return SR_ERR;
        reply[len] = '\0';
 
-       if (devc->model->series == 2) {
+       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
                /* get rid of trailing linefeed */
                if (len >= 1 && reply[len-1] == '\n')
                        reply[len-1] = '\0';
@@ -543,7 +738,7 @@
                return SR_ERR;
        sr_dbg("Current vertical gain CH1 %g CH2 %g", devc->vdiv[0], 
devc->vdiv[1]);
 
-       if (devc->model->series == 2) {
+       if (devc->model->protocol == PROTOCOL_IEEE488_2) {
                /* Vertical reference - not certain if this is the place to 
read it. */
                if (rigol_ds_send(sdi, ":WAV:SOUR CHAN1") != SR_OK)
                        return SR_ERR;
diff -urNx .git libsigrok-mling/hardware/rigol-ds/protocol.h 
libsigrok-tmp/hardware/rigol-ds/protocol.h
--- libsigrok-mling/hardware/rigol-ds/protocol.h        2013-11-28 
20:51:22.716915060 +0100
+++ libsigrok-tmp/hardware/rigol-ds/protocol.h  2013-11-28 20:41:18.000000000 
+0100
@@ -35,17 +35,52 @@
 #define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
 #define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
 
-#define DS1000_ANALOG_WAVEFORM_SIZE 600
-#define DS2000_ANALOG_WAVEFORM_SIZE 1400
+#define DS1000_ANALOG_LIVE_WAVEFORM_SIZE 600
+#define DS2000_ANALOG_LIVE_WAVEFORM_SIZE 1400
+/* Needs to be made configurable later */
+#define DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C 14000
+#define DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C 7000
 #define DIGITAL_WAVEFORM_SIZE 1210
+/* Size of acquisition buffers */
+#define ACQ_BUFFER_SIZE 32768
+
+enum rigol_ds_series {
+       RIGOL_DS1000,
+       RIGOL_DS1000Z,
+       RIGOL_DS2000,
+       RIGOL_DS4000,
+       RIGOL_DS6000,
+};
+
+enum rigol_protocol_flavor {
+       /* Used by DS1000 series */
+       PROTOCOL_LEGACY,
+       /* Used by DS2000, DS4000, DS6000, ... series */
+       PROTOCOL_IEEE488_2,
+};
+
+enum data_source {
+       DATA_SOURCE_LIVE,
+       DATA_SOURCE_MEMORY,
+       DATA_SOURCE_SEGMENTED,
+};
 
 struct rigol_ds_model {
        char *name;
-       unsigned int series;
+       enum rigol_ds_series series;
+       enum rigol_protocol_flavor protocol;
        uint64_t min_timebase[2];
        uint64_t max_timebase[2];
        uint64_t min_vdiv[2];
        bool has_digital;
+       int num_horizontal_divs;
+};
+
+enum wait_events {
+       WAIT_NONE,    /* Don't wait */
+       WAIT_TRIGGER, /* Wait for trigger (only live capture) */
+       WAIT_BLOCK,   /* Wait for block data (only when reading sample mem) */
+       WAIT_STOP,    /* Wait for scope stopping (only single shots) */
 };
 
 /** Private, per-device-instance driver context. */
@@ -64,6 +99,8 @@
        GSList *enabled_digital_probes;
        uint64_t limit_frames;
        void *cb_data;
+       enum data_source data_source;
+       uint64_t analog_frame_size;
 
        /* Device settings */
        gboolean analog_channels[2];
@@ -86,11 +123,16 @@
        uint64_t num_block_bytes;
        /* Number of data block bytes already read */
        uint64_t num_block_read;
-       /* Trigger waiting status, 0 - don't wait */
-       int trigger_wait_status;
+       /* What to wait for in *_receive */
+       enum wait_events wait_event;
+       /* Trigger/block copying/stop waiting status */
+       int wait_status;
+       /* Acq buffers used for reading from the scope and sending data to app 
*/
+       unsigned char *buffer;
+       float *data;
 };
 
-SR_PRIV int rigol_ds2xx2_acquisition_start(const struct sr_dev_inst *sdi, 
gboolean wait_for_trigger);
+SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi);
 SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data);
 SR_PRIV int rigol_ds_send(const struct sr_dev_inst *sdi, const char *format, 
...);
 SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi);

------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk
_______________________________________________
sigrok-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to