RFC: add larger pagesize read to Atom2 backend

Dirk Hohndel dirk at hohndel.org
Sun Oct 19 08:14:46 PDT 2014


So after all the back and forth I'm not 100% sure where we wanted to end
up with the larger pagesize read support.

Here's something really simple, really straight forward (I think) that
should not impact any of the other backends (unless there's a bug in my
code, always a possibility).

It should be trivial to extend this for other models that have a 128 byte
pagesize and support unaligned reads.

It doesn't mess with the multipage code, it doesn't change any of the
calling code to do alignment for us - so on average this will use about
twice the number of reads that better optimized code would use - but still
only about 1/8 of the reads that the current code would use.

Let me know what you think.

And yes, this turns into patch #5 after the four existing A300CS patches
and should applied with the four of them together, in case you like it.

/D
-------------- next part --------------
>From 440b04f7988d407b197a42ce25462225af22a1d0 Mon Sep 17 00:00:00 2001
From: Dirk Hohndel <dirk at hohndel.org>
Date: Sun, 19 Oct 2014 08:05:12 -0700
Subject: [PATCH 5/5] Add capability to read larger pages to atom2 backend

This adds pagesize, crc_size, read_cmd and an alignment flag to the
private device structure and modifies the reads accordingly.

It does not bother with caching and never switches read commands, so even
on dive computers that can switch between different sizes we take the
penalty for reading in larger chunks even if we don't need them - during a
typical download from the dive computer that will result in about twice
the number of reads than a perfect algorithm would need (but still 1/8 of
the reads that not supporting the larger pagesize would give us) but keeps
our code much simpler.

So far this is only enabled for the Aeris A300CS

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

diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c
index f507241a0d66..b5de4fcdf705 100644
--- a/src/oceanic_atom2.c
+++ b/src/oceanic_atom2.c
@@ -49,6 +49,10 @@ typedef struct oceanic_atom2_device_t {
 	oceanic_common_device_t base;
 	serial_t *port;
 	unsigned int delay;
+	unsigned int pagesize;
+	unsigned int crc_size;
+	unsigned char read_cmd;
+	unsigned char aligned;
 } 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 +427,16 @@ 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 +479,10 @@ 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->read_cmd = 0xB1;
+	device->pagesize = PAGESIZE;
+	device->crc_size = 1;
+	device->aligned = 0;
 
 	// Open the device.
 	int rc = serial_open (&device->port, context, name);
@@ -549,6 +564,10 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
 		device->base.layout = &oceanic_reactpro_layout;
 	} else if (OCEANIC_COMMON_MATCH (device->base.version, aeris_a300cs_version)) {
 		device->base.layout = &aeris_a300cs_layout;
+		device->read_cmd = 0xB8;
+		device->pagesize = 16 * PAGESIZE;
+		device->crc_size = 2;
+		device->aligned = 1;
 	} else {
 		device->base.layout = &oceanic_default_layout;
 	}
@@ -633,21 +652,30 @@ oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned
 	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 offset = 0;
+		if (device->aligned)
+			offset = (address % device->pagesize);
+		unsigned int page_address = address - offset;
+		unsigned int number = page_address / PAGESIZE;
+		unsigned char answer[256 + 2] = {0};  // that's the largest we'll encounter
+		unsigned char command[4] = {device->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,
+							 device->pagesize + device->crc_size);
 		if (rc != DC_STATUS_SUCCESS)
 			return rc;
 
-		memcpy (data, answer, PAGESIZE);
+		unsigned int read_size = device->pagesize - offset;
+		if (nbytes + read_size > size)
+			read_size = size - nbytes;
 
-		nbytes += PAGESIZE;
-		address += PAGESIZE;
-		data += PAGESIZE;
+		memcpy (data, answer + offset, read_size);
+
+		nbytes += read_size;
+		address += read_size;
+		data += read_size;
 	}
 
 	return DC_STATUS_SUCCESS;
-- 
1.8.0.rc0.18.gf84667d



More information about the devel mailing list