Convert imperial tank volume to the metric system.

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.

To avoid mistakes, the tank volume is now always returned as the metric
volume. For imperial tanks, the tank volume is converted to the metric
representation.
This commit is contained in:
Jef Driesen 2014-11-11 08:48:38 +01:00
parent 71fe683922
commit b2bc231cb4
2 changed files with 36 additions and 7 deletions

View File

@ -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 {

View File

@ -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;