>From e397791d6ec362436b21ae89c8420c55986351ee Mon Sep 17 00:00:00 2001
From: Frank Tkalcevic <frank@franksworkshop.com.au>
Date: Mon, 9 Jul 2018 21:08:07 +1000
Subject: [PATCH] Modifications to make memory mode work with MSO1104z

There was a bug, when retreiving 2 analog channels, the first channel would complete, but the second would stop after
the first block.  The code incorrectly terminated the transfer.

Add transfer_block_size to device series table, and change DSO1000z from 30k to 250k.

Turn off beep when begining a transfer, then turn it on again when complete.  The scope would beep twice for each
block transferred.

Query the number of samples from the scope, rather than transfer everything.  When retreiving past the end of the
sample memory, errors would appear on the scope screen.

Change the behaviour of memory mode - this now just reads the memory from the scope that has already
captured something ie it doesn't do a "Run" before aquiring.  I did this because retreiving the sample count
was very unreliable.

Stop read digital channels multiple times - the code is already smart enough to know the digital data comes in 2
groups, D0-D7, and D8-D15, but it transfers the data again for each channel.  Eg if D0,D1,D2 are enabled, repeats the
transfer 3 times and appends the data to the caputer, when it already has the data.
---
 src/hardware/rigol-ds/api.c      | 52 +++++++++++++++++++++++--------
 src/hardware/rigol-ds/protocol.c | 66 ++++++++++++++++++++++++++++++++--------
 src/hardware/rigol-ds/protocol.h |  6 +---
 3 files changed, 93 insertions(+), 31 deletions(-)

diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c
index bdc15b7d..f8bb1a92 100644
--- a/src/hardware/rigol-ds/api.c
+++ b/src/hardware/rigol-ds/api.c
@@ -196,21 +196,21 @@ static const struct rigol_ds_vendor supported_vendors[] = {
  * number of horizontal divs, live waveform samples, memory buffer samples */
 static const struct rigol_ds_series supported_series[] = {
 	[VS5000] = {VENDOR(RIGOL), "VS5000", PROTOCOL_V1, FORMAT_RAW,
-		{50, 1}, {2, 1000}, 14, 2048, 0},
+		{50, 1}, {2, 1000}, 14, 2048, 0, 30000},
 	[DS1000] = {VENDOR(RIGOL), "DS1000", PROTOCOL_V2, FORMAT_IEEE488_2,
-		{50, 1}, {2, 1000}, 12, 600, 1048576},
+		{50, 1}, {2, 1000}, 12, 600, 1048576, 30000},
 	[DS2000] = {VENDOR(RIGOL), "DS2000", PROTOCOL_V3, FORMAT_IEEE488_2,
-		{500, 1}, {500, 1000000}, 14, 1400, 14000},
+		{500, 1}, {500, 1000000}, 14, 1400, 14000, 30000},
 	[DS2000A] = {VENDOR(RIGOL), "DS2000A", PROTOCOL_V3, FORMAT_IEEE488_2,
-		{1000, 1}, {500, 1000000}, 14, 1400, 14000},
+		{1000, 1}, {500, 1000000}, 14, 1400, 14000, 30000},
 	[DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2,
-		{50, 1}, {2, 1000}, 12, 600, 20480},
+		{50, 1}, {2, 1000}, 12, 600, 20480, 30000},
 	[DS1000Z] = {VENDOR(RIGOL), "DS1000Z", PROTOCOL_V4, FORMAT_IEEE488_2,
-		{50, 1}, {1, 1000}, 12, 1200, 12000000},
+		{50, 1}, {1, 1000}, 12, 1200, 12000000, 250000},
 	[DS4000] = {VENDOR(RIGOL), "DS4000", PROTOCOL_V4, FORMAT_IEEE488_2,
-		{1000, 1}, {1, 1000}, 14, 1400, 14000},
+		{1000, 1}, {1, 1000}, 14, 1400, 14000, 30000},
 	[MSO7000A] = {VENDOR(AGILENT), "MSO7000A", PROTOCOL_V4, FORMAT_IEEE488_2,
-		{50, 1}, {2, 1000}, 10, 1000, 8000000},
+		{50, 1}, {2, 1000}, 10, 1000, 8000000, 30000},
 };
 
 #define SERIES(x) &supported_series[x]
@@ -412,8 +412,8 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
 		}
 	}
 
