From 28135bc57ae439e58c2a0b4b8b58206118f878c9 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 14 Jun 2014 07:51:32 +0200 Subject: [PATCH 1/3] Apply the gas mode immediately. Because the gas mode takes precedence over the individual gas mix definitions, we can simplify the code by taking the gas mode into account immediately when parsing the gas mixes. --- src/suunto_d9_parser.c | 52 +++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 300d07e..6e87173 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -146,16 +146,22 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) // Cache the data for later use. parser->mode = data[gasmode_offset]; - parser->ngasmixes = gasmix_count; - for (unsigned int i = 0; i < gasmix_count; ++i) { - if (parser->model == HELO2 || parser->model == D4i || - parser->model == D6i || parser->model == D9tx || - parser->model == DX) { - parser->oxygen[i] = data[gasmix_offset + 6 * i + 1]; - parser->helium[i] = data[gasmix_offset + 6 * i + 2]; - } else { - parser->oxygen[i] = data[gasmix_offset + i]; - parser->helium[i] = 0.0; + if (parser->mode == AIR) { + parser->oxygen[0] = 21; + parser->helium[0] = 0; + parser->ngasmixes = 1; + } else { + parser->ngasmixes = gasmix_count; + for (unsigned int i = 0; i < gasmix_count; ++i) { + if (parser->model == HELO2 || parser->model == D4i || + parser->model == D6i || parser->model == D9tx || + parser->model == DX) { + parser->oxygen[i] = data[gasmix_offset + 6 * i + 1]; + parser->helium[i] = data[gasmix_offset + 6 * i + 2]; + } else { + parser->oxygen[i] = data[gasmix_offset + i]; + parser->helium[i] = 0; + } } } parser->config = config; @@ -297,20 +303,11 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne *((double *) value) = array_uint16_le (data + 0x09) / 100.0; break; case DC_FIELD_GASMIX_COUNT: - if (parser->mode == AIR) { - *((unsigned int *) value) = 1; - } else { - *((unsigned int *) value) = parser->ngasmixes; - } + *((unsigned int *) value) = parser->ngasmixes; break; case DC_FIELD_GASMIX: - if (parser->mode == AIR) { - gasmix->helium = 0.0; - gasmix->oxygen = 0.21; - } else { - gasmix->helium = parser->helium[flags] / 100.0; - gasmix->oxygen = parser->oxygen[flags] / 100.0; - } + gasmix->helium = parser->helium[flags] / 100.0; + gasmix->oxygen = parser->oxygen[flags] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; default: @@ -460,15 +457,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca // Initial gasmix. if (time == 0) { - unsigned int he = 0; - unsigned int o2 = 0; - if (parser->mode == AIR) { - he = 0; - o2 = 21; - } else { - he = parser->helium[gasmix]; - o2 = parser->oxygen[gasmix]; - } + unsigned int he = parser->helium[gasmix]; + unsigned int o2 = parser->oxygen[gasmix]; sample.event.type = SAMPLE_EVENT_GASCHANGE2; sample.event.time = 0; sample.event.value = o2 | (he << 16); From 86e9c3dfd3e777e24762e212df9ef7ac7c760d28 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 14 Jun 2014 08:01:17 +0200 Subject: [PATCH 2/3] Cache the initial gas mix. The gas mode should not only be taken into account for parsing the gas mix definitions, but also for the initial gas mix. Because the logic needs to be kept in sync, it's convenient to have all related code in a single place, and cache the value. --- src/suunto_d9_parser.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 6e87173..912cf0a 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -67,6 +67,7 @@ struct suunto_d9_parser_t { unsigned int ngasmixes; unsigned int oxygen[NGASMIXES]; unsigned int helium[NGASMIXES]; + unsigned int gasmix; unsigned int config; }; @@ -146,6 +147,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) // Cache the data for later use. parser->mode = data[gasmode_offset]; + parser->gasmix = 0; if (parser->mode == AIR) { parser->oxygen[0] = 21; parser->helium[0] = 0; @@ -163,6 +165,14 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) parser->helium[i] = 0; } } + + // Initial gasmix. + if (parser->model == HELO2) { + parser->gasmix = data[0x26]; + } else if (parser->model == D4i || parser->model == D6i || + parser->model == D9tx) { + parser->gasmix = data[0x28]; + } } parser->config = config; parser->cached = 1; @@ -195,6 +205,7 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int parser->oxygen[i] = 0; parser->helium[i] = 0; } + parser->gasmix = 0; parser->config = 0; *out = (dc_parser_t*) parser; @@ -226,6 +237,7 @@ suunto_d9_parser_set_data (dc_parser_t *abstract, const unsigned char *data, uns parser->oxygen[i] = 0; parser->helium[i] = 0; } + parser->gasmix = 0; parser->config = 0; return DC_STATUS_SUCCESS; @@ -332,19 +344,6 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca if (rc != DC_STATUS_SUCCESS) return rc; - // Initial gasmix. - unsigned int gasmix = 0; - if (parser->model == HELO2) { - gasmix = data[0x26]; - } else if (parser->model == D4i || parser->model == D6i || - parser->model == D9tx) { - gasmix = data[0x28]; - } - if (gasmix >= parser->ngasmixes) { - ERROR (abstract->context, "Invalid initial gas mix."); - return DC_STATUS_DATAFORMAT; - } - // Number of parameters in the configuration data. unsigned int nparams = data[parser->config]; if (nparams == 0 || nparams > MAXPARAMS) { @@ -457,8 +456,12 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca // Initial gasmix. if (time == 0) { - unsigned int he = parser->helium[gasmix]; - unsigned int o2 = parser->oxygen[gasmix]; + if (parser->gasmix >= parser->ngasmixes) { + ERROR (abstract->context, "Invalid initial gas mix."); + return DC_STATUS_DATAFORMAT; + } + unsigned int he = parser->helium[parser->gasmix]; + unsigned int o2 = parser->oxygen[parser->gasmix]; sample.event.type = SAMPLE_EVENT_GASCHANGE2; sample.event.time = 0; sample.event.value = o2 | (he << 16); From f20f28e9d0014dded3a4b975a3a143d3c6c19e17 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 14 Jun 2014 08:22:28 +0200 Subject: [PATCH 3/3] Ignore disabled gas mixes. For the older models, gas mixes are disabled by setting their oxygen percentage byte to 0x00 or 0xFF. Trying to parse such a byte as a valid percentage results in an invalid gas mix. Because the device doesn't allow you to enable a gas mix if the previous gas mix has already been disabled, we can simply stop parsing the gas mixes once the first disabled gas mix has been found. --- src/suunto_d9_parser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 912cf0a..63c6d0c 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -153,7 +153,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) parser->helium[0] = 0; parser->ngasmixes = 1; } else { - parser->ngasmixes = gasmix_count; + parser->ngasmixes = 0; for (unsigned int i = 0; i < gasmix_count; ++i) { if (parser->model == HELO2 || parser->model == D4i || parser->model == D6i || parser->model == D9tx || @@ -161,9 +161,13 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) parser->oxygen[i] = data[gasmix_offset + 6 * i + 1]; parser->helium[i] = data[gasmix_offset + 6 * i + 2]; } else { - parser->oxygen[i] = data[gasmix_offset + i]; + unsigned int oxygen = data[gasmix_offset + i]; + if (oxygen == 0x00 || oxygen == 0xFF) + break; + parser->oxygen[i] = oxygen; parser->helium[i] = 0; } + parser->ngasmixes++; } // Initial gasmix. @@ -455,7 +459,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca } // Initial gasmix. - if (time == 0) { + if (time == 0 && parser->ngasmixes > 0) { if (parser->gasmix >= parser->ngasmixes) { ERROR (abstract->context, "Invalid initial gas mix."); return DC_STATUS_DATAFORMAT;