From 49410c54e98daeb925400bb1cb99cdec018b45f4 Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Tue, 19 May 2026 16:59:13 +1200 Subject: [PATCH] Shearwater: Fix the Sensor and Calibration Display. Don't use ppO2 sensor readings to calculate gas loading when in bailout rebreather mode, and don't show sensor calibration information when the internal ppO2 (setpoint) is used. Signed-off-by: Michael Keller --- src/shearwater_predator_parser.c | 97 +++++++++++++++++--------------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index f8c7b541..03e56eeb 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -76,6 +76,7 @@ #define SETPOINT_HIGH 0x04 #define SC 0x08 #define OC 0x10 +#define SAMPLE_STATUS_BO_CCR 0x20 #define M_CC 0 #define M_OC_TEC 1 @@ -179,6 +180,7 @@ struct shearwater_predator_parser_t { }; struct dc_parser_sensor_calibration_t { + bool external_ppo2_used; double sum_ppo2; double sum_calculated_ppo2; unsigned int ppo2_sample_count; @@ -438,17 +440,22 @@ add_battery_type(shearwater_predator_parser_t *parser, const unsigned char *data } } -static void print_calibration(shearwater_predator_parser_t *parser) +static void add_sensor_state(shearwater_predator_parser_t *parser, bool external_ppo2_used) { - for (size_t i = 0; i < 3; ++i) { - if (parser->calibrated & (1 << i)) { - static const char *names[] = { - "Sensor 1 calibration [bar / V]", - "Sensor 2 calibration [bar / V]", - "Sensor 3 calibration [bar / V]", - }; - dc_field_add_string_fmt(&parser->cache, names[i], "%.2f", parser->calibration[i] * 1000); - } + if (shearwater_predator_is_ccr(parser->divemode)) { + dc_field_add_string(&parser->cache, "ppO2 data source", external_ppo2_used ? "external" : "internal"); + + if (external_ppo2_used) + for (size_t i = 0; i < 3; ++i) { + if (parser->calibrated & (1 << i)) { + static const char *names[] = { + "Sensor 1 calibration [bar / V]", + "Sensor 2 calibration [bar / V]", + "Sensor 3 calibration [bar / V]", + }; + dc_field_add_string_fmt(&parser->cache, names[i], "%.2f", parser->calibration[i] * 1000); + } + } } } @@ -832,9 +839,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) } if (calibration_count > 0) { - if (calibration_default_count < calibration_count) { - print_calibration(parser); - } else { + if (calibration_default_count == calibration_count) { // All calibrated sensors report the default calibration value // so this could be a DiveCAN controller, where the calibration values // are stored in the CCR's sensor module. @@ -930,14 +935,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) break; } - if (parser->needs_divecan_calibration_estimate) { - struct dc_parser_sensor_calibration_t data = { 0 }; - - dc_status_t rc = shearwater_predator_parser_samples_foreach(abstract, NULL, (void *)&data); + struct dc_parser_sensor_calibration_t userdata = { 0 }; + dc_status_t rc = shearwater_predator_parser_samples_foreach(abstract, NULL, (void *)&userdata); - bool calibrated = false; - if (rc == DC_STATUS_SUCCESS && data.sum_ppo2 != 0) { - double calibration = data.sum_calculated_ppo2 / data.sum_ppo2; + bool calibrated = false; + if (parser->needs_divecan_calibration_estimate) { + if (rc == DC_STATUS_SUCCESS && userdata.sum_ppo2 != 0) { + double calibration = userdata.sum_calculated_ppo2 / userdata.sum_ppo2; if (calibration < 0.98 || calibration > 1.02) { // The calibration scaling is significant, use it. calibration *= SENSOR_CALIBRATION_DEFAULT / 100000.0; @@ -951,13 +955,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) } } - if (!calibrated) { - print_calibration(parser); - } - parser->needs_divecan_calibration_estimate = false; } + if (!calibrated) { + add_sensor_state(parser, userdata.external_ppo2_used); + } + static const char *name = "Divemode"; if (divemode == M_OC_REC) { static const char *oc_rec_modes[] = { @@ -1202,38 +1206,41 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal } if (ccr) { - // PPO2 if ((status & PPO2_EXTERNAL) == 0) { double calculated_ppo2 = data[offset + pnf + 6] / 100.0; - if (parser->needs_divecan_calibration_estimate) { + if (userdata) { struct dc_parser_sensor_calibration_t *out = (struct dc_parser_sensor_calibration_t *)userdata; - double ppo2_sum = 0.0; - unsigned int ppo2_count = 0; - if (parser->calibrated & 0x01) { - ppo2_sum += data[offset + pnf + 12] * SENSOR_CALIBRATION_DEFAULT / 100000.0; - ppo2_count++; - } + out->external_ppo2_used = true; - if (parser->calibrated & 0x02) { - ppo2_sum += data[offset + pnf + 14] * SENSOR_CALIBRATION_DEFAULT / 100000.0; - ppo2_count++; - } + if (parser->needs_divecan_calibration_estimate) { + double ppo2_sum = 0.0; + unsigned int ppo2_count = 0; + if (parser->calibrated & 0x01) { + ppo2_sum += data[offset + pnf + 12] * SENSOR_CALIBRATION_DEFAULT / 100000.0; + ppo2_count++; + } - if (parser->calibrated & 0x04) { - ppo2_sum += data[offset + pnf + 15] * SENSOR_CALIBRATION_DEFAULT / 100000.0; - ppo2_count++; - } + if (parser->calibrated & 0x02) { + ppo2_sum += data[offset + pnf + 14] * SENSOR_CALIBRATION_DEFAULT / 100000.0; + ppo2_count++; + } - double ppo2 = ppo2_sum / ppo2_count; + if (parser->calibrated & 0x04) { + ppo2_sum += data[offset + pnf + 15] * SENSOR_CALIBRATION_DEFAULT / 100000.0; + ppo2_count++; + } - out->sum_ppo2 += ppo2; - out->sum_calculated_ppo2 += calculated_ppo2; - out->ppo2_sample_count++; + double ppo2 = ppo2_sum / ppo2_count; + + out->sum_ppo2 += ppo2; + out->sum_calculated_ppo2 += calculated_ppo2; + out->ppo2_sample_count++; + } } - if (callback) { + if ((status & SAMPLE_STATUS_BO_CCR) == 0 && callback) { sample.ppo2.sensor = DC_SENSOR_NONE; sample.ppo2.value = calculated_ppo2; callback(DC_SAMPLE_PPO2, &sample, userdata);