From 07dcc8998ba2aefe5cd354e1f9fdb0da8a6b8b87 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 29 Oct 2016 23:25:33 +0200 Subject: [PATCH] Add support for the Cressi Drake The Cressi Drake is a mainly a freedive computer. The data format is almost identical to the Leonardo. The main difference is that a single dive now contains an entire freedive session. Each freedive in the session is delimited with a 4 byte header containing the surface interval and a special marker. --- include/libdivecomputer/cressi_leonardo.h | 3 + src/cressi_leonardo_parser.c | 101 +++++++++++++++------- src/descriptor.c | 1 + src/libdivecomputer.symbols | 1 + src/parser.c | 2 +- 5 files changed, 78 insertions(+), 30 deletions(-) diff --git a/include/libdivecomputer/cressi_leonardo.h b/include/libdivecomputer/cressi_leonardo.h index bddc9d1..23e4554 100644 --- a/include/libdivecomputer/cressi_leonardo.h +++ b/include/libdivecomputer/cressi_leonardo.h @@ -39,6 +39,9 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] dc_status_t cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context); +dc_status_t +cressi_leonardo_parser_create2 (dc_parser_t **parser, dc_context_t *context, unsigned int model); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/cressi_leonardo_parser.c b/src/cressi_leonardo_parser.c index 656f487..cd97d9a 100644 --- a/src/cressi_leonardo_parser.c +++ b/src/cressi_leonardo_parser.c @@ -31,10 +31,13 @@ #define SZ_HEADER 82 +#define DRAKE 6 + typedef struct cressi_leonardo_parser_t cressi_leonardo_parser_t; struct cressi_leonardo_parser_t { dc_parser_t base; + unsigned int model; }; static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); @@ -54,7 +57,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = { dc_status_t -cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context) +cressi_leonardo_parser_create2 (dc_parser_t **out, dc_context_t *context, unsigned int model) { cressi_leonardo_parser_t *parser = NULL; @@ -68,12 +71,21 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context) return DC_STATUS_NOMEMORY; } + parser->model = model; + *out = (dc_parser_t*) parser; return DC_STATUS_SUCCESS; } +dc_status_t +cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context) +{ + return cressi_leonardo_parser_create2 (parser, context, 0); +} + + static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) { @@ -105,23 +117,33 @@ cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datet static dc_status_t cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { + cressi_leonardo_parser_t *parser = (cressi_leonardo_parser_t *) abstract; if (abstract->size < SZ_HEADER) return DC_STATUS_DATAFORMAT; const unsigned char *data = abstract->data; + unsigned int interval = 20; + if (parser->model == DRAKE) { + interval = 1; + } + dc_gasmix_t *gasmix = (dc_gasmix_t *) value; if (value) { switch (type) { case DC_FIELD_DIVETIME: - *((unsigned int *) value) = array_uint16_le (data + 0x06) * 20; + *((unsigned int *) value) = array_uint16_le (data + 0x06) * interval; break; case DC_FIELD_MAXDEPTH: *((double *) value) = array_uint16_le (data + 0x20) / 10.0; break; case DC_FIELD_GASMIX_COUNT: - *((unsigned int *) value) = 1; + if (parser->model == DRAKE) { + *((unsigned int *) value) = 0; + } else { + *((unsigned int *) value) = 1; + } break; case DC_FIELD_GASMIX: gasmix->helium = 0.0; @@ -143,11 +165,15 @@ cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { + cressi_leonardo_parser_t *parser = (cressi_leonardo_parser_t *) abstract; const unsigned char *data = abstract->data; unsigned int size = abstract->size; unsigned int time = 0; unsigned int interval = 20; + if (parser->model == DRAKE) { + interval = 1; + } unsigned int gasmix_previous = 0xFFFFFFFF; unsigned int gasmix = 0; @@ -156,36 +182,53 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac while (offset + 2 <= size) { dc_sample_value_t sample = {0}; - unsigned int value = array_uint16_le (data + offset); - unsigned int depth = value & 0x07FF; - unsigned int ascent = (value & 0xC000) >> 14; + if (offset + 4 <= size && + array_uint16_le (data + offset + 2) == 0xFF00) + { + unsigned int surftime = data[offset] + (data[offset + 1] & 0x07) * 60; - // Time (seconds). - time += interval; - sample.time = time; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + // Time (seconds). + time += surftime; + sample.time = time; + if (callback) callback (DC_SAMPLE_TIME, sample, userdata); - // Depth (1/10 m). - sample.depth = depth / 10.0; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + // Depth (1/10 m). + sample.depth = 0.0; + if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); - // Gas change. - if (gasmix != gasmix_previous) { - sample.gasmix = gasmix; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); - gasmix_previous = gasmix; + offset += 4; + } else { + unsigned int value = array_uint16_le (data + offset); + unsigned int depth = value & 0x07FF; + unsigned int ascent = (value & 0xC000) >> 14; + + // Time (seconds). + time += interval; + sample.time = time; + if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + + // Depth (1/10 m). + sample.depth = depth / 10.0; + if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + + // Gas change. + if (gasmix != gasmix_previous) { + sample.gasmix = gasmix; + if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + gasmix_previous = gasmix; + } + + // Ascent rate + if (ascent) { + sample.event.type = SAMPLE_EVENT_ASCENT; + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = ascent; + if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + } + + offset += 2; } - - // Ascent rate - if (ascent) { - sample.event.type = SAMPLE_EVENT_ASCENT; - sample.event.time = 0; - sample.event.flags = 0; - sample.event.value = ascent; - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); - } - - offset += 2; } return DC_STATUS_SUCCESS; diff --git a/src/descriptor.c b/src/descriptor.c index b48a168..5010635 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -253,6 +253,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Cressi", "Leonardo", DC_FAMILY_CRESSI_LEONARDO, 1}, {"Cressi", "Giotto", DC_FAMILY_CRESSI_LEONARDO, 4}, {"Cressi", "Newton", DC_FAMILY_CRESSI_LEONARDO, 5}, + {"Cressi", "Drake", DC_FAMILY_CRESSI_LEONARDO, 6}, /* Zeagle N2iTiON3 */ {"Zeagle", "N2iTiON3", DC_FAMILY_ZEAGLE_N2ITION3, 0}, {"Apeks", "Quantum X", DC_FAMILY_ZEAGLE_N2ITION3, 0}, diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 347db27..acadda3 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -66,6 +66,7 @@ hw_ostc_parser_create hw_ostc3_parser_create cressi_edy_parser_create cressi_leonardo_parser_create +cressi_leonardo_parser_create2 atomics_cobalt_parser_create atomics_cobalt_parser_set_calibration shearwater_predator_parser_create diff --git a/src/parser.c b/src/parser.c index bb3eb7a..8b10e38 100644 --- a/src/parser.c +++ b/src/parser.c @@ -123,7 +123,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa rc = cressi_edy_parser_create (&parser, context, model); break; case DC_FAMILY_CRESSI_LEONARDO: - rc = cressi_leonardo_parser_create (&parser, context); + rc = cressi_leonardo_parser_create2 (&parser, context, model); break; case DC_FAMILY_ATOMICS_COBALT: rc = atomics_cobalt_parser_create (&parser, context);