summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2013-02-09 11:15:18 +1100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-08 18:22:30 -0800
commit926fcef2a1e83b58c37c948a3f1a904aa0be0d0e (patch)
tree7f759284b78c77beecb2a11bae25649122f2690a
parentb286ea638c8ce468cf9c1a1b5037867acb5d6fe4 (diff)
downloadsubsurface-926fcef2a1e83b58c37c948a3f1a904aa0be0d0e.tar.gz
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@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--dive.c55
-rw-r--r--dive.h46
-rw-r--r--divelist.c6
-rw-r--r--planner.c8
-rw-r--r--profile.c14
-rw-r--r--save-xml.c2
-rw-r--r--uemis.c4
7 files changed, 85 insertions, 50 deletions
diff --git a/dive.c b/dive.c
index cbee208ec..5d3250728 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 ddb9327c6..87c30733d 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 97981a0f2..417cb1b77 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 5bf87fb1e..847128866 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 3f24966e8..e230ab0ed 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 b95a38028..22059a178 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 026c836df..aad76c10f 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");