summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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");