-	devc->buffer = g_malloc(ACQ_BUFFER_SIZE);
-	devc->data = g_malloc(ACQ_BUFFER_SIZE * sizeof(float));
+	devc->buffer = g_malloc(devc->model->series->transfer_block_size);
+	devc->data = g_malloc(devc->model->series->transfer_block_size * sizeof(float));
 
 	devc->data_source = DATA_SOURCE_LIVE;
 
@@ -871,6 +871,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->num_frames = 0;
 
 	some_digital = FALSE;
+    uint16_t enabled_digital_channels = 0;
 	for (l = sdi->channels; l; l = l->next) {
 		ch = l->data;
 		sr_dbg("handling channel %s", ch->name);
@@ -891,8 +892,21 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 			if (ch->enabled && (
 						devc->model->series->protocol > PROTOCOL_V3 ||
 						!some_digital))
-				devc->enabled_channels = g_slist_append(
-						devc->enabled_channels, ch);
+            {
+                if ( devc->data_source == DATA_SOURCE_MEMORY ) {
+                    // only add 1 channel from each channel group D0-D7, D8-D15
+                    if ( ( ch->index < 8 && (enabled_digital_channels & 0x00FF) == 0 ) ||
+                         ( ch->index >= 8 && (enabled_digital_channels & 0xFF00) == 0 ) ) {
+                        devc->enabled_channels = g_slist_append(
+                                devc->enabled_channels, ch);
+                    } 
+                }
+                else {
+                    devc->enabled_channels = g_slist_append(
+                            devc->enabled_channels, ch);
+                }
+                enabled_digital_channels |= 1 << ch->index;
+            }
 			if (ch->enabled) {
 				some_digital = TRUE;
 				/* Turn on LA module if currently off. */
@@ -956,9 +970,21 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 		break;
 	}
 
-	if (devc->data_source == DATA_SOURCE_LIVE)
+	if (devc->data_source == DATA_SOURCE_LIVE) {
 		if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
 			return SR_ERR;
+    }
+    else {
+        // We must be stopped in memory mode
+        char *buf;
+        if (sr_scpi_get_string(sdi->conn, ":TRIG:STAT?", &buf) != SR_OK)
+            return SR_ERR;
+        if ( strcmp(buf,"STOP") != 0 ) {
+            sr_err("Scope must be STOPped when using memory mode");
+            return SR_ERR;
+        }
+
+    }
 
 	sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
 			rigol_ds_receive, (void *)sdi);
diff --git a/src/hardware/rigol-ds/protocol.c b/src/hardware/rigol-ds/protocol.c
index a533f12a..70653e0a 100644
--- a/src/hardware/rigol-ds/protocol.c
+++ b/src/hardware/rigol-ds/protocol.c
@@ -369,6 +369,10 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
 		break;
 	case PROTOCOL_V3:
 	case PROTOCOL_V4:
+	    if (devc->model->series->protocol == PROTOCOL_V4) {
+            if (rigol_ds_config_set(sdi, ":SYST:BEEP 0") != SR_OK)
+                return SR_ERR;
+        }
 		if (rigol_ds_config_set(sdi, ":WAV:FORM BYTE") != SR_OK)
 			return SR_ERR;
 		if (devc->data_source == DATA_SOURCE_LIVE) {
@@ -404,10 +408,13 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
 							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;
+            if (devc->data_source == DATA_SOURCE_LIVE) {
+                if (rigol_ds_config_set(sdi, ":SING") != SR_OK)
+                    return SR_ERR;
+            }
 			rigol_ds_set_wait_event(devc, WAIT_STOP);
 		}
 		break;
@@ -493,6 +500,31 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
 	} else if (ch->type == SR_CHANNEL_ANALOG) {
 		devc->vert_inc[ch->index] = devc->vdiv[ch->index] / 25.6;
 	}
