From 5116ee8f2d0ab5550566b18e0a36da9a6856b54e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 2 Apr 2019 21:01:21 +0200 Subject: [PATCH 1/4] Get the gas mix index directly from the event data There is no need to lookup the gas mix index, because the number is stored directly in the event data, right next to the oxygen and helium values. This actually removes an ambiguity in cases where the user has configured two or more identical gas mixes. In that case, the lookup would always find the first gas mix. --- src/suunto_d9_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 10a7590..362f0d7 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -729,7 +729,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } - unknown = data[offset + 0]; + type = data[offset + 0]; he = data[offset + 1]; o2 = data[offset + 2]; if (parser->model == DX || parser->model == VYPERNOVO || @@ -738,7 +738,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca } else { seconds = data[offset + 3]; } - idx = suunto_d9_parser_find_gasmix(parser, o2, he); + idx = type & 0x0F; if (idx >= parser->ngasmixes) { ERROR (abstract->context, "Invalid gas mix."); return DC_STATUS_DATAFORMAT; From 6867ffb1435a292e34c9d1a77a254677bae107a6 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 2 Apr 2019 21:07:03 +0200 Subject: [PATCH 2/4] Implement the initial gas mix Initialize the initial gas mix correctly from the data in the dive header, instead of always using the first gas mix. --- src/suunto_d9_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 362f0d7..420d438 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -223,6 +223,8 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) } else { parser->gasmix = data[0x28]; } + } else if (parser->model == DX) { + parser->gasmix = data[0x31] & 0x7F; } } parser->config = config; From 8a70885f89d3ddef67e79c246a8d2d94c5f3efdd Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 2 Apr 2019 21:12:16 +0200 Subject: [PATCH 3/4] Take the CCR diluents into account The Suunto DX supports 3 CCR diluents and 8 OC gas mixes. Since the gas mix index in the data is relative to either the set of CCR diluents or OC gas mixes (depending on the dive mode) and libdivecomputer reports both sets, the index needs to be adjusted. --- src/suunto_d9_parser.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 420d438..39b42d3 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -77,6 +77,7 @@ struct suunto_d9_parser_t { unsigned int id; unsigned int mode; unsigned int ngasmixes; + unsigned int nccr; unsigned int oxygen[NGASMIXES]; unsigned int helium[NGASMIXES]; unsigned int gasmix; @@ -109,7 +110,7 @@ static unsigned int suunto_d9_parser_find_gasmix (suunto_d9_parser_t *parser, unsigned int o2, unsigned int he) { // Find the gasmix in the list. - unsigned int i = 0; + unsigned int i = parser->nccr; while (i < parser->ngasmixes) { if (o2 == parser->oxygen[i] && he == parser->helium[i]) break; @@ -136,6 +137,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) unsigned int gasmode_offset = 0x19; unsigned int gasmix_offset = 0x21; unsigned int gasmix_count = 3; + unsigned int ccr_count = 0; if (parser->model == HELO2) { gasmode_offset = 0x1F; gasmix_offset = 0x54; @@ -169,6 +171,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) else gasmix_offset = 0xC1; gasmix_count = 11; + ccr_count = 3; } // Offset to the configuration data. @@ -189,12 +192,15 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) parser->gasmix = 0; if (parser->mode == GAUGE || parser->mode == FREEDIVE) { parser->ngasmixes = 0; + parser->nccr = 0; } else if (parser->mode == AIR) { parser->oxygen[0] = 21; parser->helium[0] = 0; parser->ngasmixes = 1; + parser->nccr = 0; } else { parser->ngasmixes = 0; + parser->nccr = ccr_count; for (unsigned int i = 0; i < gasmix_count; ++i) { if (parser->model == HELO2 || parser->model == D4i || parser->model == D6i || parser->model == D9tx || @@ -225,6 +231,9 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) } } else if (parser->model == DX) { parser->gasmix = data[0x31] & 0x7F; + if ((data[0x31] & 0x80) == 0) { + parser->gasmix += parser->nccr; + } } } parser->config = config; @@ -255,6 +264,7 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int parser->id = 0; parser->mode = AIR; parser->ngasmixes = 0; + parser->nccr = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { parser->oxygen[i] = 0; parser->helium[i] = 0; @@ -278,6 +288,7 @@ suunto_d9_parser_set_data (dc_parser_t *abstract, const unsigned char *data, uns parser->id = 0; parser->mode = AIR; parser->ngasmixes = 0; + parser->nccr = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { parser->oxygen[i] = 0; parser->helium[i] = 0; @@ -741,6 +752,9 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca seconds = data[offset + 3]; } idx = type & 0x0F; + if ((type & 0x80) == 0) { + idx += parser->nccr; + } if (idx >= parser->ngasmixes) { ERROR (abstract->context, "Invalid gas mix."); return DC_STATUS_DATAFORMAT; From 6ee786c31a72dc36c79ce34da9091246afd01f69 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 2 Apr 2019 21:17:45 +0200 Subject: [PATCH 4/4] Report the setpoint data --- src/suunto_d9_parser.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 39b42d3..11b99e9 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -555,7 +555,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca unsigned int event = data[offset++]; unsigned int seconds, type, unknown, heading; unsigned int current, next; - unsigned int he, o2, idx; + unsigned int he, o2, ppo2, idx; unsigned int length; sample.event.type = SAMPLE_EVENT_NONE; @@ -747,8 +747,10 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca o2 = data[offset + 2]; if (parser->model == DX || parser->model == VYPERNOVO || (parser->model == D6i && parser->id == ID_D6I_V2)) { + ppo2 = data[offset + 3]; seconds = data[offset + 4]; } else { + ppo2 = 0; seconds = data[offset + 3]; } idx = type & 0x0F; @@ -761,6 +763,10 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca } sample.gasmix = idx; if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (type & 0x80) { + sample.setpoint = ppo2 / 10.0; + if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); + } offset += length; break; default: