[PATCH] Fix reading Cressi Leonardo data.

Vsevolod Velichko torkvemada at sorokdva.net
Mon Oct 2 15:15:17 PDT 2017


Jef,

I just tested your idea, so here are the results:
1. Double toggle on-off of DTR flag appears to be changing nothing. It still works if it is done before each message, and it still fails if it's done only once at startup.
2. Removal of the ping is definitely leads to fail. In most cases it looks like hang-up in the middle of dump sending. I have no idea for what reason.
3. Good news is that delays can be slightly decreased, so in modified patch below it's 120 ms instead of 300 ms.

In fact I suppose that this delay in each message shouldn't be considered something awful since in most cases it's done only 2-3 times before full dump, and the multiple random access to device memory is hardly ever used.
So I attach the modified version of the patch with decreased delays. 


Signed-off-by: Vsevolod Velichko <torkvemada at sorokdva.net>
---
 src/cressi_leonardo.c | 133 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 89 insertions(+), 44 deletions(-)

diff --git a/src/cressi_leonardo.c b/src/cressi_leonardo.c
index f21a223..14db35f 100644
--- a/src/cressi_leonardo.c
+++ b/src/cressi_leonardo.c
@@ -44,7 +44,10 @@
 #define RB_PROFILE_END   SZ_MEMORY
 #define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, 0, RB_PROFILE_BEGIN, RB_PROFILE_END)
 
