diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index 19fbf99..b64400e 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -82,6 +83,9 @@ typedef struct suunto_eonsteel_parser_t { dc_gasmix_t gasmix[MAXGASES]; dc_salinity_t salinity; double surface_pressure; + dc_tankvolume_t tankinfo[MAXGASES]; + double tanksize[MAXGASES]; + double tankworkingpressure[MAXGASES]; } cache; } suunto_eonsteel_parser_t; @@ -879,6 +883,8 @@ suunto_eonsteel_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback static dc_status_t suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value) { + dc_tank_t *tank = (dc_tank_t *) value; + suunto_eonsteel_parser_t *eon = (suunto_eonsteel_parser_t *)parser; if (!(eon->cache.initialized >> type)) @@ -895,6 +901,7 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi field_value(value, eon->cache.avgdepth); break; case DC_FIELD_GASMIX_COUNT: + case DC_FIELD_TANK_COUNT: field_value(value, eon->cache.ngases); break; case DC_FIELD_GASMIX: @@ -908,6 +915,35 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi case DC_FIELD_ATMOSPHERIC: field_value(value, eon->cache.surface_pressure); 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 + * that metric is (at least so far) always whole liters + */ + tank->volume = eon->cache.tanksize[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_TANKVOLUME_METRIC)) { + if (fabs(tank->volume - rint(tank->volume)) > 0.001) + tank->type = DC_TANKVOLUME_IMPERIAL; + } + break; default: return DC_STATUS_UNSUPPORTED; } @@ -953,10 +989,30 @@ 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_TANKVOLUME 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_tankvolume_t tankinfo = DC_TANKVOLUME_METRIC; + + if (idx >= MAXGASES) + return 0; + + eon->cache.ngases = idx+1; + switch (type) { + case 0: + tankinfo = 0; + break; + default: + break; + } + eon->cache.tankinfo[idx] = tankinfo; + eon->cache.initialized |= 1 << DC_FIELD_GASMIX_COUNT; return 0; } @@ -983,6 +1039,22 @@ static int add_gas_he(suunto_eonsteel_parser_t *eon, unsigned char he) return 0; } +static int add_gas_size(suunto_eonsteel_parser_t *eon, float l) +{ + int idx = eon->cache.ngases-1; + if (idx >= 0) + eon->cache.tanksize[idx] = l; + return 0; +} + +static int add_gas_workpressure(suunto_eonsteel_parser_t *eon, float wp) +{ + int idx = eon->cache.ngases-1; + if (idx >= 0) + eon->cache.tankworkingpressure[idx] = wp; + return 0; +} + static float get_le32_float(const unsigned char *src) { union { @@ -1066,6 +1138,12 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty if (!strcmp(name, "Gases.Gas.Helium")) return add_gas_he(eon, data[0]); + if (!strcmp(name, "Gases.Gas.TankSize")) + return add_gas_size(eon, get_le32_float(data)); + + if (!strcmp(name, "Gases.Gas.TankFillPressure")) + return add_gas_workpressure(eon, get_le32_float(data)); + if (!strcmp(name, "SurfacePressure")) { unsigned int pressure = array_uint32_le(data); // in SI units - Pascal eon->cache.surface_pressure = pressure / 100000.0; // bar