From 5d36cc079878672d3669db91c44f05fa2905e1dd Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 31 Jul 2023 21:08:50 +0200 Subject: [PATCH] Remove disabled gas mixes Returning disabled gas mixes to the application mainly results in lots of unnecessary information. Therefore, remove all disabled gas mixes, unless they are actively used. Many other dive computers do not even include disabled gas mixes in the data. The removal of the disabled gas mixes requires a two pass approach for parsing the profile data. The first pass is only used to discover which gas mixes are actively used during the dive. Next, all disabled and not actively used gas mixes are removed from the list. Since removing one or more gas mixes also invalidates the index of the remaining gas mixes, the profile needs to be parsed again to report the new index in the gas switch samples. The original one based index is used as the stable gas mix id, used for looking up the new gas mix index. --- src/hw_ostc_parser.c | 99 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 20 deletions(-) diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 59e06ae..f1e306d 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -124,6 +124,7 @@ typedef struct hw_ostc_parser_t { const hw_ostc_layout_t *layout; unsigned int ngasmixes; unsigned int nfixed; + unsigned int ndisabled; unsigned int initial; unsigned int initial_setpoint; unsigned int initial_cns; @@ -134,6 +135,8 @@ static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_dateti static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); +static dc_status_t hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata); + static const dc_parser_vtable_t hw_ostc_parser_vtable = { sizeof(hw_ostc_parser_t), DC_FAMILY_HW_OSTC, @@ -194,7 +197,7 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = { static unsigned int hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil) { - unsigned int offset = parser->nfixed; + unsigned int offset = parser->nfixed - parser->ndisabled; unsigned int count = parser->ngasmixes; unsigned int i = offset; @@ -207,6 +210,22 @@ hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned return i; } +static unsigned int +hw_ostc_find_gasmix_fixed (hw_ostc_parser_t *parser, unsigned int id) +{ + unsigned int offset = 0; + unsigned int count = parser->nfixed - parser->ndisabled; + + unsigned int i = offset; + while (i < count) { + if (id == parser->gasmix[i].id) + break; + i++; + } + + return i; +} + static unsigned int hw_ostc_is_ccr (unsigned int divemode, unsigned int version) { @@ -341,7 +360,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser) ERROR(abstract->context, "Invalid initial gas mix."); return DC_STATUS_DATAFORMAT; } - initial--; /* Convert to a zero based index. */ } else { WARNING(abstract->context, "No initial gas mix available."); } @@ -352,6 +370,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser) parser->layout = layout; parser->ngasmixes = ngasmixes; parser->nfixed = ngasmixes; + parser->ndisabled = 0; parser->initial = initial; parser->initial_setpoint = initial_setpoint; parser->initial_cns = initial_cns; @@ -387,6 +406,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const parser->layout = NULL; parser->ngasmixes = 0; parser->nfixed = 0; + parser->ndisabled = 0; parser->initial = 0; parser->initial_setpoint = 0; parser->initial_cns = 0; @@ -491,7 +511,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned // Cache the profile data. if (parser->cached < PROFILE) { - rc = hw_ostc_parser_samples_foreach (abstract, NULL, NULL); + rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL); if (rc != DC_STATUS_SUCCESS) return rc; } @@ -679,17 +699,12 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned static dc_status_t -hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) +hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata) { - hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract; + dc_parser_t *abstract = (dc_parser_t *) parser; const unsigned char *data = abstract->data; unsigned int size = abstract->size; - // Cache the parser data. - dc_status_t rc = hw_ostc_parser_cache (parser); - if (rc != DC_STATUS_SUCCESS) - return rc; - unsigned int version = parser->version; unsigned int header = parser->header; const hw_ostc_layout_t *layout = parser->layout; @@ -795,7 +810,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call unsigned int time = 0; unsigned int nsamples = 0; - unsigned int tank = parser->initial != UNDEFINED ? parser->initial : 0; + unsigned int tank = parser->initial != UNDEFINED ? parser->initial - 1 : 0; unsigned int offset = header; if (version == 0x23 || version == 0x24) @@ -812,8 +827,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call // Initial gas mix. if (time == samplerate && parser->initial != UNDEFINED) { - parser->gasmix[parser->initial].active = 1; - sample.gasmix = parser->initial; + unsigned int idx = hw_ostc_find_gasmix_fixed (parser, parser->initial); + parser->gasmix[idx].active = 1; + sample.gasmix = idx; if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); } @@ -929,20 +945,20 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call ERROR (abstract->context, "Buffer overflow detected!"); return DC_STATUS_DATAFORMAT; } - unsigned int idx = data[offset]; - if (parser->model == OSTC4 && ccr && idx > parser->nfixed) { + unsigned int id = data[offset]; + if (parser->model == OSTC4 && ccr && id > parser->nfixed) { // Fix the OSTC4 diluent index. - idx -= parser->nfixed; + id -= parser->nfixed; } - if (idx < 1 || idx > parser->nfixed) { - ERROR(abstract->context, "Invalid gas mix (%u).", idx); + if (id < 1 || id > parser->nfixed) { + ERROR(abstract->context, "Invalid gas mix (%u).", id); return DC_STATUS_DATAFORMAT; } - idx--; /* Convert to a zero based index. */ + unsigned int idx = hw_ostc_find_gasmix_fixed (parser, id); parser->gasmix[idx].active = 1; sample.gasmix = idx; if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); - tank = idx; + tank = id - 1; offset++; length--; } @@ -1141,7 +1157,50 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call return DC_STATUS_DATAFORMAT; } + // Remove the disabled gas mixes from the fixed gas mixes. + unsigned int ndisabled = 0, nenabled = 0; + unsigned int count = parser->nfixed - parser->ndisabled; + for (unsigned int i = 0; i < count; ++i) { + if (parser->gasmix[i].enabled || parser->gasmix[i].active) { + // Move the fixed gas mix. + parser->gasmix[nenabled] = parser->gasmix[i]; + nenabled++; + } else { + ndisabled++; + } + } + + // Move all the manual gas mixes. + memmove (parser->gasmix + nenabled, parser->gasmix + count, + (parser->ngasmixes - count) * sizeof (hw_ostc_gasmix_t)); + memset (parser->gasmix + parser->ngasmixes - ndisabled, 0, + ndisabled * sizeof (hw_ostc_gasmix_t)); + + // Adjust the counts. + parser->ngasmixes -= ndisabled; + parser->ndisabled += ndisabled; + parser->cached = PROFILE; return DC_STATUS_SUCCESS; } + +static dc_status_t +hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) +{ + hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract; + + // Cache the header data. + dc_status_t rc = hw_ostc_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Cache the profile data. + if (parser->cached < PROFILE) { + rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL); + if (rc != DC_STATUS_SUCCESS) + return rc; + } + + return hw_ostc_parser_internal_foreach (parser, callback, userdata); +}