diff --git a/src/suunto_eon_parser.c b/src/suunto_eon_parser.c index 534b847..a803801 100644 --- a/src/suunto_eon_parser.c +++ b/src/suunto_eon_parser.c @@ -39,6 +39,8 @@ struct suunto_eon_parser_t { unsigned int cached; unsigned int divetime; unsigned int maxdepth; + unsigned int marker; + unsigned int nitrox; }; static dc_status_t suunto_eon_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); @@ -56,6 +58,55 @@ static const dc_parser_vtable_t suunto_eon_parser_vtable = { suunto_eon_parser_destroy /* destroy */ }; +static dc_status_t +suunto_eon_parser_cache (suunto_eon_parser_t *parser) +{ + dc_parser_t *abstract = (dc_parser_t *) parser; + const unsigned char *data = parser->base.data; + unsigned int size = parser->base.size; + + if (parser->cached) { + return DC_STATUS_SUCCESS; + } + + if (size < 13) { + return DC_STATUS_DATAFORMAT; + } + + // The Solution Nitrox/Vario stores nitrox data, not tank pressure. + unsigned int nitrox = !parser->spyder && (data[4] & 0x80); + + // Parse the samples. + unsigned int interval = data[3]; + unsigned int nsamples = 0; + unsigned int depth = 0, maxdepth = 0; + unsigned int offset = 11; + while (offset < size && data[offset] != 0x80) { + unsigned char value = data[offset++]; + if (value < 0x7d || value > 0x82) { + depth += (signed char) value; + if (depth > maxdepth) + maxdepth = depth; + nsamples++; + } + } + + // Check the end marker. + unsigned int marker = offset; + if (marker + 2 >= size || data[marker] != 0x80) { + ERROR (abstract->context, "No valid end marker found!"); + return DC_STATUS_DATAFORMAT; + } + + // Cache the data for later use. + parser->divetime = nsamples * interval; + parser->maxdepth = maxdepth; + parser->marker = marker; + parser->nitrox = nitrox; + parser->cached = 1; + + return DC_STATUS_SUCCESS; +} dc_status_t suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, int spyder) @@ -78,6 +129,8 @@ suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, int spyder) parser->cached = 0; parser->divetime = 0; parser->maxdepth = 0; + parser->marker = 0; + parser->nitrox = 0; *out = (dc_parser_t*) parser; @@ -104,6 +157,8 @@ suunto_eon_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un parser->cached = 0; parser->divetime = 0; parser->maxdepth = 0; + parser->marker = 0; + parser->nitrox = 0; return DC_STATUS_SUCCESS; } @@ -146,37 +201,24 @@ suunto_eon_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract; const unsigned char *data = abstract->data; - unsigned int size = abstract->size; - if (size < 13) - return DC_STATUS_DATAFORMAT; - - if (!parser->cached) { - unsigned int interval = data[3]; - unsigned int nsamples = 0; - unsigned int depth = 0, maxdepth = 0; - unsigned int offset = 11; - while (offset < size && data[offset] != 0x80) { - unsigned char value = data[offset++]; - if (value < 0x7d || value > 0x82) { - depth += (signed char) value; - if (depth > maxdepth) - maxdepth = depth; - nsamples++; - } - } - - // Store the offset to the end marker. - unsigned int marker = offset; - if (marker + 2 >= size || data[marker] != 0x80) - return DC_STATUS_DATAFORMAT; - - parser->cached = 1; - parser->divetime = nsamples * interval; - parser->maxdepth = maxdepth; - } + // Cache the data. + dc_status_t rc = suunto_eon_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; + dc_tank_t *tank = (dc_tank_t *) value; + + unsigned int oxygen = 21; + unsigned int beginpressure = 0; + unsigned int endpressure = 0; + if (parser->nitrox) { + oxygen = data[0x05]; + } else { + beginpressure = data[5] * 2; + endpressure = data[parser->marker + 2] * 2; + } if (value) { switch (type) { @@ -191,12 +233,29 @@ suunto_eon_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign break; case DC_FIELD_GASMIX: gasmix->helium = 0.0; - if ((data[4] & 0x80) && !parser->spyder) - gasmix->oxygen = data[0x05] / 100.0; - else - gasmix->oxygen = 0.21; + gasmix->oxygen = oxygen / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; + case DC_FIELD_TANK_COUNT: + if (beginpressure == 0 && endpressure == 0) + *((unsigned int *) value) = 0; + else + *((unsigned int *) value) = 1; + break; + case DC_FIELD_TANK: + tank->type = DC_TANKVOLUME_NONE; + tank->volume = 0.0; + tank->workpressure = 0.0; + tank->gasmix = 0; + tank->beginpressure = beginpressure; + tank->endpressure = endpressure; + break; + case DC_FIELD_TEMPERATURE_MINIMUM: + if (parser->spyder) + *((double *) value) = (signed char) data[parser->marker + 1]; + else + *((double *) value) = data[parser->marker + 1] - 40; + break; default: return DC_STATUS_UNSUPPORTED; } @@ -210,58 +269,29 @@ static dc_status_t suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract; - const unsigned char *data = abstract->data; unsigned int size = abstract->size; - - if (size < 13) - return DC_STATUS_DATAFORMAT; - - // Find the maximum depth. - unsigned int depth = 0, maxdepth = 0; - unsigned int offset = 11; - while (offset < size && data[offset] != 0x80) { - unsigned char value = data[offset++]; - if (value < 0x7d || value > 0x82) { - depth += (signed char) value; - if (depth > maxdepth) - maxdepth = depth; - } - } - - // Store the offset to the end marker. - unsigned int marker = offset; - if (marker + 2 >= size || data[marker] != 0x80) - return DC_STATUS_DATAFORMAT; - - // The Solution Nitrox/Vario stores nitrox data, not tank pressure. - unsigned int nitrox = !parser->spyder && (data[4] & 0x80); - - unsigned int time = 0; - unsigned int interval = data[3]; - unsigned int complete = 1; - dc_sample_value_t sample = {0}; - // Time - sample.time = time; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + // Cache the data. + dc_status_t rc = suunto_eon_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; - // Tank Pressure (2 bar) - if (!nitrox) { - sample.pressure.tank = 0; - sample.pressure.value = data[5] * 2; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - } + // Time + sample.time = 0; + if (callback) callback (DC_SAMPLE_TIME, sample, userdata); // Depth (0 ft) sample.depth = 0; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); - depth = 0; - offset = 11; + unsigned int depth = 0; + unsigned int time = 0; + unsigned int interval = data[3]; + unsigned int complete = 1; + unsigned int offset = 11; while (offset < size && data[offset] != 0x80) { - dc_sample_value_t sample = {0}; unsigned char value = data[offset++]; if (complete) { @@ -276,15 +306,6 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c // Delta depth. depth += (signed char) value; - // Temperature at maximum depth (°C) - if (depth == maxdepth) { - if (parser->spyder) - sample.temperature = (signed char) data[marker + 1]; - else - sample.temperature = data[marker + 1] - 40; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); - } - // Depth (ft). sample.depth = depth * FEET; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); @@ -327,13 +348,6 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c if (callback) callback (DC_SAMPLE_TIME, sample, userdata); } - // Tank Pressure (2 bar) - if (!nitrox) { - sample.pressure.tank = 0; - sample.pressure.value = data[offset + 2] * 2; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - } - // Depth (0 ft) sample.depth = 0; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c index 910670f..946dcaf 100644 --- a/src/suunto_vyper_parser.c +++ b/src/suunto_vyper_parser.c @@ -237,12 +237,17 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi unsigned int size = abstract->size; dc_gasmix_t *gas = (dc_gasmix_t *) value; + dc_tank_t *tank = (dc_tank_t *) value; // Cache the data. dc_status_t rc = suunto_vyper_parser_cache (parser); if (rc != DC_STATUS_SUCCESS) return rc; + unsigned int gauge = data[4] & 0x40; + unsigned int beginpressure = data[5] * 2; + unsigned int endpressure = data[parser->marker + 3] * 2; + if (value) { switch (type) { case DC_FIELD_DIVETIME: @@ -252,8 +257,8 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = parser->maxdepth * FEET; break; case DC_FIELD_GASMIX_COUNT: - if (data[4] & 0x40) - *((unsigned int *) value) = 0; // Gauge mode + if (gauge) + *((unsigned int *) value) = 0; else *((unsigned int *) value) = parser->ngasmixes; break; @@ -262,6 +267,23 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi gas->oxygen = parser->oxygen[flags] / 100.0; gas->nitrogen = 1.0 - gas->oxygen - gas->helium; break; + case DC_FIELD_TANK_COUNT: + if (beginpressure == 0 && endpressure == 0) + *((unsigned int *) value) = 0; + else + *((unsigned int *) value) = 1; + break; + case DC_FIELD_TANK: + tank->type = DC_TANKVOLUME_NONE; + tank->volume = 0.0; + tank->workpressure = 0.0; + if (gauge) + tank->gasmix = DC_GASMIX_UNKNOWN; + else + tank->gasmix = 0; + tank->beginpressure = beginpressure; + tank->endpressure = endpressure; + break; case DC_FIELD_TEMPERATURE_SURFACE: *((double *) value) = (signed char) data[8]; break; @@ -269,7 +291,7 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = (signed char) data[parser->marker + 1]; break; case DC_FIELD_DIVEMODE: - if (data[4] & 0x40) { + if (gauge) { *((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE; } else { *((dc_divemode_t *) value) = DC_DIVEMODE_OC; @@ -300,15 +322,6 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t sample.time = 0; if (callback) callback (DC_SAMPLE_TIME, sample, userdata); - // Temperature (°C) - sample.temperature = (signed char) data[8]; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); - - // Tank Pressure (2 bar) - sample.pressure.tank = 0; - sample.pressure.value = data[5] * 2; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - // Depth (0 ft) sample.depth = 0; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); @@ -333,12 +346,6 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Delta depth. depth += (signed char) value; - // Temperature at maximum depth (°C) - if (depth == parser->maxdepth) { - sample.temperature = (signed char) data[parser->marker + 1]; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); - } - // Depth (ft). sample.depth = depth * FEET; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); @@ -396,15 +403,6 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t if (callback) callback (DC_SAMPLE_TIME, sample, userdata); } - // Temperature (°C) - sample.temperature = (signed char) data[offset + 2]; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); - - // Tank Pressure (2 bar) - sample.pressure.tank = 0; - sample.pressure.value = data[offset + 3] * 2; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - // Depth (0 ft) sample.depth = 0; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);