-#define MAXRETRIES 4
+#define PING_ADDRESS 0x1000
+#define PING_LENGTH 19
+
+#define MAXRETRIES 20
 #define PACKETSIZE 32
 
 typedef struct cressi_leonardo_device_t {
@@ -74,6 +77,9 @@ static const dc_device_vtable_t cressi_leonardo_device_vtable = {
 static dc_status_t
 cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
 
+static dc_status_t
+cressi_leonardo_transfer_prepare (cressi_leonardo_device_t *device, dc_context_t *context);
+
 static void
 cressi_leonardo_make_ascii (const unsigned char raw[], unsigned int rsize, unsigned char ascii[], unsigned int asize)
 {
@@ -105,6 +111,13 @@ cressi_leonardo_packet (cressi_leonardo_device_t *device, const unsigned char co
 	if (device_is_cancelled (abstract))
 		return DC_STATUS_CANCELLED;
 
+	// Prepare device for writing.
+	status = cressi_leonardo_transfer_prepare (device, abstract->context);
+	if (status != DC_STATUS_SUCCESS) {
+		ERROR (abstract->context, "Failed to prepare device for transfer.");
+		return status;
+	}
+
 	// Send the command to the device.
 	status = dc_serial_write (device->port, command, csize, NULL);
 	if (status != DC_STATUS_SUCCESS) {
@@ -141,6 +154,37 @@ cressi_leonardo_packet (cressi_leonardo_device_t *device, const unsigned char co
 }
 
 static dc_status_t
+cressi_leonardo_transfer_prepare (cressi_leonardo_device_t *device, dc_context_t *context)
+{
+	// Set the RTS line.
+	dc_status_t status = dc_serial_set_rts (device->port, 1);
+	if (status != DC_STATUS_SUCCESS) {
+		ERROR (context, "Failed to set the RTS line.");
+		return status;
+	}
+
+	// Set the DTR line.
+	status = dc_serial_set_dtr (device->port, 1);
+	if (status != DC_STATUS_SUCCESS) {
+		ERROR (context, "Failed to set the DTR line.");
+		return status;
+	}
+
+	dc_serial_sleep (device->port, 100);
+
+	// Clear the DTR line.
+	status = dc_serial_set_dtr (device->port, 0);
+	if (status != DC_STATUS_SUCCESS) {
+		ERROR (context, "Failed to clear the DTR line.");
+		return status;
+	}
+
+	dc_serial_sleep (device->port, 20);
+	dc_serial_purge (device->port, DC_DIRECTION_ALL);
+	return status;
+}
+
+static dc_status_t
 cressi_leonardo_transfer (cressi_leonardo_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
 {
 	unsigned int nretries = 0;
@@ -197,39 +241,13 @@ cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const cha
 		goto error_close;
 	}
 
-	// Set the timeout for receiving data (1000 ms).
-	status = dc_serial_set_timeout (device->port, 1000);
+	// Set the timeout for receiving data (3000 ms).
+	status = dc_serial_set_timeout (device->port, 3000);
 	if (status != DC_STATUS_SUCCESS) {
 		ERROR (context, "Failed to set the timeout.");
 		goto error_close;
 	}
 
-	// Set the RTS line.
-	status = dc_serial_set_rts (device->port, 1);
-	if (status != DC_STATUS_SUCCESS) {
-		ERROR (context, "Failed to set the RTS line.");
-		goto error_close;
-	}
-
-	// Set the DTR line.
-	status = dc_serial_set_dtr (device->port, 1);
-	if (status != DC_STATUS_SUCCESS) {
-		ERROR (context, "Failed to set the DTR line.");
-		goto error_close;
-	}
-
-	dc_serial_sleep (device->port, 200);
-
-	// Clear the DTR line.
-	status = dc_serial_set_dtr (device->port, 0);
-	if (status != DC_STATUS_SUCCESS) {
-		ERROR (context, "Failed to clear the DTR line.");
-		goto error_close;
-	}
-
-	dc_serial_sleep (device->port, 100);
-	dc_serial_purge (device->port, DC_DIRECTION_ALL);
-
 	*out = (dc_device_t *) device;
 
 	return DC_STATUS_SUCCESS;
@@ -332,29 +350,56 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
 	progress.maximum = SZ_MEMORY;
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
-	// Send the command header to the dive computer.
-	const unsigned char command[] = {0x7B, 0x31, 0x32, 0x33, 0x44, 0x42, 0x41, 0x7d};
-	status = dc_serial_write (device->port, command, sizeof (command), NULL);
-	if (status != DC_STATUS_SUCCESS) {
-		ERROR (abstract->context, "Failed to send the command.");
-		return status;
+	for (int attempt = 0; attempt < MAXRETRIES; ++attempt) {
+		// Send the ping command to the dive computer.
+		unsigned char tmp[PING_LENGTH] = {0};
+		status = cressi_leonardo_device_read(abstract, PING_ADDRESS, tmp, sizeof(tmp));
+		if (status == DC_STATUS_SUCCESS)
+			break;
 	}
 
-	// Receive the header packet.
-	unsigned char header[7] = {0};
-	status = dc_serial_read (device->port, header, sizeof (header), NULL);
 	if (status != DC_STATUS_SUCCESS) {
-		ERROR (abstract->context, "Failed to receive the answer.");
+		ERROR (abstract->context, "Failed to ping device.");
 		return status;
 	}
 
-	// Verify the header packet.
-	const unsigned char expected[] = {0x7B, 0x21, 0x44, 0x35, 0x42, 0x33, 0x7d};
-	if (memcmp (header, expected, sizeof (expected)) != 0) {
-		ERROR (abstract->context, "Unexpected answer byte.");
-		return DC_STATUS_PROTOCOL;
+	for (int attempt = 0; attempt < MAXRETRIES; ++attempt) {
+		status = cressi_leonardo_transfer_prepare (device, abstract->context);
+		if (status != DC_STATUS_SUCCESS) {
+			ERROR (abstract->context, "Failed to prepare device for transfer.");
+			continue;
+		}
+
+		// Send the command header to the dive computer.
+		const unsigned char command[] = {0x7B, 0x31, 0x32, 0x33, 0x44, 0x42, 0x41, 0x7d};
+		status = dc_serial_write (device->port, command, sizeof (command), NULL);
+		if (status != DC_STATUS_SUCCESS) {
+			ERROR (abstract->context, "Failed to send the command.");
+			continue;
+		}
+
+		// Receive the header packet.
+		unsigned char header[7] = {0};
+		status = dc_serial_read (device->port, header, sizeof (header), NULL);
+		if (status != DC_STATUS_SUCCESS) {
+			ERROR (abstract->context, "Failed to receive the answer.");
+			continue;
+		}
+
+		// Verify the header packet.
+		const unsigned char expected[] = {0x7B, 0x21, 0x44, 0x35, 0x42, 0x33, 0x7d};
+		if (memcmp (header, expected, sizeof (expected)) != 0) {
+			ERROR (abstract->context, "Unexpected answer byte.");
+			status = DC_STATUS_PROTOCOL;
+			continue;
+		}
+
+		break;
 	}
 
+	if (status != DC_STATUS_SUCCESS)
+		return status;
+
 	unsigned char *data = dc_buffer_get_data (buffer);
 
 	unsigned int nbytes = 0;
-- 
2.11.0



More information about the devel mailing list