[PATCH 2/3] Do more dive fixup for each dive computer

Linus Torvalds torvalds at linux-foundation.org
Fri Feb 8 16:49:49 PST 2013


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Sat, 9 Feb 2013 11:15:18 +1100
Subject: [PATCH 2/3] Do more dive fixup for each dive computer

In commit b6c9301e5847 ("Move more dive computer filled data to the
divecomputer structure") we moved the fields that get filled in by the
dive computers to be per-divecomputer data structures.

This patch re-creates some of those fields back in the "struct dive",
but now the fields are initialized to be a reasonable average from the
dive computer data.  We already did some of this for the temperature
min/max fields for the statistics, so this just continues that trend.

The goal is to make it easy to look at "dive values" without having to
iterate over dive computers every time you do.  Just do it once in
"fixup_dive()" instead.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

This changes the surface-pressure and water salinity to be precalculated. 
Not that we can't loop over the dive computers, but it's what we do with 
the other fields, so this is a bit more consistent, I think.

 dive.c     | 55 ++++++++++++++++++++++++++++++++++---------------------
 dive.h     | 46 ++++++++++++++++++++++++++++++++++------------
 divelist.c |  6 +++---
 planner.c  |  8 ++++----
 profile.c  | 14 +++++++-------
 save-xml.c |  2 +-
 uemis.c    |  4 ++--
 7 files changed, 85 insertions(+), 50 deletions(-)

diff --git a/dive.c b/dive.c
index cbee208ec7e6..5d3250728bf6 100644
--- a/dive.c
+++ b/dive.c
@@ -230,27 +230,6 @@ int get_duration_in_sec(struct dive *dive)
 	return duration;
 }
 
-int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null)
-{
-	unsigned int count = 0, sum = 0;
-	const struct divecomputer *dc = &dive->dc;
-
-	do {
-		if (!dc->surface_pressure.mbar)
-			continue;
-		sum += dc->surface_pressure.mbar;
-		count++;
-	} while ((dc = dc->next) != NULL);
-
-	/* Did we have any dive computers with surface pressure information */
-	if (count)
-		return (sum + count/2) / count;
-
-	if (non_null)
-		return SURFACE_PRESSURE;
-	return 0;
-}
-
 static void update_temperature(temperature_t *temperature, int new)
 {
 	if (new) {
@@ -445,6 +424,36 @@ static struct event *find_previous_event(struct divecomputer *dc, struct event *
 	return previous;
 }
 
+static void fixup_surface_pressure(struct dive *dive)
+{
+	struct divecomputer *dc;
+	int sum, nr;
+
+	for_each_dc(dive, dc) {
+		if (dc->surface_pressure.mbar) {
+			sum += dc->surface_pressure.mbar;
+			nr++;
+		}
+	}
+	if (nr)
+		dive->surface_pressure.mbar = (sum + nr/2)/nr;
+}
+
+static void fixup_water_salinity(struct dive *dive)
+{
+	struct divecomputer *dc;
+	int sum, nr;
+
+	for_each_dc(dive, dc) {
+		if (dc->salinity) {
+			sum += dc->salinity;
+			nr++;
+		}
+	}
+	if (nr)
+		dive->salinity = (sum + nr/2)/nr;
+}
+
 /* right now this only operates on the first divecomputer */
 struct dive *fixup_dive(struct dive *dive)
 {
@@ -466,6 +475,10 @@ struct dive *fixup_dive(struct dive *dive)
 	add_suit(dive->suit);
 	sanitize_cylinder_info(dive);
 	dive->maxcns = dive->cns;
+
+	fixup_water_salinity(dive);
+	fixup_surface_pressure(dive);
+
 	dc = &dive->dc;
 	for (i = 0; i < dc->samples; i++) {
 		struct sample *sample = dc->sample + i;
diff --git a/dive.h b/dive.h
index ddb9327c6514..87c30733d01c 100644
--- a/dive.h
+++ b/dive.h
@@ -20,6 +20,10 @@
 #define SURFACE_PRESSURE_STRING "1013"
 #define ZERO_C_IN_MKELVIN	273150  // mKelvin
 
+/* Salinity is expressed in weight in grams per 10l */
+#define SEAWATER_SALINITY	10300
+#define FRESHWATER_SALINITY	10000
+
 
 /*
  * Some silly typedefs to make our units very explicit.
@@ -314,9 +318,12 @@ struct dive {
 	weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS];
 	char *suit;
 	int sac, otu, cns, maxcns;
+
+	/* Calculated based on dive computer data */
 	temperature_t mintemp, maxtemp;
+	pressure_t surface_pressure;
+	int salinity; // kg per 10000 l
 
-	/* Eventually we'll do multiple dive computers */
 	struct divecomputer dc;
 };
 
@@ -333,22 +340,34 @@ static inline void copy_gps_location(struct dive *from, struct dive *to)
 	}
 }
 
-extern int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null);
+static inline int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null)
+{
+	int mbar = dive->surface_pressure.mbar;
+	if (!mbar && non_null)
+		mbar = SURFACE_PRESSURE;
+	return mbar;
+}
 
 /* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m
  * of water (and use standard salt water at 1.03kg per liter if we don't know salinity)
  * and add that to the surface pressure (or to 1013 if that's unknown) */
