diff --git a/examples/universal.c b/examples/universal.c index 9d07088..2f5d616 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -426,6 +426,47 @@ doparse (FILE *fp, dc_device_t *device, const unsigned char data[], unsigned int gasmix.nitrogen * 100.0); } + // Parse the tanks. + message ("Parsing the tanks.\n"); + unsigned int ntanks = 0; + rc = dc_parser_get_field (parser, DC_FIELD_TANK_COUNT, 0, &ntanks); + if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { + WARNING ("Error parsing the tank count."); + dc_parser_destroy (parser); + return rc; + } + + for (unsigned int i = 0; i < ntanks; ++i) { + const char *names[] = {"none", "metric", "imperial"}; + + dc_tank_t tank = {0}; + rc = dc_parser_get_field (parser, DC_FIELD_TANK, i, &tank); + if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) { + WARNING ("Error parsing the tank."); + dc_parser_destroy (parser); + return rc; + } + + fprintf (fp, "\n"); + if (tank.gasmix != DC_GASMIX_UNKNOWN) { + fprintf (fp, + " %u\n", + tank.gasmix); + } + if (tank.type != DC_TANKVOLUME_NONE) { + fprintf (fp, + " %s\n" + " %.1f\n" + " %.2f\n", + names[tank.type], tank.volume, tank.workpressure); + } + fprintf (fp, + " %.2f\n" + " %.2f\n" + "\n", + tank.beginpressure, tank.endpressure); + } + // Parse the salinity. message ("Parsing the salinity.\n"); dc_salinity_t salinity = {DC_WATER_FRESH, 0.0}; diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index 526173a..63dc113 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -56,7 +56,9 @@ typedef enum dc_field_type_t { DC_FIELD_ATMOSPHERIC, DC_FIELD_TEMPERATURE_SURFACE, DC_FIELD_TEMPERATURE_MINIMUM, - DC_FIELD_TEMPERATURE_MAXIMUM + DC_FIELD_TEMPERATURE_MAXIMUM, + DC_FIELD_TANK_COUNT, + DC_FIELD_TANK } dc_field_type_t; typedef enum parser_sample_event_t { @@ -131,6 +133,23 @@ typedef struct dc_gasmix_t { double nitrogen; } dc_gasmix_t; +#define DC_GASMIX_UNKNOWN 0xFFFFFFFF + +typedef enum dc_tankvolume_t { + DC_TANKVOLUME_NONE, + DC_TANKVOLUME_METRIC, + DC_TANKVOLUME_IMPERIAL, +} dc_tankvolume_t; + +typedef struct dc_tank_t { + unsigned int gasmix; /* Index of the gas mix, or DC_GASMIX_UNKNOWN */ + dc_tankvolume_t type; + double volume; /* Wet or air volume (depending on the type) in liter */ + double workpressure; /* Pressure in bar */ + double beginpressure; + double endpressure; +} dc_tank_t; + typedef union dc_sample_value_t { unsigned int time; double depth; diff --git a/include/libdivecomputer/units.h b/include/libdivecomputer/units.h index 0636759..17f4b8c 100644 --- a/include/libdivecomputer/units.h +++ b/include/libdivecomputer/units.h @@ -32,6 +32,7 @@ #define FSW (ATM / 33.0) #define MSW (BAR / 10.0) #define PSI ((POUND * GRAVITY) / (INCH * INCH)) +#define CUFT (FEET * FEET * FEET) #endif /* UNITS_H */ diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index fdf918c..f5b1044 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -150,6 +150,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un const unsigned char *p = abstract->data; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; + dc_tank_t *tank = (dc_tank_t *) value; double atmospheric = 0.0; if (parser->atmospheric) @@ -166,6 +167,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un *((double *) value) = (array_uint16_le (p + 0x56) * BAR / 1000.0 - atmospheric) / parser->hydrostatic; break; case DC_FIELD_GASMIX_COUNT: + case DC_FIELD_TANK_COUNT: *((unsigned int *) value) = p[0x2a]; break; case DC_FIELD_GASMIX: @@ -176,6 +178,31 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un case DC_FIELD_TEMPERATURE_SURFACE: *((double *) value) = (p[0x1B] - 32.0) * (5.0 / 9.0); break; + case DC_FIELD_TANK: + p += SZ_HEADER + SZ_GASMIX * flags; + switch (p[2]) { + case 1: // Cuft at psi + tank->type = DC_TANKVOLUME_IMPERIAL; + tank->volume = array_uint16_le(p + 8) * CUFT * 1000.0; + tank->workpressure = array_uint16_le(p + 10) * PSI / BAR; + break; + case 2: // Cuft at bar + tank->type = DC_TANKVOLUME_IMPERIAL; + tank->volume = array_uint16_le(p + 8) * CUFT * 1000.0; + tank->workpressure = array_uint16_le(p + 10); + break; + case 3: // Wet volume in 1/10 liter + tank->type = DC_TANKVOLUME_METRIC; + tank->volume = array_uint16_le(p + 8) / 10.0; + tank->workpressure = 0.0; + break; + default: + return DC_STATUS_DATAFORMAT; + } + tank->gasmix = flags; + tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR; + tank->endpressure = array_uint16_le(p + 14) * PSI / BAR; + break; default: return DC_STATUS_UNSUPPORTED; } diff --git a/src/mares_darwin_parser.c b/src/mares_darwin_parser.c index 183df48..5de4c4b 100644 --- a/src/mares_darwin_parser.c +++ b/src/mares_darwin_parser.c @@ -38,6 +38,7 @@ typedef struct mares_darwin_parser_t mares_darwin_parser_t; struct mares_darwin_parser_t { dc_parser_t base; + unsigned int model; unsigned int headersize; unsigned int samplesize; }; @@ -74,6 +75,8 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i // Initialize the base class. parser_init (&parser->base, context, &mares_darwin_parser_vtable); + parser->model = model; + if (model == DARWINAIR) { parser->headersize = 60; parser->samplesize = 3; @@ -139,6 +142,7 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi const unsigned char *p = abstract->data; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; + dc_tank_t *tank = (dc_tank_t *) value; if (value) { switch (type) { @@ -159,6 +163,25 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed char) p[0x0A]; break; + case DC_FIELD_TANK_COUNT: + if (parser->model == DARWINAIR) { + *((unsigned int *) value) = 1; + } else { + *((unsigned int *) value) = 0; + } + break; + case DC_FIELD_TANK: + if (parser->model == DARWINAIR) { + tank->type = DC_TANKVOLUME_METRIC; + tank->volume = p[0x13] / 10.0; + tank->workpressure = 0.0; + tank->gasmix = 0; + tank->beginpressure = array_uint16_be (p + 0x17); + tank->endpressure = array_uint16_be (p + 0x19); + } else { + return DC_STATUS_UNSUPPORTED; + } + break; default: return DC_STATUS_UNSUPPORTED; }