From 1cd285a4d8b36b11e5ff9ffddcd94e750056392f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Aug 2019 20:05:02 +0200 Subject: [PATCH 1/5] Use a struct for the gasmix and tank data This small refactoring is mainly a preparation to support multiple tanks. There is no functional change. --- src/divesystem_idive_parser.c | 83 +++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index 66f77dc..ec3399a 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -39,6 +39,7 @@ #define SZ_SAMPLE_IX3M_APOS4 0x40 #define NGASMIXES 8 +#define NTANKS 1 #define EPOCH 1199145600 /* 2008-01-01 00:00:00 */ @@ -51,6 +52,16 @@ typedef struct divesystem_idive_parser_t divesystem_idive_parser_t; +typedef struct divesystem_idive_gasmix_t { + unsigned int oxygen; + unsigned int helium; +} divesystem_idive_gasmix_t; + +typedef struct divesystem_idive_tank_t { + unsigned int beginpressure; + unsigned int endpressure; +} divesystem_idive_tank_t; + struct divesystem_idive_parser_t { dc_parser_t base; unsigned int model; @@ -61,10 +72,9 @@ struct divesystem_idive_parser_t { unsigned int divetime; unsigned int maxdepth; unsigned int ngasmixes; - unsigned int oxygen[NGASMIXES]; - unsigned int helium[NGASMIXES]; - unsigned int beginpressure; - unsigned int endpressure; + unsigned int ntanks; + divesystem_idive_gasmix_t gasmix[NGASMIXES]; + divesystem_idive_tank_t tank[NTANKS]; }; static dc_status_t divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); @@ -110,12 +120,15 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign parser->divetime = 0; parser->maxdepth = 0; parser->ngasmixes = 0; + parser->ntanks = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { - parser->oxygen[i] = 0; - parser->helium[i] = 0; + parser->gasmix[i].oxygen = 0; + parser->gasmix[i].helium = 0; + } + for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].beginpressure = 0; + parser->tank[i].endpressure = 0; } - parser->beginpressure = 0; - parser->endpressure = 0; *out = (dc_parser_t*) parser; @@ -134,12 +147,15 @@ divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *da parser->divetime = 0; parser->maxdepth = 0; parser->ngasmixes = 0; + parser->ntanks = 0; for (unsigned int i = 0; i < NGASMIXES; ++i) { - parser->oxygen[i] = 0; - parser->helium[i] = 0; + parser->gasmix[i].oxygen = 0; + parser->gasmix[i].helium = 0; + } + for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].beginpressure = 0; + parser->tank[i].endpressure = 0; } - parser->beginpressure = 0; - parser->endpressure = 0; return DC_STATUS_SUCCESS; } @@ -276,21 +292,19 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, *((unsigned int *) value) = parser->ngasmixes; break; case DC_FIELD_GASMIX: - gasmix->helium = parser->helium[flags] / 100.0; - gasmix->oxygen = parser->oxygen[flags] / 100.0; + gasmix->helium = parser->gasmix[flags].helium / 100.0; + gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; case DC_FIELD_TANK_COUNT: - if (parser->beginpressure == 0 && parser->endpressure == 0) - return DC_STATUS_UNSUPPORTED; - *((unsigned int *) value) = 1; + *((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->beginpressure; - tank->endpressure = parser->endpressure; + tank->beginpressure = parser->tank[flags].beginpressure; + tank->endpressure = parser->tank[flags].endpressure; tank->gasmix = DC_GASMIX_UNKNOWN; break; case DC_FIELD_ATMOSPHERIC: @@ -347,14 +361,13 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba unsigned int time = 0; unsigned int maxdepth = 0; unsigned int ngasmixes = 0; - unsigned int oxygen[NGASMIXES]; - unsigned int helium[NGASMIXES]; + unsigned int ntanks = 0; + divesystem_idive_gasmix_t gasmix[NGASMIXES] = {0}; + divesystem_idive_tank_t tank[NTANKS] = {0}; unsigned int o2_previous = 0xFFFFFFFF; unsigned int he_previous = 0xFFFFFFFF; unsigned int mode_previous = INVALID; unsigned int divemode = INVALID; - unsigned int beginpressure = 0; - unsigned int endpressure = 0; unsigned int firmware = 0; unsigned int apos4 = 0; @@ -431,7 +444,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba // Find the gasmix in the list. unsigned int i = 0; while (i < ngasmixes) { - if (o2 == oxygen[i] && he == helium[i]) + if (o2 == gasmix[i].oxygen && he == gasmix[i].helium) break; i++; } @@ -442,8 +455,8 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba ERROR (abstract->context, "Maximum number of gas mixes reached."); return DC_STATUS_DATAFORMAT; } - oxygen[i] = o2; - helium[i] = he; + gasmix[i].oxygen = o2; + gasmix[i].helium = he; ngasmixes = i + 1; } @@ -490,14 +503,15 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba // Tank Pressure if (samplesize == SZ_SAMPLE_IX3M_APOS4) { unsigned int pressure = data[offset + 49]; - if (beginpressure == 0 && pressure != 0) { - beginpressure = pressure; + if (tank[0].beginpressure == 0 && pressure != 0) { + tank[0].beginpressure = pressure; + ntanks = 1; } - if (beginpressure) { + if (tank[0].beginpressure) { sample.pressure.tank = 0; sample.pressure.value = pressure; if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - endpressure = pressure; + tank[0].endpressure = pressure; } } @@ -505,13 +519,14 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba } // Cache the data for later use. - parser->beginpressure = beginpressure; - parser->endpressure = endpressure; + for (unsigned int i = 0; i < ntanks; ++i) { + parser->tank[i] = tank[i]; + } for (unsigned int i = 0; i < ngasmixes; ++i) { - parser->helium[i] = helium[i]; - parser->oxygen[i] = oxygen[i]; + parser->gasmix[i] = gasmix[i]; } parser->ngasmixes = ngasmixes; + parser->ntanks = ntanks; parser->maxdepth = maxdepth; parser->divetime = time; parser->divemode = divemode; From dc508c30f93d7271955274d97157f5713e95ac0f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 22 Aug 2019 21:18:48 +0200 Subject: [PATCH 2/5] Add support for multiple tank transmitters The Ratio dive computers support up to 10 tank pressure sensors. The ID of the active tank sensor is stored in the sample data, and gets mapped to the corresponding tank index. --- src/divesystem_idive_parser.c | 42 +++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index ec3399a..bba5d51 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -39,7 +39,7 @@ #define SZ_SAMPLE_IX3M_APOS4 0x40 #define NGASMIXES 8 -#define NTANKS 1 +#define NTANKS 10 #define EPOCH 1199145600 /* 2008-01-01 00:00:00 */ @@ -58,6 +58,7 @@ typedef struct divesystem_idive_gasmix_t { } divesystem_idive_gasmix_t; typedef struct divesystem_idive_tank_t { + unsigned int id; unsigned int beginpressure; unsigned int endpressure; } divesystem_idive_tank_t; @@ -126,6 +127,7 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign parser->gasmix[i].helium = 0; } for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].id = 0; parser->tank[i].beginpressure = 0; parser->tank[i].endpressure = 0; } @@ -153,6 +155,7 @@ divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *da parser->gasmix[i].helium = 0; } for (unsigned int i = 0; i < NTANKS; ++i) { + parser->tank[i].id = 0; parser->tank[i].beginpressure = 0; parser->tank[i].endpressure = 0; } @@ -368,6 +371,8 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba unsigned int he_previous = 0xFFFFFFFF; unsigned int mode_previous = INVALID; unsigned int divemode = INVALID; + unsigned int tank_previous = INVALID; + unsigned int tank_idx = INVALID; unsigned int firmware = 0; unsigned int apos4 = 0; @@ -502,16 +507,39 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba // Tank Pressure if (samplesize == SZ_SAMPLE_IX3M_APOS4) { + unsigned int id = data[offset + 47] & 0x0F; unsigned int pressure = data[offset + 49]; - if (tank[0].beginpressure == 0 && pressure != 0) { - tank[0].beginpressure = pressure; - ntanks = 1; + + // Get the index of the tank. + if (id != tank_previous) { + unsigned int i = 0; + while (i < ntanks) { + if (id == tank[i].id) + break; + i++; + } + + tank_previous = id; + tank_idx = i; } - if (tank[0].beginpressure) { - sample.pressure.tank = 0; + + // Add a new tank if necessary. + if (tank_idx >= ntanks && pressure != 0) { + if (tank_idx >= NTANKS) { + ERROR (abstract->context, "Maximum number of tanks reached."); + return DC_STATUS_DATAFORMAT; + } + tank[tank_idx].id = id; + tank[tank_idx].beginpressure = pressure; + tank[tank_idx].endpressure = pressure; + ntanks = tank_idx + 1; + } + + if (tank_idx < ntanks) { + sample.pressure.tank = tank_idx; sample.pressure.value = pressure; if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - tank[0].endpressure = pressure; + tank[tank_idx].endpressure = pressure; } } From 88296194738b2c827c3698ee9133a19bef212d0e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 28 Aug 2019 23:19:11 +0200 Subject: [PATCH 3/5] Take the tank transmitter flags into account Suppress the tank pressure sample when there is no active transmitter available, or the connection with the transmitter is (temporary) lost. In the latter case, the pressure is recorded as zero. --- src/divesystem_idive_parser.c | 64 +++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index bba5d51..7325b0b 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -508,38 +508,50 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba // Tank Pressure if (samplesize == SZ_SAMPLE_IX3M_APOS4) { unsigned int id = data[offset + 47] & 0x0F; + unsigned int flags = data[offset + 47] & 0xF0; unsigned int pressure = data[offset + 49]; - // Get the index of the tank. - if (id != tank_previous) { - unsigned int i = 0; - while (i < ntanks) { - if (id == tank[i].id) - break; - i++; + if (flags & 0x80) { + // No active transmitter available + } else if (flags & 0x40) { + // Transmitter connection lost + sample.event.type = SAMPLE_EVENT_TRANSMITTER; + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = 0; + if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + } else { + // Get the index of the tank. + if (id != tank_previous) { + unsigned int i = 0; + while (i < ntanks) { + if (id == tank[i].id) + break; + i++; + } + + tank_previous = id; + tank_idx = i; } - tank_previous = id; - tank_idx = i; - } - - // Add a new tank if necessary. - if (tank_idx >= ntanks && pressure != 0) { - if (tank_idx >= NTANKS) { - ERROR (abstract->context, "Maximum number of tanks reached."); - return DC_STATUS_DATAFORMAT; + // Add a new tank if necessary. + if (tank_idx >= ntanks && pressure != 0) { + if (tank_idx >= NTANKS) { + ERROR (abstract->context, "Maximum number of tanks reached."); + return DC_STATUS_DATAFORMAT; + } + tank[tank_idx].id = id; + tank[tank_idx].beginpressure = pressure; + tank[tank_idx].endpressure = pressure; + ntanks = tank_idx + 1; } - tank[tank_idx].id = id; - tank[tank_idx].beginpressure = pressure; - tank[tank_idx].endpressure = pressure; - ntanks = tank_idx + 1; - } - if (tank_idx < ntanks) { - sample.pressure.tank = tank_idx; - sample.pressure.value = pressure; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); - tank[tank_idx].endpressure = pressure; + if (tank_idx < ntanks) { + sample.pressure.tank = tank_idx; + sample.pressure.value = pressure; + if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + tank[tank_idx].endpressure = pressure; + } } } From d62674a8030a49f03b4356dd091ff02720599007 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Aug 2019 15:25:26 -0700 Subject: [PATCH 4/5] Add support for Aqualung i200c It's exactly the same as the regular i200, but has a new version number and string. Tested-by: Tiago Thedim Dias Signed-off-by: Linus Torvalds --- src/descriptor.c | 1 + src/oceanic_atom2.c | 1 + src/oceanic_atom2_parser.c | 14 +++++++++----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index 73f9e62..3495acd 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -237,6 +237,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Aqualung", "i550", DC_FAMILY_OCEANIC_ATOM2, 0x4642, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i200", DC_FAMILY_OCEANIC_ATOM2, 0x4646, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i300C", DC_FAMILY_OCEANIC_ATOM2, 0x4648, DC_TRANSPORT_SERIAL, NULL}, + {"Aqualung", "i200C", DC_FAMILY_OCEANIC_ATOM2, 0x4649, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x464E, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i770R", DC_FAMILY_OCEANIC_ATOM2, 0x4651, DC_TRANSPORT_SERIAL, NULL}, {"Aqualung", "i550C", DC_FAMILY_OCEANIC_ATOM2, 0x4652, DC_TRANSPORT_SERIAL, NULL}, diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 8aed308..88d8c54 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -112,6 +112,7 @@ static const oceanic_common_version_t oceanic_atom2a_version[] = { {"OCEGEO20 \0\0 512K"}, {"OCE GEO R\0\0 512K"}, {"AQUAI200 \0\0 512K"}, + {"AQUA200C \0\0 512K"}, }; static const oceanic_common_version_t oceanic_atom2b_version[] = { diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index da2ba0f..7a517d0 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -88,6 +88,7 @@ #define I550 0x4642 #define I200 0x4646 #define I300C 0x4648 +#define I200C 0x4649 #define I100 0x464E #define I770R 0x4651 #define I550C 0x4652 @@ -162,7 +163,8 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned model == A300 || model == MANTA || model == INSIGHT2 || model == ZEN || model == I300 || model == I550 || - model == I200 || model == I300C) { + model == I200 || model == I200C || + model == I300C) { parser->headersize -= PAGESIZE; } else if (model == VT4 || model == VT41) { parser->headersize += PAGESIZE; @@ -281,6 +283,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim case INSIGHT2: case I300: case I200: + case I200C: case I100: case I300C: datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000; @@ -718,7 +721,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == GEO || parser->model == GEO20 || parser->model == MANTA || parser->model == I300 || parser->model == I200 || parser->model == I100 || - parser->model == I300C || parser->model == TALIS) { + parser->model == I300C || parser->model == TALIS || + parser->model == I200C) { have_pressure = 0; } @@ -876,7 +880,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == OCI || parser->model == A300 || parser->model == I450T || parser->model == I300 || parser->model == I200 || parser->model == I100 || - parser->model == I300C) { + parser->model == I300C || parser->model == I200C) { temperature = data[offset + 3]; } else if (parser->model == OCS || parser->model == TX1) { temperature = data[offset + 1]; @@ -948,7 +952,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == OCI || parser->model == A300 || parser->model == I450T || parser->model == I300 || parser->model == I200 || parser->model == I100 || - parser->model == I300C) + parser->model == I300C || parser->model == I200C) depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF; else if (parser->model == ATOM1) depth = data[offset + 3] * 16; @@ -1001,7 +1005,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == OC1A || parser->model == OC1B || parser->model == OC1C || parser->model == OCI || parser->model == I100 || parser->model == I300C || - parser->model == I450T) { + parser->model == I450T || parser->model == I200C) { decostop = (data[offset + 7] & 0xF0) >> 4; decotime = array_uint16_le(data + offset + 6) & 0x0FFF; have_deco = 1; From 912eb37ac3e560443ef7e72a3646dd9178da2d4f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 3 Sep 2019 16:26:40 +0200 Subject: [PATCH 5/5] Discard the cached BLE packet When using a BLE connection, it's not sufficient to purge the buffers of the underlying I/O stream. The locally cached BLE packet needs to be discarded also. --- src/mares_iconhd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index bb318e1..2a714a4 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -327,6 +327,8 @@ mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char comman // Discard any garbage bytes. dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT); + device->available = 0; + device->offset = 0; } return DC_STATUS_SUCCESS;