diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index f1f73bd..774e5e3 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -149,13 +149,36 @@ typedef enum dc_tankvolume_t { DC_TANKVOLUME_IMPERIAL, } dc_tankvolume_t; +/* + * Tank volume + * + * There are two different ways to specify the volume of a tank. In the + * metric system, the tank volume is specified as the water capacity, + * while in the imperial system the tank volume is specified as the air + * capacity at the surface (1 ATM) when the tank is filled at its + * working pressure. Libdivecomputer will always convert the tank volume + * to the metric representation, and indicate the original tank type: + * + * DC_TANKVOLUME_NONE: Tank volume is not available. Both the volume and + * workpressure will be zero. + * + * DC_TANKVOLUME_METRIC: A metric tank. The workpressure is optional and + * may be zero. + * + * DC_TANKVOLUME_IMPERIAL: An imperial tank. Both the volume and + * workpressure are mandatory and always non-zero. The volume has been + * converted from air capacity to water capacity. To calculate the + * original air capacity again, multiply with the workpressure and + * divide by 1 ATM (Vair = Vwater * Pwork / Patm). + */ + 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; + unsigned int gasmix; /* Gas mix index, or DC_GASMIX_UNKNOWN */ + dc_tankvolume_t type; /* Tank type */ + double volume; /* Volume (liter) */ + double workpressure; /* Work pressure (bar) */ + double beginpressure; /* Begin pressure (bar) */ + double endpressure; /* End pressure (bar) */ } dc_tank_t; typedef union dc_sample_value_t { diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index 7a53746..83bcfc7 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -158,6 +158,8 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un else atmospheric = array_uint16_le (p + 0x26) * BAR / 1000.0; + unsigned int workpressure = 0; + if (value) { switch (type) { case DC_FIELD_DIVETIME: @@ -183,9 +185,13 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un switch (p[2]) { case 1: // Cuft at psi case 2: // Cuft at bar + workpressure = array_uint16_le(p + 10); + if (workpressure == 0) + return DC_STATUS_DATAFORMAT; tank->type = DC_TANKVOLUME_IMPERIAL; tank->volume = array_uint16_le(p + 8) * CUFT * 1000.0; - tank->workpressure = array_uint16_le(p + 10) * PSI / BAR; + tank->volume /= workpressure * PSI / ATM; + tank->workpressure = workpressure * PSI / BAR; break; case 3: // Wet volume in 1/10 liter tank->type = DC_TANKVOLUME_METRIC;