Oceanic / Aeris A300CS multipage patches

Dirk Hohndel dirk at hohndel.org
Tue Oct 14 10:27:22 PDT 2014


On Tue, Oct 14, 2014 at 06:41:29PM +0200, Dirk Hohndel wrote:
> Hi Jef,
> 
> as discussed earlier today, here are patches that implement aligned
> multipage reads and mixed blocksize reads ONLY for dive computers that
> support 256 byte page reads. So far that appears to be only the A300CS but
> my guess is that we'll see more such dive computers in the future.
> 
> This way we should get performant downloads from the A300CS without
> risking to break older dive computers.

BTW: if you'd prefer we could add another field (something like
"mixed_pagesize_support") to oceanic_atom2_device_t and then could enable
this for those dive computers with 128 byte pages where we can test and
verify that this works. That would make it less of a special case for the
A300CS. I wasn't sure which version you'd prefer, so I implemented the
A300CS specific one (or actually, the 256 byte page specific one), but I'm
happy to go the other direction if you think that's better.

Actually, the more I think about it, maybe that's the better way in case
Oceanic / Aeris come out with a 256 byte page read model that doesn't
support mixed paged sizes...

So attached are three patches as an alternative to the two im my last
email that implement things this way (and enable it on the A300CS).

This has been tested with Linus' A300CS and it's fast and works reliably
with the dives I can still download from the dive computer.

/D
-------------- next part --------------
>From 72b301b9dc10e9ef790d0c913d6919c628a26c96 Mon Sep 17 00:00:00 2001
From: Dirk Hohndel <dirk at hohndel.org>
Date: Fri, 26 Sep 2014 10:58:15 -0700
Subject: [PATCH 1/3] Adjust multipage algorithm to create aligned reads for
 256 byte pages

At least the A300CS requires that 256 byte reads (16 * PAGESIZE) are
aligned to that pagesize.

Signed-off-by: Dirk Hohndel <dirk at hohndel.org>
---
 src/oceanic_common.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/oceanic_common.c b/src/oceanic_common.c
index f5f37a149596..6069157a4aaf 100644
--- a/src/oceanic_common.c
+++ b/src/oceanic_common.c
@@ -536,6 +536,16 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
 			if (nbytes + len > remaining)
 				len = remaining - nbytes; // End of profile.
 
+			// for the newer device that support reads of 16 pages, the address appears
+			// to have to be aligned
+			if (device->multipage == 16 && len == PAGESIZE * device->multipage) {
+				if (address % (PAGESIZE * device->multipage)) {
+					// this wouldn't be an aligned read
+					// let's read a smaller subset first which should have the remaining
+					// reads be aligned
+					len = address % (PAGESIZE * device->multipage);
+				}
+			}
 			// Move to the start of the current page.
 			address -= len;
 			offset -= len;
-- 
1.8.0.rc0.18.gf84667d

-------------- next part --------------
>From 9b43d7644d75eabf558e305b24a3d8bdbf0b1eb3 Mon Sep 17 00:00:00 2001
From: Dirk Hohndel <dirk at hohndel.org>
Date: Wed, 24 Sep 2014 21:26:32 -0700
Subject: [PATCH 2/3] Prepare Oceanic infrastructure for mixed multi page
 reads

Some new Oceanic dive computers like the Aeris A300CS support a new read
command that always reads 256 byte pages instead of 16 byte pages. So far
the only known implementations of this command is known to support mixing
and matching different read page sizes. On the other hand, some older dive
computers that support the 128 byte pagesize read appear not to support
mixing different read page sizes. So in order not to break support for
older dive computer, this patch only implements mixing different page
sizes where explicitly enabled

This patch adds two fields to the oceanic_atom2_device_t structure to
indicate which type of device this is. The multipage algorithm will
request larger, (and in the case of 256 byte reads, aligned) reads
wherever possible and fall back to standard 16 byte reads otherwise.

Signed-off-by: Dirk Hohndel <dirk at hohndel.org>
---
 src/oceanic_atom2.c | 62 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 49 insertions(+), 13 deletions(-)

diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c
index 8cc2c71a2b77..295fd0ac846b 100644
--- a/src/oceanic_atom2.c
+++ b/src/oceanic_atom2.c
@@ -49,6 +49,8 @@ typedef struct oceanic_atom2_device_t {
 	oceanic_common_device_t base;
 	serial_t *port;
 	unsigned int delay;
+	unsigned char bigpage;
+	unsigned char mixed_pagesize_support;
 } oceanic_atom2_device_t;
 
 static dc_status_t oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
@@ -423,9 +425,15 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm
 			return EXITCODE (n);
 		}
 
