From 6c441bb402b842fbe7b42816809c8a8faef03388 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 23 Sep 2019 21:23:57 +0200 Subject: [PATCH] Improve the support for multiple tank transmitters Some of the newer Shearwater dive computers support up to 2 tank pressure sensors. The tank pressure samples were already reported, but the tank field with the corresponding begin/end pressure was still missing. --- src/shearwater_predator_parser.c | 112 +++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index a4ef700..02b34da 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -68,6 +68,7 @@ #define IMPERIAL 1 #define NGASMIXES 10 +#define NTANKS 2 #define NRECORDS 7 #define PREDATOR 2 @@ -82,6 +83,12 @@ typedef struct shearwater_predator_gasmix_t { unsigned int helium; } shearwater_predator_gasmix_t; +typedef struct shearwater_predator_tank_t { + unsigned int enabled; + unsigned int beginpressure; + unsigned int endpressure; +} shearwater_predator_tank_t; + struct shearwater_predator_parser_t { dc_parser_t base; unsigned int model; @@ -97,7 +104,10 @@ struct shearwater_predator_parser_t { unsigned int closing[NRECORDS]; unsigned int final; unsigned int ngasmixes; + unsigned int ntanks; shearwater_predator_gasmix_t gasmix[NGASMIXES]; + shearwater_predator_tank_t tank[NTANKS]; + unsigned int tankidx[NTANKS]; unsigned int calibrated; double calibration[3]; dc_divemode_t mode; @@ -192,6 +202,13 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig parser->gasmix[i].oxygen = 0; parser->gasmix[i].helium = 0; } + parser->ntanks = 0; + for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].enabled = 0; + parser->tank[i].beginpressure = 0; + parser->tank[i].endpressure = 0; + parser->tankidx[i] = i; + } parser->calibrated = 0; for (unsigned int i = 0; i < 3; ++i) { parser->calibration[i] = 0.0; @@ -242,6 +259,13 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char parser->gasmix[i].oxygen = 0; parser->gasmix[i].helium = 0; } + parser->ntanks = 0; + for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].enabled = 0; + parser->tank[i].beginpressure = 0; + parser->tank[i].endpressure = 0; + parser->tankidx[i] = i; + } parser->calibrated = 0; for (unsigned int i = 0; i < 3; ++i) { parser->calibration[i] = 0.0; @@ -345,6 +369,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) // Get the gas mixes. unsigned int ngasmixes = 0; shearwater_predator_gasmix_t gasmix[NGASMIXES] = {0}; + shearwater_predator_tank_t tank[NTANKS] = {0}; unsigned int o2_previous = 0, he_previous = 0; unsigned int offset = headersize; @@ -392,6 +417,31 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) o2_previous = o2; he_previous = he; } + + // Tank pressure + if (logversion >= 7) { + const unsigned int idx[NTANKS] = {27, 19}; + for (unsigned int i = 0; i < NTANKS; ++i) { + // Values above 0xFFF0 are special codes: + // 0xFFFF AI is off + // 0xFFFE No comms for 90 seconds+ + // 0xFFFD No comms for 30 seconds + // 0xFFFC Transmitter not paired + // For regular values, the top 4 bits contain the battery + // level (0=normal, 1=critical, 2=warning), and the lower 12 + // bits the tank pressure in units of 2 psi. + unsigned int pressure = array_uint16_be (data + offset + pnf + idx[i]); + if (pressure < 0xFFF0) { + pressure &= 0x0FFF; + if (!tank[i].enabled) { + tank[i].enabled = 1; + tank[i].beginpressure = pressure; + tank[i].endpressure = pressure; + } + tank[i].endpressure = pressure; + } + } + } } else if (type == LOG_RECORD_FREEDIVE_SAMPLE) { // Freedive record mode = DC_DIVEMODE_FREEDIVE; @@ -463,6 +513,16 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) for (unsigned int i = 0; i < ngasmixes; ++i) { parser->gasmix[i] = gasmix[i]; } + parser->ntanks = 0; + for (unsigned int i = 0; i < NTANKS; ++i) { + if (tank[i].enabled) { + parser->tankidx[i] = parser->ntanks; + parser->tank[parser->ntanks] = tank[i]; + parser->ntanks++; + } else { + parser->tankidx[i] = UNDEFINED; + } + } parser->mode = mode; parser->units = data[parser->opening[0] + 8]; parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47)); @@ -485,6 +545,7 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ return rc; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; + dc_tank_t *tank = (dc_tank_t *) value; dc_salinity_t *water = (dc_salinity_t *) value; if (value) { @@ -511,6 +572,17 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ gasmix->helium = parser->gasmix[flags].helium / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; + case DC_FIELD_TANK_COUNT: + *((unsigned int *) value) = parser->ntanks; + break; + case DC_FIELD_TANK: + tank->type = DC_TANKVOLUME_NONE; + tank->volume = 0.0; + tank->workpressure = 0.0; + tank->beginpressure = parser->tank[flags].beginpressure * 2 * PSI / BAR; + tank->endpressure = parser->tank[flags].endpressure * 2 * PSI / BAR; + tank->gasmix = DC_GASMIX_UNKNOWN; + break; case DC_FIELD_SALINITY: if (parser->density == 1000) water->type = DC_WATER_FRESH; @@ -680,28 +752,24 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal // for logversion 7 and newer (introduced for Perdix AI) // detect tank pressure if (parser->logversion >= 7) { - // Tank pressure - // Values above 0xFFF0 are special codes: - // 0xFFFF AI is off - // 0xFFFE No comms for 90 seconds+ - // 0xFFFD No comms for 30 seconds - // 0xFFFC Transmitter not paired - // For regular values, the top 4 bits contain the battery - // level (0=normal, 1=critical, 2=warning), and the lower 12 - // bits the tank pressure in units of 2 psi. - unsigned int pressure = array_uint16_be (data + offset + pnf + 27); - if (pressure < 0xFFF0) { - pressure &= 0x0FFF; - sample.pressure.tank = 0; - sample.pressure.value = pressure * 2 * PSI / BAR; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - } - pressure = array_uint16_be (data + offset + pnf + 19); - if (pressure < 0xFFF0) { - pressure &= 0x0FFF; - sample.pressure.tank = 1; - sample.pressure.value = pressure * 2 * PSI / BAR; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + const unsigned int idx[NTANKS] = {27, 19}; + for (unsigned int i = 0; i < NTANKS; ++i) { + // Tank pressure + // Values above 0xFFF0 are special codes: + // 0xFFFF AI is off + // 0xFFFE No comms for 90 seconds+ + // 0xFFFD No comms for 30 seconds + // 0xFFFC Transmitter not paired + // For regular values, the top 4 bits contain the battery + // level (0=normal, 1=critical, 2=warning), and the lower 12 + // bits the tank pressure in units of 2 psi. + unsigned int pressure = array_uint16_be (data + offset + pnf + idx[i]); + if (pressure < 0xFFF0) { + pressure &= 0x0FFF; + sample.pressure.tank = parser->tankidx[i]; + sample.pressure.value = pressure * 2 * PSI / BAR; + if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + } } // Gas time remaining in minutes