From 6b88bc1b8b18059cd570dd023c21aec4cb48087c Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 31 Aug 2017 19:44:38 +0200 Subject: [PATCH] Fix the Uwatec trimix data format The trimix dive header is only 84 bytes large, instead of 0xB1 bytes. The difference is quite hard to notice, because compared to the normal Galileo data format, the majority of the fields are located at exactly the same offset. But there are also some subtle differences, like the settings field containing the freedive and gauge bits. To fix this bug, a new header table is added. The rest of the code is updated to use this new table instead of the old trimix flag. The only place where the old flag is still used is for the decoding of the tank and pressure sample. --- src/uwatec_smart_parser.c | 67 ++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 54bdee5..c1311ee 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -142,9 +142,9 @@ struct uwatec_smart_parser_t { unsigned int nsamples; const uwatec_smart_event_info_t *events[NEVENTS]; unsigned int nevents[NEVENTS]; + unsigned int trimix; // Cached fields. unsigned int cached; - unsigned int trimix; unsigned int ngasmixes; uwatec_smart_gasmix_t gasmix[NGASMIXES]; unsigned int ntanks; @@ -194,6 +194,19 @@ uwatec_smart_header_info_t uwatec_smart_galileo_header = { 92, /* settings */ }; +static const +uwatec_smart_header_info_t uwatec_smart_trimix_header = { + 22, /* maxdepth */ + 26, /* divetime */ + UNSUPPORTED, 0, /* gasmixes */ + 30, /* temp_minimum */ + 28, /* temp_maximum */ + 32, /* temp_surface */ + UNSUPPORTED, /* tankpressure */ + 16, /* timezone */ + 68, /* settings */ +}; + static const uwatec_smart_header_info_t uwatec_smart_aladin_tec_header = { 22, @@ -418,32 +431,32 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) { const unsigned char *data = parser->base.data; unsigned int size = parser->base.size; - const uwatec_smart_header_info_t *header = parser->header; if (parser->cached) { return DC_STATUS_SUCCESS; } - unsigned int trimix = 0; if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { if (size < 44) return DC_STATUS_DATAFORMAT; if (data[43] & 0x80) { - trimix = 1; - } - - if (trimix) { + parser->trimix = 1; + parser->headersize = 84; + parser->header = &uwatec_smart_trimix_header; parser->events[2] = uwatec_smart_trimix_events_2; parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_trimix_events_2); } else { + parser->trimix = 0; + parser->headersize = 152; + parser->header = &uwatec_smart_galileo_header; parser->events[2] = uwatec_smart_galileo_events_2; parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_galileo_events_2); } - } else if (parser->model == G2) { - trimix = 1; } + const uwatec_smart_header_info_t *header = parser->header; + // Get the settings. dc_divemode_t divemode = DC_DIVEMODE_OC; dc_water_t watertype = DC_WATER_FRESH; @@ -479,7 +492,7 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) unsigned int ngasmixes = 0; uwatec_smart_tank_t tank[NGASMIXES] = {{0}}; uwatec_smart_gasmix_t gasmix[NGASMIXES] = {{0}}; - if (!trimix) { + if (header->gasmix != UNSUPPORTED) { for (unsigned int i = 0; i < header->ngases; ++i) { unsigned int idx = DC_GASMIX_UNKNOWN; unsigned int o2 = 0; @@ -526,7 +539,6 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) } // Cache the data for later use. - parser->trimix = trimix; parser->ngasmixes = ngasmixes; for (unsigned int i = 0; i < ngasmixes; ++i) { parser->gasmix[i] = gasmix[i]; @@ -563,6 +575,7 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i parser->model = model; parser->devtime = devtime; parser->systime = systime; + parser->trimix = 0; for (unsigned int i = 0; i < NEVENTS; ++i) { parser->events[i] = NULL; parser->nevents[i] = 0; @@ -582,7 +595,6 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i case MERIDIAN: case CHROMIS: case MANTIS2: - case G2: parser->headersize = 152; parser->header = &uwatec_smart_galileo_header; parser->samples = uwatec_smart_galileo_samples; @@ -594,6 +606,19 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_galileo_events_1); parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_galileo_events_2); break; + case G2: + parser->headersize = 84; + parser->header = &uwatec_smart_trimix_header; + parser->samples = uwatec_smart_galileo_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_galileo_samples); + parser->events[0] = uwatec_smart_galileo_events_0; + parser->events[1] = uwatec_smart_galileo_events_1; + parser->events[2] = uwatec_smart_trimix_events_2; + parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_galileo_events_0); + parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_galileo_events_1); + parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_trimix_events_2); + parser->trimix = 1; + break; case ALADINTEC: parser->headersize = 108; parser->header = &uwatec_smart_aladin_tec_header; @@ -635,7 +660,6 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i } parser->cached = 0; - parser->trimix = 0; parser->ngasmixes = 0; parser->ntanks = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { @@ -667,7 +691,6 @@ uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, // Reset the cache. parser->cached = 0; - parser->trimix = 0; parser->ngasmixes = 0; parser->ntanks = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { @@ -728,9 +751,6 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi { uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract; - const unsigned char *data = abstract->data; - const uwatec_smart_header_info_t *table = parser->header; - // Cache the parser data. dc_status_t rc = uwatec_smart_parser_cache (parser); if (rc != DC_STATUS_SUCCESS) @@ -743,6 +763,9 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi return rc; } + const uwatec_smart_header_info_t *table = parser->header; + const unsigned char *data = abstract->data; + double salinity = (parser->watertype == DC_WATER_SALT ? SALT : FRESH); dc_gasmix_t *gasmix = (dc_gasmix_t *) value; @@ -766,13 +789,9 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; case DC_FIELD_TANK_COUNT: - if (table->tankpressure == UNSUPPORTED) - return DC_STATUS_UNSUPPORTED; *((unsigned int *) value) = parser->ntanks; break; case DC_FIELD_TANK: - if (table->tankpressure == UNSUPPORTED) - return DC_STATUS_UNSUPPORTED; tank->type = DC_TANKVOLUME_NONE; tank->volume = 0.0; tank->workpressure = 0.0; @@ -885,10 +904,6 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t const uwatec_smart_sample_info_t *table = parser->samples; unsigned int entries = parser->nsamples; - unsigned int header = parser->headersize; - if (parser->trimix) { - header = 0xB1; - } // Get the maximum number of alarm bytes. unsigned int nalarms = 0; @@ -927,7 +942,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t int have_depth = 0, have_temperature = 0, have_pressure = 0, have_rbt = 0, have_heartrate = 0, have_bearing = 0; - unsigned int offset = header; + unsigned int offset = parser->headersize; while (offset < size) { dc_sample_value_t sample = {0};