From af3b38d6f4b3c2c96485bea7c19b01550b446f17 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 12 Jul 2015 23:29:28 +0200 Subject: [PATCH 1/3] Cache the sample and header/footer size. --- src/shearwater_predator_parser.c | 83 +++++++++++++++++--------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 3d9d26d..daae44b 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -47,8 +47,11 @@ typedef struct shearwater_predator_parser_t shearwater_predator_parser_t; struct shearwater_predator_parser_t { dc_parser_t base; unsigned int petrel; + unsigned int samplesize; // Cached fields. unsigned int cached; + unsigned int headersize; + unsigned int footersize; unsigned int ngasmixes; unsigned int oxygen[NGASMIXES]; unsigned int helium[NGASMIXES]; @@ -96,12 +99,16 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig parser->petrel = petrel; if (petrel) { parser_init (&parser->base, context, &shearwater_petrel_parser_vtable); + parser->samplesize = SZ_SAMPLE_PETREL; } else { parser_init (&parser->base, context, &shearwater_predator_parser_vtable); + parser->samplesize = SZ_SAMPLE_PREDATOR; } // Set the default values. parser->cached = 0; + parser->headersize = 0; + parser->footersize = 0; parser->ngasmixes = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { parser->oxygen[i] = 0; @@ -145,6 +152,8 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char // Reset the cache. parser->cached = 0; + parser->headersize = 0; + parser->footersize = 0; parser->ngasmixes = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { parser->oxygen[i] = 0; @@ -176,6 +185,7 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d static dc_status_t shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) { + dc_parser_t *abstract = (dc_parser_t *) parser; const unsigned char *data = parser->base.data; unsigned int size = parser->base.size; @@ -183,6 +193,22 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) return DC_STATUS_SUCCESS; } + unsigned int headersize = SZ_BLOCK; + unsigned int footersize = SZ_BLOCK; + if (size < headersize + footersize) { + ERROR (abstract->context, "Invalid data length."); + return DC_STATUS_DATAFORMAT; + } + + // Adjust the footersize for the final block. + if (parser->petrel || array_uint16_be (data + size - footersize) == 0xFFFD) { + footersize += SZ_BLOCK; + if (size < headersize + footersize) { + ERROR (abstract->context, "Invalid data length."); + return DC_STATUS_DATAFORMAT; + } + } + // Get the gas mixes. unsigned int ngasmixes = 0; unsigned int oxygen[NGASMIXES] = {0}; @@ -198,6 +224,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) } // Cache the data for later use. + parser->headersize = headersize; + parser->footersize = footersize; parser->ngasmixes = ngasmixes; for (unsigned int i = 0; i < ngasmixes; ++i) { parser->oxygen[i] = oxygen[i]; @@ -217,26 +245,17 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ const unsigned char *data = abstract->data; unsigned int size = abstract->size; - if (size < 2 * SZ_BLOCK) - return DC_STATUS_DATAFORMAT; - - // Get the offset to the footer record. - unsigned int footer = size - SZ_BLOCK; - if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) { - if (size < 3 * SZ_BLOCK) - return DC_STATUS_DATAFORMAT; - - footer -= SZ_BLOCK; - } - - // Get the unit system. - unsigned int units = data[8]; - - // Cache the gas mix data. + // Cache the parser data. dc_status_t rc = shearwater_predator_parser_cache (parser); if (rc != DC_STATUS_SUCCESS) return rc; + // Get the offset to the footer record. + unsigned int footer = size - parser->footersize; + + // Get the unit system. + unsigned int units = data[8]; + dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_salinity_t *water = (dc_salinity_t *) value; unsigned int density = 0; @@ -288,23 +307,10 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal const unsigned char *data = abstract->data; unsigned int size = abstract->size; - if (size < 2 * SZ_BLOCK) - return DC_STATUS_DATAFORMAT; - - // Get the offset to the footer record. - unsigned int footer = size - SZ_BLOCK; - if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) { - if (size < 3 * SZ_BLOCK) - return DC_STATUS_DATAFORMAT; - - footer -= SZ_BLOCK; - } - - // Get the sample size. - unsigned int samplesize = SZ_SAMPLE_PREDATOR; - if (parser->petrel) { - samplesize = SZ_SAMPLE_PETREL; - } + // Cache the parser data. + dc_status_t rc = shearwater_predator_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; // Get the unit system. unsigned int units = data[8]; @@ -313,13 +319,14 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal unsigned int o2_previous = 0, he_previous = 0; unsigned int time = 0; - unsigned int offset = SZ_BLOCK; - while (offset < footer) { + unsigned int offset = parser->headersize; + unsigned int length = size - parser->footersize; + while (offset < length) { dc_sample_value_t sample = {0}; // Ignore empty samples. - if (array_isequal (data + offset, samplesize, 0x00)) { - offset += samplesize; + if (array_isequal (data + offset, parser->samplesize, 0x00)) { + offset += parser->samplesize; continue; } @@ -382,7 +389,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal sample.deco.time = data[offset + 9] * 60; if (callback) callback (DC_SAMPLE_DECO, sample, userdata); - offset += samplesize; + offset += parser->samplesize; } return DC_STATUS_SUCCESS; From 1a8e757daf8d014bd3e5ada3fee614753a7a58a3 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 12 Jul 2015 23:43:37 +0200 Subject: [PATCH 2/3] Add support for the dive mode. The Shearwaters store the current dive mode for each sample, and not one single value for each dive. Therfore we need to process all samples. If there is at least one sample marked as closed circuit, we classify the dive as a closed circuit dive. Otherwise we default to open circuit. --- src/shearwater_predator_parser.c | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index daae44b..4a7aa4c 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -37,6 +37,12 @@ #define SZ_SAMPLE_PREDATOR 0x10 #define SZ_SAMPLE_PETREL 0x20 +#define GASSWITCH 0x01 +#define PPO2_EXTERNAL 0x02 +#define SETPOINT_HIGH 0x04 +#define SC 0x08 +#define OC 0x10 + #define METRIC 0 #define IMPERIAL 1 @@ -236,6 +242,33 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) return DC_STATUS_SUCCESS; } +static dc_divemode_t +shearwater_predator_parser_get_divemode (shearwater_predator_parser_t *parser) +{ + dc_parser_t *abstract = (dc_parser_t *) parser; + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int offset = parser->headersize; + unsigned int length = size - parser->footersize; + while (offset < length) { + // Ignore empty samples. + if (array_isequal (data + offset, parser->samplesize, 0x00)) { + offset += parser->samplesize; + continue; + } + + // Status flags. + unsigned int status = data[offset + 11]; + if ((status & OC) == 0) { + return DC_DIVEMODE_CC; + } + + offset += parser->samplesize; + } + + return DC_DIVEMODE_OC; +} static dc_status_t shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) @@ -290,6 +323,9 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ case DC_FIELD_ATMOSPHERIC: *((double *) value) = array_uint16_be (data + 47) / 1000.0; break; + case DC_FIELD_DIVEMODE: + *((dc_divemode_t *) value) = shearwater_predator_parser_get_divemode (parser); + break; default: return DC_STATUS_UNSUPPORTED; } From 0d04ad58a3607978395c247038e613b56d72b27c Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 5 Mar 2015 16:11:59 +0100 Subject: [PATCH 3/3] Add support for setpoint samples. The setpoint samples are only enabled for closed circuit dives. --- src/shearwater_predator_parser.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 4a7aa4c..f5ada2b 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -387,10 +387,27 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal sample.temperature = temperature; if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); + // Status flags. + unsigned int status = data[offset + 11]; + // PPO2 sample.ppo2 = data[offset + 6] / 100.0; if (callback) callback (DC_SAMPLE_PPO2, sample, userdata); + if ((status & OC) == 0) { + // Setpoint + if (parser->petrel) { + sample.setpoint = data[offset + 18] / 100.0; + } else { + if (status & SETPOINT_HIGH) { + sample.setpoint = data[18] / 100.0; + } else { + sample.setpoint = data[17] / 100.0; + } + } + if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); + } + // CNS if (parser->petrel) { sample.cns = data[offset + 22] / 100.0;