-static inline int depth_to_mbar(int depth, struct dive *dive, struct divecomputer *dc)
+static inline int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity)
 {
-	double specific_weight = 1.03 * 0.981;
-	int surface_pressure;
-	if (dc->salinity)
-		specific_weight = dc->salinity / 10000.0 * 0.981;
-	if (dc->surface_pressure.mbar)
-		surface_pressure = dc->surface_pressure.mbar;
-	else
-		surface_pressure = get_surface_pressure_in_mbar(dive, TRUE);
-	return depth / 10.0 * specific_weight + surface_pressure + 0.5;
+	double specific_weight;
+	int mbar = surface_pressure.mbar;
+
+	if (!mbar)
+		mbar = SURFACE_PRESSURE;
+	if (!salinity)
+		salinity = SEAWATER_SALINITY;
+	specific_weight = salinity / 10000.0 * 0.981;
+	mbar += depth / 10.0 * specific_weight + 0.5;
+	return mbar;
+}
+
+static inline int depth_to_mbar(int depth, struct dive *dive)
+{
+	return calculate_depth_to_mbar(depth, dive->surface_pressure, dive->salinity);
 }
 
 /* for the inverse calculation we use just the relative pressure
@@ -468,6 +487,9 @@ static inline struct dive *get_dive(int nr)
 #define for_each_dive(_i,_x) \
 	for ((_i) = 0; ((_x) = get_dive(_i)) != NULL; (_i)++)
 
+#define for_each_dc(_dive,_dc) \
+	for (_dc = &_dive->dc; _dc; _dc = _dc->next)
+
 #define for_each_gps_location(_i,_x) \
 	for ((_i) = 0; ((_x) = get_gps_location(_i, &gps_location_table)) != NULL; (_i)++)
 
diff --git a/divelist.c b/divelist.c
index 97981a0f26b6..417cb1b7713b 100644
--- a/divelist.c
+++ b/divelist.c
@@ -655,7 +655,7 @@ static int calculate_otu(struct dive *dive)
 			po2 = sample->po2;
 		} else {
 			int o2 = active_o2(dive, dc, sample->time);
-			po2 = o2 / 1000.0 * depth_to_mbar(sample->depth.mm, dive, &dive->dc);
+			po2 = o2 / 1000.0 * depth_to_mbar(sample->depth.mm, dive);
 		}
 		if (po2 >= 500)
 			otu += pow((po2 - 500) / 1000.0, 0.83) * t / 30.0;
@@ -720,7 +720,7 @@ static int calculate_sac(struct dive *dive)
 		}
 	}
 	/* Mean pressure in bar (SAC calculations are in bar*l/min) */
