[PATCH 2/2] Fix cylinder end pressure fixup from samples

Linus Torvalds torvalds at linux-foundation.org
Fri Apr 1 13:36:40 PDT 2016


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Fri, 1 Apr 2016 15:23:55 -0500
Subject: [PATCH 2/2] Fix cylinder end pressure fixup from samples

This bug admittedly hits almost nobody, but if you had multiple cylinder
pressure sensors on the same cylinder (attached to multiple dive
computers, of course), we would take the beginning pressure from the
first dive computer, and the ending pressure from the last dive
computer.

That came about because we'd just walk all the dive computer samples in
order, and the first time we see a relevant sample and we don't have a
beginning pressure, we'd take that pressure.  So the beginning pressure
was from the first dive computer, and once we'd seen a valid beginning
pressure, that would never change.

But as we're walking along, we'd continue to update the ending pressure
from the last relevant sample we see, which means that as we go on to
look at the other dive computers, we'd continue to update the ending
pressure with data from them.

And mixing beginning/ending pressures from two different sensors just
does not make sense.

This changes the logic to be the same for beginning and ending
pressures: we only update it once, with the first relevant sample we
see.  But we walk the samples twice: forwards frm the beginning to find
the first beginning pressure, and backwards from the end to find the
ending pressure.

That means that as we move on to the second dive computer, we've now
filled in the ending pressure from the first one, and will no longer
update it any more.

NOTE! We don't stop scanning the samples (or the dive computers) just
because we've found a valid pressure value.  We'll always walk all the
samples because there might be multiple different cylinders that get
pressure data from different samples (and different dive computers).

We could have some early-out logic when we've filled in all relevant
cylinders, but since this just runs once per dive it's not worth it.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
 subsurface-core/dive.c | 94 +++++++++++++++++++++++++++-----------------------
 1 file changed, 51 insertions(+), 43 deletions(-)

diff --git a/subsurface-core/dive.c b/subsurface-core/dive.c
index 6ee002e1f8f1..12154704f5d8 100644
--- a/subsurface-core/dive.c
+++ b/subsurface-core/dive.c
@@ -798,45 +798,6 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me
 	}
 }
 
-static void fixup_pressure(struct dive *dive, struct sample *sample, enum cylinderuse cyl_use)
-{
-	int pressure, index;
-	cylinder_t *cyl;
-
-	if (cyl_use != OXYGEN) {
-		pressure = sample->cylinderpressure.mbar;
-		index = sample->sensor;
-	} else {	// for the CCR oxygen cylinder:
-		pressure = sample->o2cylinderpressure.mbar;
-		index = get_cylinder_idx_by_use(dive, OXYGEN);
-	}
-	if (index < 0)
-		return;
-	if (!pressure)
-		return;
-
-	/*
-	 * Ignore surface samples for tank pressure information.
-	 *
-	 * At the beginning of the dive, let the cylinder cool down
-	 * if the diver starts off at the surface. And at the end
-	 * of the dive, there may be surface pressures where the
-	 * diver has already turned off the air supply (especially
-	 * for computers like the Uemis Zurich that end up saving
-	 * quite a bit of samples after the dive has ended).
-	 */
-	if (sample->depth.mm < SURFACE_THRESHOLD)
-		return;
-
-	/* FIXME! sensor -> cylinder mapping? */
-	if (index >= MAX_CYLINDERS)
-		return;
-	cyl = dive->cylinder + index;
-	if (!cyl->sample_start.mbar)
-		cyl->sample_start.mbar = pressure;
-	cyl->sample_end.mbar = pressure;
-}
-
 static void update_min_max_temperatures(struct dive *dive, temperature_t temperature)
 {
 	if (temperature.mkelvin) {
@@ -1419,18 +1380,65 @@ static void simplify_dc_pressures(struct dive *dive, struct divecomputer *dc)
 	}
 }
 
+/* FIXME! sensor -> cylinder mapping? */
+static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
+{
+	if (idx >= 0 && idx < MAX_CYLINDERS) {
+		cylinder_t *cyl = dive->cylinder + idx;
+		if (p.mbar && !cyl->sample_start.mbar)
+			cyl->sample_start = p;
+	}
+}
+
+static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
+{
+	if (idx >= 0 && idx < MAX_CYLINDERS) {
+		cylinder_t *cyl = dive->cylinder + idx;
+		if (p.mbar && !cyl->sample_end.mbar)
+			cyl->sample_end = p;
+	}
+}
+
 /*
  * Check the cylinder pressure sample information and fill in the
  * overall cylinder pressures from those.
+ *
+ * We ignore surface samples for tank pressure information.
+ *
+ * At the beginning of the dive, let the cylinder cool down
+ * if the diver starts off at the surface. And at the end
+ * of the dive, there may be surface pressures where the
+ * diver has already turned off the air supply (especially
+ * for computers like the Uemis Zurich that end up saving
+ * quite a bit of samples after the dive has ended).
  */
 static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
 {
-	int i;
+	int i, o2index = -1;
+
+	if (dive->dc.divemode == CCR)
+		o2index = get_cylinder_idx_by_use(dive, OXYGEN);
+
+	/* Walk the samples from the beginning to find starting pressures.. */
 	for (i = 0; i < dc->samples; i++) {
 		struct sample *sample = dc->sample + i;
-		fixup_pressure(dive, sample, OC_GAS);
-		if (dive->dc.divemode == CCR)
-			fixup_pressure(dive, sample, OXYGEN);
+
+		if (sample->depth.mm < SURFACE_THRESHOLD)
+			continue;
+
+		fixup_start_pressure(dive, sample->sensor, sample->cylinderpressure);
+		fixup_start_pressure(dive, o2index, sample->o2cylinderpressure);
+	}
+
+	/* ..and from the end for ending pressures */
+	for (i = dc->samples; --i >= 0; ) {
+		struct sample *sample = dc->sample + i;
+
+		if (sample->depth.mm < SURFACE_THRESHOLD)
+			continue;
+
+		fixup_end_pressure(dive, sample->sensor, sample->cylinderpressure);
+		fixup_end_pressure(dive, o2index, sample->o2cylinderpressure);
 	}
 
 	simplify_dc_pressures(dive, dc);
-- 
2.8.0.rc4.303.g3931579



More information about the subsurface mailing list