From 2e26ae47087eef59ad954660e5de0a0af9da1e52 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 18 Jul 2016 15:54:53 +0900 Subject: [PATCH] Make the tank "type" field more useful Right now it only has an indication of whether the cylinder size is imperial or metric, which is frankly quite useless. Turn it into a bitmask instead, where we keep the imperial/metric data for compatibility, but add another two bits that say that it's a CC cylinder, and whether it's the oxygen or diluent cylinder. Signed-off-by: Linus Torvalds Signed-off-by: Dirk Hohndel --- include/libdivecomputer/parser.h | 18 ++++++--- src/suunto_eonsteel_parser.c | 69 +++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index 921efdc..111de48 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -146,11 +146,17 @@ typedef struct 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 unsigned int dc_tankinfo_t; +#define DC_TANKINFO_METRIC 1 +#define DC_TANKINFO_IMPERIAL 2 +#define DC_TANKINFO_CC_DILUENT 4 +#define DC_TANKINFO_CC_O2 8 + +// For backwards compatibility +#define DC_TANKVOLUME_NONE 0 +#define DC_TANKVOLUME_METRIC DC_TANKINFO_METRIC +#define DC_TANKVOLUME_IMPERIAL DC_TANKINFO_IMPERIAL + /* * Tank volume @@ -177,7 +183,7 @@ typedef enum dc_tankvolume_t { typedef struct dc_tank_t { unsigned int gasmix; /* Gas mix index, or DC_GASMIX_UNKNOWN */ - dc_tankvolume_t type; /* Tank type */ + dc_tankinfo_t type; /* Tank type - metric/imperial and oc/cc */ double volume; /* Volume (liter) */ double workpressure; /* Work pressure (bar) */ double beginpressure; /* Begin pressure (bar) */ diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index b2fe5d8..04fd2a2 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Wow. MSC is truly crap */ #ifdef _MSC_VER @@ -97,6 +98,7 @@ typedef struct suunto_eonsteel_parser_t { double highsetpoint; double customsetpoint; dc_field_string_t strings[MAXSTRINGS]; + dc_tankinfo_t tankinfo[MAXGASES]; double tanksize[MAXGASES]; double tankworkingpressure[MAXGASES]; } cache; @@ -1007,19 +1009,32 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi field_value(value, eon->cache.divemode); break; case DC_FIELD_TANK: - /* Sadly it seems that the EON Steel doesn't tell us whether we get imperial - * or metric data - the only indication is metric is always whole liters */ + /* + * Sadly it seems that the EON Steel doesn't tell us whether + * we get imperial or metric data - the only indication is + * that metric is (at least so far) always whole liters + */ tank->volume = eon->cache.tanksize[flags]; - if (eon->cache.tanksize[flags] - (int)eon->cache.tanksize[flags] < 0.001) { - tank->type = DC_TANKVOLUME_METRIC; - tank->workpressure = 0; - } else { - /* the pressure reported is NOT the pressure the user enters. - * So 3000psi turns into 206.700 bar instead of 206.843 bar; - * We report it as we get it and let the application figure out - * what to do with that */ - tank->type = DC_TANKVOLUME_IMPERIAL; - tank->workpressure = eon->cache.tankworkingpressure[flags]; + + /* + * The pressure reported is NOT the pressure the user enters. + * + * So 3000psi turns into 206.700 bar instead of 206.843 bar; + * We report it as we get it and let the application figure out + * what to do with that + */ + tank->workpressure = eon->cache.tankworkingpressure[flags]; + tank->type = eon->cache.tankinfo[flags]; + + /* + * See if we should call this imperial instead. + * + * We need to have workpressure and a valid tank. In that case, + * a fractional tank size implies imperial. + */ + if (tank->workpressure && (tank->type & DC_TANKINFO_METRIC)) { + if (fabs(tank->volume - rint(tank->volume)) > 0.001) + tank->type += DC_TANKINFO_IMPERIAL - DC_TANKINFO_METRIC; } break; case DC_FIELD_STRING: @@ -1069,10 +1084,36 @@ static void set_depth_field(suunto_eonsteel_parser_t *eon, unsigned short d) // Two versions so far: // "enum:0=Off,1=Primary,2=?,3=Diluent" // "enum:0=Off,1=Primary,3=Diluent,4=Oxygen" +// +// We turn that into the DC_TANKINFO data here, but +// initially consider all non-off tanks to me METRIC. +// +// We may later turn the METRIC tank size into IMPERIAL if we +// get a working pressure and non-integral size static int add_gas_type(suunto_eonsteel_parser_t *eon, const struct type_desc *desc, unsigned char type) { - if (eon->cache.ngases < MAXGASES) - eon->cache.ngases++; + int idx = eon->cache.ngases; + dc_tankinfo_t tankinfo = DC_TANKINFO_METRIC; + + if (idx >= MAXGASES) + return 0; + + eon->cache.ngases = idx+1; + switch (type) { + case 0: + tankinfo = 0; + break; + case 3: + tankinfo |= DC_TANKINFO_CC_DILUENT; + break; + case 4: + tankinfo |= DC_TANKINFO_CC_O2; + break; + default: + break; + } + eon->cache.tankinfo[idx] = tankinfo; + eon->cache.initialized |= 1 << DC_FIELD_GASMIX_COUNT; eon->cache.initialized |= 1 << DC_FIELD_TANK_COUNT; return 0;