>From 1b3a2fe3b3257ddb198507b2c87dbcb80735dc3d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 24 Sep 2014 21:26:32 -0700 Subject: [PATCH 2/5] Prepare Oceanic infrastructure for 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, other versions support reading 128 byte pages. This patch adds a field to the oceanic_atom2_device_t structure to indicate which type of device this is. The multipage algorithm will request larger, aligned reads wherever possible and fall back to standard 16 byte reads otherwise. Signed-off-by: Dirk Hohndel --- src/oceanic_atom2.c | 58 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 17e19580d42f..9fd10f56a90d 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; + } 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); @@ -406,9 +408,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; @@ -451,6 +459,7 @@ 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 // Open the device. int rc = serial_open (&device->port, context, name); @@ -598,33 +607,56 @@ oceanic_atom2_device_version (dc_device_t *abstract, unsigned char data[], unsig } +/* if we have aligned reads of a larger pagesize (and the device supports that), 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 (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 == 256) { + read_cmd = 0xB8; + crc_size = 2; + } else if (pagesize == 128) { + 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