-	pressure = depth_to_mbar(dive->dc.meandepth.mm, dive, &dive->dc) / 1000.0;
+	pressure = depth_to_mbar(dive->dc.meandepth.mm, dive) / 1000.0;
 	sac = airuse / pressure * 60 / duration;
 
 	/* milliliters per minute.. */
@@ -744,7 +744,7 @@ static void add_dive_to_deco(struct dive *dive)
 
 		for (j = t0; j < t1; j++) {
 			int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
-			(void) add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0,
+			(void) add_segment(depth_to_mbar(depth, dive) / 1000.0,
 					   &dive->cylinder[sample->sensor].gasmix, 1, sample->po2, dive);
 		}
 	}
diff --git a/planner.c b/planner.c
index 5bf87fb1e84b..847128866ec6 100644
--- a/planner.c
+++ b/planner.c
@@ -112,7 +112,7 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
 			lastdepth = psample->depth.mm;
 		for (j = t0; j < t1; j++) {
 			int depth = interpolate(lastdepth, sample->depth.mm, j - t0, t1 - t0);
-			tissue_tolerance = add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0,
+			tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0,
 						       &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive);
 		}
 		psample = sample;
@@ -139,7 +139,7 @@ int time_at_last_depth(struct dive *dive, int next_stop, char **cached_data_p)
 	gasidx = get_gasidx(dive, o2, he);
 	while (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) > next_stop) {
 		wait++;
-		tissue_tolerance = add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0,
+		tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0,
 					       &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive);
 	}
 	return wait;
