diff --git a/src/array.c b/src/array.c index 29f5faf..f47c3eb 100644 --- a/src/array.c +++ b/src/array.c @@ -404,3 +404,14 @@ signextend (unsigned int value, unsigned int nbits) else return value & mask; } + +unsigned int +popcount (unsigned int value) +{ + unsigned int count = 0; + while (value) { + value &= value - 1; + count++; + } + return count; +} diff --git a/src/array.h b/src/array.h index a6ef21e..fab1475 100644 --- a/src/array.h +++ b/src/array.h @@ -126,6 +126,9 @@ dec2bcd (unsigned char value); unsigned int signextend (unsigned int value, unsigned int nbits); +unsigned int +popcount (unsigned int value); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index b6aa7e2..fc06b66 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -118,6 +118,7 @@ typedef struct shearwater_predator_tank_t { unsigned int pressure_reserve; unsigned int serial; char name[2]; + dc_usage_t usage; } shearwater_predator_tank_t; struct shearwater_predator_parser_t { @@ -140,6 +141,7 @@ struct shearwater_predator_parser_t { shearwater_predator_tank_t tank[NTANKS]; unsigned int tankidx[NTANKS]; unsigned int aimode; + unsigned int hpccr; unsigned int calibrated; double calibration[3]; unsigned int divemode; @@ -179,6 +181,12 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = { }; +static unsigned int +shearwater_predator_is_ccr (unsigned int divemode) +{ + return divemode == M_CC || divemode == M_CC2 || divemode == M_SC; +} + static unsigned int shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil) { @@ -248,9 +256,11 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, const parser->tank[i].pressure_reserve = 0; parser->tank[i].serial = 0; memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name)); + parser->tank[i].usage = DC_USAGE_NONE; parser->tankidx[i] = i; } parser->aimode = AI_OFF; + parser->hpccr = 0; parser->calibrated = 0; for (unsigned int i = 0; i < 3; ++i) { parser->calibration[i] = 0.0; @@ -379,6 +389,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) shearwater_predator_tank_t tank[NTANKS] = {0}; unsigned int o2_previous = UNDEFINED, he_previous = UNDEFINED, dil_previous = UNDEFINED; unsigned int aimode = AI_OFF; + unsigned int hpccr = 0; if (!pnf) { for (unsigned int i = 0; i < NFIXED; ++i) { gasmix[i].oxygen = data[20 + i]; @@ -490,8 +501,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) tank[id].enabled = 1; tank[id].beginpressure = pressure; tank[id].endpressure = pressure; - tank[id].name[0] = i == 0 ? 'D': 'O'; - tank[id].name[1] = 0; + tank[id].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN; + hpccr = 1; } tank[id].endpressure = pressure; } @@ -535,9 +546,17 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) if (aimode == AI_HPCCR) { for (unsigned int i = 0; i < 2; ++i) { tank[4 + i].enabled = 1; - tank[4 + i].name[0] = i == 0 ? 'D': 'O'; - tank[4 + i].name[1] = 0; + tank[4 + i].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN; } + hpccr = 1; + } + } + } + unsigned int gtrmode = data[offset + 29]; + if (popcount(gtrmode) >= 2) { + for (unsigned int i = 0; i < 4; ++i) { + if (gtrmode & (1 << i)) { + tank[i].usage = DC_USAGE_SIDEMOUNT; } } } @@ -659,8 +678,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) for (unsigned int i = 0; i < ngasmixes; ++i) { if (gasmix[i].oxygen == 0 && gasmix[i].helium == 0) continue; - if (gasmix[i].diluent && - (divemode != M_CC && divemode != M_CC2 && divemode != M_SC)) + if (gasmix[i].diluent && !shearwater_predator_is_ccr (divemode)) continue; parser->gasmix[parser->ngasmixes] = gasmix[i]; parser->ngasmixes++; @@ -677,6 +695,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) } } parser->aimode = aimode; + parser->hpccr = hpccr; parser->divemode = divemode; parser->units = data[parser->opening[0] + 8]; parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47)); @@ -741,21 +760,20 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ tank->beginpressure = parser->tank[flags].beginpressure * 2 * PSI / BAR; tank->endpressure = parser->tank[flags].endpressure * 2 * PSI / BAR; tank->gasmix = DC_GASMIX_UNKNOWN; - switch (parser->tank[flags].name[0]) { - case 'S': - tank->usage = DC_USAGE_SIDEMOUNT; - break; - case 'O': - tank->usage = DC_USAGE_OXYGEN; - break; - case 'D': - tank->usage = DC_USAGE_DILUENT; - break; - case 'T': - case 'B': - default: - tank->usage = DC_USAGE_NONE; - break; + if (shearwater_predator_is_ccr (parser->divemode) && !parser->hpccr) { + switch (parser->tank[flags].name[0]) { + case 'O': + tank->usage = DC_USAGE_OXYGEN; + break; + case 'D': + tank->usage = DC_USAGE_DILUENT; + break; + default: + tank->usage = DC_USAGE_NONE; + break; + } + } else { + tank->usage = parser->tank[flags].usage; } break; case DC_FIELD_SALINITY: