From 651123de537b4b866d5b6b9e8314ccd2e37f53df Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 27 Oct 2014 09:37:45 +0100 Subject: [PATCH 1/3] Add support for parsing the dive mode. --- examples/universal.c | 16 ++++++++++++++++ include/libdivecomputer/parser.h | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/examples/universal.c b/examples/universal.c index 2f5d616..2b0fc81 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -467,6 +467,22 @@ doparse (FILE *fp, dc_device_t *device, const unsigned char data[], unsigned int tank.beginpressure, tank.endpressure); } + // Parse the dive mode. + message ("Parsing the dive mode.\n"); + dc_divemode_t divemode = DC_DIVEMODE_OC; + rc = dc_parser_get_field (parser, DC_FIELD_DIVEMODE, 0, &divemode); + if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { + WARNING ("Error parsing the dive mode."); + dc_parser_destroy (parser); + return rc; + } + + if (rc != DC_STATUS_UNSUPPORTED) { + const char *names[] = {"freedive", "gauge", "oc", "cc"}; + fprintf (fp, "%s\n", + names[divemode]); + } + // Parse the salinity. message ("Parsing the salinity.\n"); dc_salinity_t salinity = {DC_WATER_FRESH, 0.0}; diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index 63dc113..f1f73bd 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -58,7 +58,8 @@ typedef enum dc_field_type_t { DC_FIELD_TEMPERATURE_MINIMUM, DC_FIELD_TEMPERATURE_MAXIMUM, DC_FIELD_TANK_COUNT, - DC_FIELD_TANK + DC_FIELD_TANK, + DC_FIELD_DIVEMODE } dc_field_type_t; typedef enum parser_sample_event_t { @@ -115,6 +116,13 @@ typedef enum dc_water_t { DC_WATER_SALT } dc_water_t; +typedef enum dc_divemode_t { + DC_DIVEMODE_FREEDIVE, + DC_DIVEMODE_GAUGE, + DC_DIVEMODE_OC, /* Open circuit */ + DC_DIVEMODE_CC /* Closed circuit */ +} dc_divemode_t; + typedef enum dc_deco_type_t { DC_DECO_NDL, DC_DECO_SAFETYSTOP, From c95ab19e6a4151f307a3db9bcda78e5c08fff3e2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 5 Nov 2014 10:08:47 +0100 Subject: [PATCH 2/3] Use symbolic constants for the dive mode. --- src/mares_common.c | 9 +++++++-- src/mares_nemo_parser.c | 19 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/mares_common.c b/src/mares_common.c index b7042c8..7f0655e 100644 --- a/src/mares_common.c +++ b/src/mares_common.c @@ -46,6 +46,11 @@ #define NEMOAPNEIST 18 #define PUCKAIR 19 +#define AIR 0 +#define NITROX 1 +#define FREEDIVE 2 +#define GAUGE 3 + void mares_common_device_init (mares_common_device_t *device, dc_context_t *context, const dc_device_vtable_t *vtable) { @@ -212,9 +217,9 @@ mares_common_extract_dives (dc_context_t *context, const mares_common_layout_t * // Get the freedive mode for this model. unsigned int model = data[1]; - unsigned int freedive = 2; + unsigned int freedive = FREEDIVE; if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR) - freedive = 3; + freedive = GAUGE; // Get the end of the profile ring buffer. unsigned int eop = array_uint16_le (data + 0x6B); diff --git a/src/mares_nemo_parser.c b/src/mares_nemo_parser.c index e226ce6..03a88ee 100644 --- a/src/mares_nemo_parser.c +++ b/src/mares_nemo_parser.c @@ -39,6 +39,11 @@ #define NEMOAPNEIST 18 #define PUCKAIR 19 +#define AIR 0 +#define NITROX 1 +#define FREEDIVE 2 +#define GAUGE 3 + typedef struct mares_nemo_parser_t mares_nemo_parser_t; struct mares_nemo_parser_t { @@ -87,14 +92,14 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int parser_init (&parser->base, context, &mares_nemo_parser_vtable); // Get the freedive mode for this model. - unsigned int freedive = 2; + unsigned int freedive = FREEDIVE; if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR) - freedive = 3; + freedive = GAUGE; // Set the default values. parser->model = model; parser->freedive = freedive; - parser->mode = 0; + parser->mode = AIR; parser->length = 0; parser->sample_count = 0; parser->sample_size = 0; @@ -125,7 +130,7 @@ mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un // Clear the previous state. parser->base.data = NULL; parser->base.size = 0; - parser->mode = 0; + parser->mode = AIR; parser->length = 0; parser->sample_count = 0; parser->sample_size = 0; @@ -234,17 +239,17 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign *((double *) value) = array_uint16_le (p + 53 - 10) / 10.0; break; case DC_FIELD_GASMIX_COUNT: - if (parser->mode == 0 || parser->mode == 1) + if (parser->mode == AIR || parser->mode == NITROX) *((unsigned int *) value) = 1; else *((unsigned int *) value) = 0; break; case DC_FIELD_GASMIX: switch (parser->mode) { - case 0: // Air + case AIR: gasmix->oxygen = 0.21; break; - case 1: // Nitrox + case NITROX: gasmix->oxygen = p[53 - 43] / 100.0; break; default: From 88159c6fe4bac07a526e62b3c7cb83930243ec67 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 27 Oct 2014 09:38:14 +0100 Subject: [PATCH 3/3] Implement the dive mode for several devices. The new dive mode field is now supported by devices from these manufacturers: * Atomic Aquatics * Heinrichs Weikamp * Mares * Reefnet * Suunto --- src/atomics_cobalt_parser.c | 12 ++++++ src/hw_ostc_parser.c | 71 ++++++++++++++++++++++++++++++++ src/mares_iconhd_parser.c | 13 ++++++ src/mares_nemo_parser.c | 17 ++++++++ src/reefnet_sensus_parser.c | 3 ++ src/reefnet_sensuspro_parser.c | 3 ++ src/reefnet_sensusultra_parser.c | 3 ++ src/suunto_d9_parser.c | 21 ++++++++++ src/suunto_vyper_parser.c | 7 ++++ 9 files changed, 150 insertions(+) diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index f5b1044..ce17100 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -203,6 +203,18 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR; tank->endpressure = array_uint16_le(p + 14) * PSI / BAR; break; + case DC_FIELD_DIVEMODE: + switch(p[0x24]) { + case 0: // Open Circuit Trimix + case 2: // Open Circuit Nitrox + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case 1: // Closed Circuit + *((dc_divemode_t *) value) = DC_DIVEMODE_CC; + break; + default: + return DC_STATUS_DATAFORMAT; + } default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index ac42219..de0cef9 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -33,6 +33,23 @@ #define MAXCONFIG 7 #define MAXGASMIX 5 +#define OSTC_ZHL16_OC 0 +#define OSTC_GAUGE 1 +#define OSTC_ZHL16_CC 2 +#define OSTC_APNEA 3 +#define OSTC_ZHL16_OC_GF 4 +#define OSTC_ZHL16_CC_GF 5 +#define OSTC_PSCR_GF 6 + +#define FROG_ZHL16 0 +#define FROG_ZHL16_GF 1 +#define FROG_APNEA 2 + +#define OSTC3_OC 0 +#define OSTC3_CC 1 +#define OSTC3_GAUGE 2 +#define OSTC3_APNEA 3 + typedef struct hw_ostc_parser_t hw_ostc_parser_t; struct hw_ostc_parser_t { @@ -323,6 +340,60 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed short) array_uint16_le (data + layout->temperature) / 10.0; break; + case DC_FIELD_DIVEMODE: + if (version == 0x21) { + switch (data[51]) { + case OSTC_APNEA: + *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; + break; + case OSTC_GAUGE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; + case OSTC_ZHL16_OC: + case OSTC_ZHL16_OC_GF: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case OSTC_ZHL16_CC: + case OSTC_ZHL16_CC_GF: + case OSTC_PSCR_GF: + *((dc_divemode_t *) value) = DC_DIVEMODE_CC; + break; + default: + return DC_STATUS_DATAFORMAT; + } + } else if (version == 0x22) { + switch (data[51]) { + case FROG_ZHL16: + case FROG_ZHL16_GF: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case FROG_APNEA: + *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; + break; + default: + return DC_STATUS_DATAFORMAT; + } + } else if (version == 0x23) { + switch (data[82]) { + case OSTC3_OC: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case OSTC3_CC: + *((dc_divemode_t *) value) = DC_DIVEMODE_CC; + break; + case OSTC3_GAUGE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; + case OSTC3_APNEA: + *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; + break; + default: + return DC_STATUS_DATAFORMAT; + } + } else { + return DC_STATUS_UNSUPPORTED; + } + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 6016e44..ccf297b 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -258,6 +258,19 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi case DC_FIELD_TEMPERATURE_MAXIMUM: *((double *) value) = (signed short) array_uint16_le (p + 0x48) / 10.0; break; + case DC_FIELD_DIVEMODE: + switch (p[0] & 0x03) { + case AIR: + case NITROX: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case GAUGE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; + default: + return DC_STATUS_DATAFORMAT; + } + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/mares_nemo_parser.c b/src/mares_nemo_parser.c index 03a88ee..c396fea 100644 --- a/src/mares_nemo_parser.c +++ b/src/mares_nemo_parser.c @@ -261,6 +261,20 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed char) p[53 - 11]; break; + case DC_FIELD_DIVEMODE: + switch (parser->mode) { + case AIR: + case NITROX: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case FREEDIVE: + case GAUGE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; + default: + return DC_STATUS_DATAFORMAT; + } + break; default: return DC_STATUS_UNSUPPORTED; } @@ -283,6 +297,9 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed char) p[28 - 11]; break; + case DC_FIELD_DIVEMODE: + *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/reefnet_sensus_parser.c b/src/reefnet_sensus_parser.c index cbbb5dd..9b5de72 100644 --- a/src/reefnet_sensus_parser.c +++ b/src/reefnet_sensus_parser.c @@ -211,6 +211,9 @@ reefnet_sensus_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = 0; break; + case DC_FIELD_DIVEMODE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c index 6f818e8..0f3af95 100644 --- a/src/reefnet_sensuspro_parser.c +++ b/src/reefnet_sensuspro_parser.c @@ -200,6 +200,9 @@ reefnet_sensuspro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = 0; break; + case DC_FIELD_DIVEMODE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/reefnet_sensusultra_parser.c b/src/reefnet_sensusultra_parser.c index e4ed80a..1d85b06 100644 --- a/src/reefnet_sensusultra_parser.c +++ b/src/reefnet_sensusultra_parser.c @@ -201,6 +201,9 @@ reefnet_sensusultra_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = 0; break; + case DC_FIELD_DIVEMODE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 63c6d0c..939dab6 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -51,6 +51,7 @@ #define GAUGE 2 #define FREEDIVE 3 #define MIXED 4 +#define CCR 5 #define SAFETYSTOP (1 << 0) #define DECOSTOP (1 << 1) @@ -326,6 +327,26 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne gasmix->oxygen = parser->oxygen[flags] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; + case DC_FIELD_DIVEMODE: + switch (parser->mode) { + case AIR: + case NITROX: + case MIXED: + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + break; + case GAUGE: + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + break; + case FREEDIVE: + *((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE; + break; + case CCR: + *((dc_divemode_t *) value) = DC_DIVEMODE_CC; + break; + default: + return DC_STATUS_DATAFORMAT; + } + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c index f1dc6ce..15e6db6 100644 --- a/src/suunto_vyper_parser.c +++ b/src/suunto_vyper_parser.c @@ -198,6 +198,13 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed char) data[parser->marker + 1]; break; + case DC_FIELD_DIVEMODE: + if (data[4] & 0x40) { + *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; + } else { + *((dc_divemode_t *) value) = DC_DIVEMODE_OC; + } + break; default: return DC_STATUS_UNSUPPORTED; }