@@ -504,7 +504,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
 		gasidx = get_gasidx(dive, o2, he);
 		len = strlen(buffer);
 		if (dp->depth != lastdepth) {
-			used = diveplan->bottomsac / 1000.0 * depth_to_mbar((dp->depth + lastdepth) / 2, dive, &dive->dc) *
+			used = diveplan->bottomsac / 1000.0 * depth_to_mbar((dp->depth + lastdepth) / 2, dive) *
 						(dp->time - lasttime) / 60;
 			snprintf(buffer + len, sizeof(buffer) - len, _("Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s\n"),
 							decimals, depthvalue, depth_unit,
@@ -514,7 +514,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
 		} else {
 			/* we use deco SAC rate during the calculated deco stops, bottom SAC rate everywhere else */
 			int sac = dp->entered ? diveplan->bottomsac : diveplan->decosac;
-			used = sac / 1000.0 * depth_to_mbar(dp->depth, dive, &dive->dc) * (dp->time - lasttime) / 60;
+			used = sac / 1000.0 * depth_to_mbar(dp->depth, dive) * (dp->time - lasttime) / 60;
 			snprintf(buffer + len, sizeof(buffer) - len, _("Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s\n"),
 							decimals, depthvalue, depth_unit,
 							FRACTION(dp->time - lasttime, 60),
diff --git a/profile.c b/profile.c
index 3f24966e8342..e230ab0ed43a 100644
--- a/profile.c
+++ b/profile.c
@@ -1011,11 +1011,11 @@ static void set_sac_color(struct graphics_context *gc, int sac, int avg_sac)
 }
 
 /* calculate the current SAC in ml/min and convert to int */
-#define GET_LOCAL_SAC(_entry1, _entry2, _dive, _dc)	(int)		\
+#define GET_LOCAL_SAC(_entry1, _entry2, _dive)	(int)		\
 	((GET_PRESSURE((_entry1)) - GET_PRESSURE((_entry2))) *			\
 		(_dive)->cylinder[(_entry1)->cylinderindex].type.size.mliter /	\
 		(((_entry2)->sec - (_entry1)->sec) / 60.0) /			\
-		depth_to_mbar(((_entry1)->depth + (_entry2)->depth) / 2.0, (_dive), (_dc)))
+		depth_to_mbar(((_entry1)->depth + (_entry2)->depth) / 2.0, (_dive)))
 
 #define SAC_WINDOW 45	/* sliding window in seconds for current SAC calculation */
 
@@ -1050,12 +1050,12 @@ static void plot_cylinder_pressure(struct graphics_context *gc, struct plot_info
 		if (!last_entry) {
 			last = i;
 			last_entry = entry;
-			sac = GET_LOCAL_SAC(entry, pi->entry + i + 1, dive, dc);
+			sac = GET_LOCAL_SAC(entry, pi->entry + i + 1, dive);
 		} else {
 			int j;
 			sac = 0;
 			for (j = last; j < i; j++)
-				sac += GET_LOCAL_SAC(pi->entry + j, pi->entry + j + 1, dive, dc);
+				sac += GET_LOCAL_SAC(pi->entry + j, pi->entry + j + 1, dive);
 			sac /= (i - last);
 			if (entry->sec - last_entry->sec >= SAC_WINDOW) {
 				last++;
@@ -1405,7 +1405,7 @@ static inline int pressure_time(struct dive *dive, struct divecomputer *dc, stru
 	int time = b->sec - a->sec;
 	int depth = (a->depth + b->depth)/2;
 
-	return depth_to_mbar(depth, dive, dc) * time;
+	return depth_to_mbar(depth, dive) * time;
 }
 
 static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr)
@@ -1822,7 +1822,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
 		struct plot_data *entry = pi->entry + i;
 		int cylinderindex = entry->cylinderindex;
 
-		amb_pressure = depth_to_mbar(entry->depth, dive, dc) / 1000.0;
+		amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0;
 		fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille ? : O2_IN_AIR;
 		fhe = dive->cylinder[cylinderindex].gasmix.he.permille;
 		double ratio = (double)fhe / (1000.0 - fo2);
@@ -1876,7 +1876,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
 		tissue_tolerance = 0;
 		for (j = t0+1; j <= t1; j++) {
 			int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
-			double min_pressure = add_segment(depth_to_mbar(depth, dive, dc) / 1000.0,
+			double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0,
 							&dive->cylinder[cylinderindex].gasmix, 1, entry->po2 * 1000, dive);
 			tissue_tolerance = min_pressure;
 		}
diff --git a/save-xml.c b/save-xml.c
index b95a38028aef..22059a17855c 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -172,7 +172,7 @@ static void save_airpressure(FILE *f, struct divecomputer *dc)
 static void save_salinity(FILE *f, struct divecomputer *dc)
 {
 	/* only save if we have a value that isn't the default of sea water */
-	if (!dc->salinity || dc->salinity == 10300)
+	if (!dc->salinity || dc->salinity == SEAWATER_SALINITY)
 		return;
 	fputs("  <water", f);
 	show_salinity(f, dc->salinity, " salinity='", "'");
diff --git a/uemis.c b/uemis.c
index 026c836dfec1..aad76c10f405 100644
--- a/uemis.c
+++ b/uemis.c
@@ -300,9 +300,9 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
 	dive->dc.airtemp.mkelvin = *(uint16_t *)(data + 45) * 100 + ZERO_C_IN_MKELVIN;
 	dive->dc.surface_pressure.mbar = *(uint16_t *)(data + 43);
 	if (*(uint8_t *)(data + 19))
-		dive->dc.salinity = 10300; /* avg grams per 10l sea water */
+		dive->dc.salinity = SEAWATER_SALINITY; /* avg grams per 10l sea water */
 	else
-		dive->dc.salinity = 10000; /* grams per 10l fresh water */
+		dive->dc.salinity = FRESHWATER_SALINITY; /* grams per 10l fresh water */
 
 	/* this will allow us to find the last dive read so far from this computer */
 	dc->model = strdup("Uemis Zurich");
-- 
1.8.1.3.535.ga923c31



More information about the subsurface mailing list