-		// Verify the checksum of the answer.
-		unsigned char crc = answer[asize - 1];
-		unsigned char ccrc = checksum_add_uint8 (answer, asize - 1, 0x00);
+		// Verify the checksum of the answer; we can use unsigned short in both cases
+		unsigned short crc, ccrc;
+		if (asize == 256 + 2) { // 256 byte pages get two crc bytes
+			crc = (answer[asize - 1] << 8) | answer[asize - 2] ;
+			ccrc = checksum_add_uint16 (answer, asize - 2, 0x0000);
+		} else {
+			crc = answer[asize - 1];
+			ccrc = checksum_add_uint8 (answer, asize - 1, 0x00);
+		}
 		if (crc != ccrc) {
 			ERROR (abstract->context, "Unexpected answer checksum.");
 			return DC_STATUS_PROTOCOL;
@@ -468,6 +476,8 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
 	// Set the default values.
 	device->port = NULL;
 	device->delay = 0;
+	device->bigpage = 1; // no big pages
+	device->mixed_pagesize_support = 0; // don't mix different page sizes when reading
 
 	// Open the device.
 	int rc = serial_open (&device->port, context, name);
@@ -623,33 +633,59 @@ oceanic_atom2_device_version (dc_device_t *abstract, unsigned char data[], unsig
 }
 
 
+/* newer devices like the A300CS allow switching between different page sizes between reads across
+ * the whole address space - but some older devices have problems when doing that. In order not to
+ * break support for older dive computers, we only support mixed block sized for models that
+ * explicitly enable support for that. In that case, if we have aligned reads of a larger pagesize
+ * use the larger block reads, otherwise just loop and read in PAGESIZE chunks */
 static dc_status_t
 oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
 {
 	oceanic_atom2_device_t *device = (oceanic_atom2_device_t*) abstract;
 
-	if ((address % PAGESIZE != 0) ||
-		(size    % PAGESIZE != 0))
+	// pick the best pagesize to use
+	unsigned int pagesize = PAGESIZE;
+
+	if (device->mixed_pagesize_support && size == device->bigpage * PAGESIZE && address % (device->bigpage * PAGESIZE) == 0)
+		pagesize = device->bigpage * PAGESIZE;
+
+	// pick the correct read command and number of crc bytes based on the page size
+	unsigned char read_cmd, crc_size;
+	if (pagesize == 16 * PAGESIZE) {
+		read_cmd = 0xB8;
+		crc_size = 2;
+	} else if (pagesize == 8 * PAGESIZE) {
+		read_cmd = 0xB4;
+		crc_size = 1;
+	} else {
+		read_cmd = 0xB1;
+		crc_size = 1;
+	}
+
+	if ((address % pagesize != 0) ||
+	    (size    % pagesize != 0))
 		return DC_STATUS_INVALIDARGS;
 
 	unsigned int nbytes = 0;
+
 	while (nbytes < size) {
 		// Read the package.
-		unsigned int number = address / PAGESIZE;
-		unsigned char answer[PAGESIZE + 1] = {0};
-		unsigned char command[4] = {0xB1,
+		unsigned int number = address / PAGESIZE;      // this is always PAGESIZE, even in BIGPAGE mode
+		unsigned char answer[256 + 2] = {0};           // maximum we support for the known commands
+		unsigned int answersize = pagesize + crc_size;
+		unsigned char command[4] = {read_cmd,
 				(number >> 8) & 0xFF, // high
 				(number     ) & 0xFF, // low
 				0};
-		dc_status_t rc = oceanic_atom2_transfer (device, command, sizeof (command), answer, sizeof (answer));
+		dc_status_t rc = oceanic_atom2_transfer (device, command, sizeof (command), answer, answersize);
 		if (rc != DC_STATUS_SUCCESS)
 			return rc;
 
-		memcpy (data, answer, PAGESIZE);
+		memcpy (data, answer, pagesize);
 
-		nbytes += PAGESIZE;
-		address += PAGESIZE;
-		data += PAGESIZE;
+		nbytes += pagesize;
+		address += pagesize;
+		data += pagesize;
 	}
 
 	return DC_STATUS_SUCCESS;
-- 
1.8.0.rc0.18.gf84667d

-------------- next part --------------
>From 1c2c459d2df1c68139a441f48385fea5f94bd3b8 Mon Sep 17 00:00:00 2001
From: Dirk Hohndel <dirk at hohndel.org>
Date: Tue, 14 Oct 2014 19:20:32 +0200
Subject: [PATCH 3/3] Aeris A300CS: Enable mixed page size reads

Signed-off-by: Dirk Hohndel <dirk at hohndel.org>
---
 src/oceanic_atom2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c
index 295fd0ac846b..75da4f4e027e 100644
--- a/src/oceanic_atom2.c
+++ b/src/oceanic_atom2.c
@@ -561,6 +561,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
 		device->base.layout = &aeris_a300cs_layout;
 		device->bigpage = 16;
 		device->base.multipage = 16;
+		device->mixed_pagesize_support = 1;
 	} else {
 		device->base.layout = &oceanic_default_layout;
 	}
-- 
1.8.0.rc0.18.gf84667d



More information about the devel mailing list