+    if (devc->model->series->protocol == PROTOCOL_V4) {
+        // Ask the scope what the memory depth is.  We do this here, after the
+        // buffer has been captured.
+		char *preamble;
+        if ( sr_scpi_get_string(sdi->conn, ":WAV:PRE?", &preamble ) == SR_OK )
+        {
+            // points in the buffer is the 3 item in the comma separated list
+            gchar **params = g_strsplit(preamble,",",0);
+            if (  params[0] && params[1] && params[2] ) {
+                int memory_depth;
+                if ( sr_atoi( params[2], &memory_depth ) == SR_OK ) {
+                    if ( memory_depth ==  0 ) {
+                        // memory depth comes back as 0 sometimes - I don't know why
+                        sr_scpi_get_int( sdi->conn, ":ACQ:MDEP?", &memory_depth );
+                    }
+                    sr_dbg( "Scope reports Memory Depth = %d", memory_depth);
+                    if ( memory_depth > 0 ) {
+                        devc->analog_frame_size = devc->digital_frame_size = memory_depth;
+                    }
+                }
+            }
+            g_strfreev(params);
+        }
+    }
+
 
 	rigol_ds_set_wait_event(devc, WAIT_BLOCK);
 
@@ -626,7 +658,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 					devc->num_channel_bytes + 1) != SR_OK)
 				return TRUE;
 			if (rigol_ds_config_set(sdi, ":WAV:STOP %d",
-					MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE,
+					MIN(devc->num_channel_bytes + devc->model->series->transfer_block_size,
 						devc->analog_frame_size)) != SR_OK)
 				return TRUE;
 		}
@@ -671,8 +703,8 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 	}
 
 	len = devc->num_block_bytes - devc->num_block_read;
-	if (len > ACQ_BUFFER_SIZE)
-		len = ACQ_BUFFER_SIZE;
+	if (len > devc->model->series->transfer_block_size)
+		len = devc->model->series->transfer_block_size;
 	sr_dbg("Requesting read of %d bytes", len);
 
 	len = sr_scpi_read_data(scpi, (char *)devc->buffer, len);
@@ -738,14 +770,18 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 			if (devc->data_source != DATA_SOURCE_LIVE)
 				rigol_ds_set_wait_event(devc, WAIT_BLOCK);
 		}
+		// This code aborts a "from memory" acquisition too early when using multiple channels.
+		// The first channel completes, then the 2nd channel completes the first block, then aborts
+		// because devc->channel_entry->next is null.  This aborts before the check against
+		// expected_data_bytes a few lines down.
 		/* End acquisition when data for all channels is acquired. */
-		if (!sr_scpi_read_complete(scpi) && !devc->channel_entry->next) {
-			sr_err("Read should have been completed");
-			packet.type = SR_DF_FRAME_END;
-			sr_session_send(sdi, &packet);
-			sr_dev_acquisition_stop(sdi);
-			return TRUE;
-		}
+		//if (!sr_scpi_read_complete(scpi) && !devc->channel_entry->next) {
+			//sr_err("Read should have been completed");
+			//packet.type = SR_DF_FRAME_END;
+			//sr_session_send(sdi, &packet);
+			//sr_dev_acquisition_stop(sdi);
+			//return TRUE;
+		//}
 		devc->num_block_read = 0;
 	} else {
 		sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read",
@@ -779,8 +815,12 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
 		packet.type = SR_DF_FRAME_END;
 		sr_session_send(sdi, &packet);
 
-		if (++devc->num_frames == devc->limit_frames) {
+		// limit_frames is zero for the memory acquistion so after all channels a read, it starts again.
+		if (++devc->num_frames >= devc->limit_frames) {
 			/* Last frame, stop capture. */
+            if (devc->model->series->protocol == PROTOCOL_V4) {
+                rigol_ds_config_set(sdi, ":SYST:BEEP 1");
+            }
 			sr_dev_acquisition_stop(sdi);
 		} else {
 			/* Get the next frame, starting with the first channel. */
diff --git a/src/hardware/rigol-ds/protocol.h b/src/hardware/rigol-ds/protocol.h
index 86669b40..2aa2d23a 100644
--- a/src/hardware/rigol-ds/protocol.h
+++ b/src/hardware/rigol-ds/protocol.h
@@ -28,11 +28,6 @@
 
 #define LOG_PREFIX "rigol-ds"
 
-/* Size of acquisition buffers */
-#define ACQ_BUFFER_SIZE (32 * 1024)
-
-/* Maximum number of samples to retrieve at once. */
-#define ACQ_BLOCK_SIZE (30 * 1000)
 
 #define MAX_ANALOG_CHANNELS 4
 #define MAX_DIGITAL_CHANNELS 16
@@ -72,6 +67,7 @@ struct rigol_ds_series {
 	int num_horizontal_divs;
 	int live_samples;
 	int buffer_samples;
+    int transfer_block_size;
 };
 
 enum cmds {
-- 
2.11.0

