summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2017-07-28 10:35:25 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2017-07-28 21:50:20 -0700
commitdefa71256fe16de32f69e78657c807828b7488bd (patch)
tree91c5e784225375bff7256d9ca885f548b1059480
parent1e337518b81fdcd21b9c2e6efac3cc3ad0667439 (diff)
downloadsubsurface-defa71256fe16de32f69e78657c807828b7488bd.tar.gz
Use the right gasmix for deco calculations
In commit e1b880f4 "Profile support for multiple concurrent pressure sensors" I had mindlessly hacked away at some of the sensor lookups from the plot entries to make it all build, and forgotten about my butchery. Thankfully Jan and Davide noticed in their multi-cylinder deco dives that the deco calculations were no longer correct. This uses the newly introduced "get_gasmix()" helper to look up the currently breathing gasmix, and fixes the deco calculations. Reported-and-tested-by: Jan Mulder <jlmulder@xs4all.nl> Reported-by: Davide DB <dbdavide@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--core/divelist.c7
-rw-r--r--core/profile.c35
2 files changed, 26 insertions, 16 deletions
diff --git a/core/divelist.c b/core/divelist.c
index d51aedf78..60b398539 100644
--- a/core/divelist.c
+++ b/core/divelist.c
@@ -316,10 +316,13 @@ static int calculate_sac(struct dive *dive)
static void add_dive_to_deco(struct dive *dive)
{
struct divecomputer *dc = &dive->dc;
+ struct gasmix *gasmix = NULL;
+ struct event *ev = NULL;
int i;
if (!dc)
return;
+
for (i = 1; i < dc->samples; i++) {
struct sample *psample = dc->sample + i - 1;
struct sample *sample = dc->sample + i;
@@ -329,8 +332,8 @@ 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);
- add_segment(depth_to_bar(depth, dive),
- &dive->cylinder[sample->sensor[0]].gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
+ gasmix = get_gasmix(dive, dc, j, &ev, gasmix);
+ add_segment(depth_to_bar(depth, dive), gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
}
}
}
diff --git a/core/profile.c b/core/profile.c
index 6e216ec04..6e62ac499 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -820,9 +820,8 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc
#ifndef SUBSURFACE_MOBILE
/* calculate DECO STOP / TTS / NDL */
-static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double surface_pressure)
+static void calculate_ndl_tts(struct dive *dive, struct plot_data *entry, struct gasmix *gasmix, double surface_pressure)
{
- int cylinderindex = 0;
/* FIXME: This should be configurable */
/* ascent speed up to first deco stop */
const int ascent_s_per_step = 1;
@@ -852,7 +851,7 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
while (entry->ndl_calc < MAX_PROFILE_DECO && deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, 1) <= 0) {
entry->ndl_calc += time_stepsize;
add_segment(depth_to_bar(entry->depth, dive),
- &dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac);
+ gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.bottomsac);
}
/* we don't need to calculate anything else */
return;
@@ -864,7 +863,7 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
/* Add segments for movement to stopdepth */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
add_segment(depth_to_bar(ascent_depth, dive),
- &dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->o2pressure.mbar, dive, prefs.decosac);
+ gasmix, ascent_s_per_step, entry->o2pressure.mbar, dive, prefs.decosac);
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(ascent_depth, dive)), surface_pressure, dive, 1), deco_stepsize);
}
ascent_depth = next_stop;
@@ -884,13 +883,13 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
if (entry->tts_calc > MAX_PROFILE_DECO)
break;
add_segment(depth_to_bar(ascent_depth, dive),
- &dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac);
+ gasmix, time_stepsize, entry->o2pressure.mbar, dive, prefs.decosac);
if (deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(ascent_depth,dive)), surface_pressure, dive, 1) <= next_stop) {
/* move to the next stop and add the travel between stops */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step)
add_segment(depth_to_bar(ascent_depth, dive),
- &dive->cylinder[cylinderindex].gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, dive, prefs.decosac);
+ gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, dive, prefs.decosac);
ascent_depth = next_stop;
next_stop -= deco_stepsize;
}
@@ -913,11 +912,16 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
* Set maximum number of iterations to 10 just in case */
while ((abs(prev_deco_time - deco_time) >= 30) && (count_iteration < 10)) {
int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, final_tts = 0 , time_clear_ceiling = 0, time_deep_ceiling = 0;
+ struct gasmix *gasmix = NULL;
+ struct event *ev = NULL;
+
for (i = 1; i < pi->nr; i++) {
struct plot_data *entry = pi->entry + i;
int j, t0 = (entry - 1)->sec, t1 = entry->sec;
int time_stepsize = 20;
+ gasmix = get_gasmix(dive, dc, t1, &ev, gasmix);
+
entry->ambpressure = depth_to_bar(entry->depth, dive);
entry->gfline = get_gf(entry->ambpressure, dive) * (100.0 - AMB_PERCENTAGE) + AMB_PERCENTAGE;
if (t0 > t1) {
@@ -931,7 +935,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
add_segment(depth_to_bar(depth, dive),
- &dive->cylinder[0].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
+ gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
if ((t1 - j < time_stepsize) && (j < t1))
time_stepsize = t1 - j;
}
@@ -1000,7 +1004,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
/* We are going to mess up deco state, so store it for later restore */
struct deco_state *cache_data = NULL;
cache_deco_state(&cache_data);
- calculate_ndl_tts(entry, dive, surface_pressure);
+ calculate_ndl_tts(dive, entry, gasmix, surface_pressure);
if (decoMode() == VPMB && !in_planner() && i == pi->nr - 1)
final_tts = entry->tts_calc;
/* Restore "real" deco state for next real time step */
@@ -1077,19 +1081,22 @@ static int calculate_ccr_po2(struct plot_data *entry, struct divecomputer *dc)
}
}
-static void calculate_gas_information_new(struct dive *dive, struct plot_info *pi)
+static void calculate_gas_information_new(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{
int i;
double amb_pressure;
+ struct gasmix *gasmix = NULL;
+ struct event *ev = NULL;
for (i = 1; i < pi->nr; i++) {
int fn2, fhe;
struct plot_data *entry = pi->entry + i;
- int cylinderindex = 0;
+
+ gasmix = get_gasmix(dive, dc, entry->sec, &ev, gasmix);
amb_pressure = depth_to_bar(entry->depth, dive);
- fill_pressures(&entry->pressures, amb_pressure, &dive->cylinder[cylinderindex].gasmix, entry->o2pressure.mbar / 1000.0, dive->dc.divemode);
+ fill_pressures(&entry->pressures, amb_pressure, gasmix, entry->o2pressure.mbar / 1000.0, dive->dc.divemode);
fn2 = (int)(1000.0 * entry->pressures.n2 / amb_pressure);
fhe = (int)(1000.0 * entry->pressures.he / amb_pressure);
@@ -1098,7 +1105,7 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
* END takes O₂ + N₂ (air) into account ("Narcotic" for trimix dives)
* EAD just uses N₂ ("Air" for nitrox dives) */
pressure_t modpO2 = { .mbar = (int)(prefs.modpO2 * 1000) };
- entry->mod = (double)gas_mod(&dive->cylinder[cylinderindex].gasmix, modpO2, dive, 1).mm;
+ entry->mod = (double)gas_mod(gasmix, modpO2, dive, 1).mm;
entry->end = (entry->depth + 10000) * (1000 - fhe) / 1000.0 - 10000;
entry->ead = (entry->depth + 10000) * fn2 / (double)N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) *
@@ -1106,7 +1113,7 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
entry->pressures.n2 / amb_pressure * N2_DENSITY +
entry->pressures.he / amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) * 1000 - 10000;
- entry->density = gas_density(&dive->cylinder[cylinderindex].gasmix, depth_to_mbar(entry->depth, dive));
+ entry->density = gas_density(gasmix, depth_to_mbar(entry->depth, dive));
if (entry->mod < 0)
entry->mod = 0;
if (entry->ead < 0)
@@ -1220,7 +1227,7 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
#ifndef SUBSURFACE_MOBILE
calculate_deco_information(dive, dc, pi, false); /* and ceiling information, using gradient factor values in Preferences) */
#endif
- calculate_gas_information_new(dive, pi); /* Calculate gas partial pressures */
+ calculate_gas_information_new(dive, dc, pi); /* Calculate gas partial pressures */
#ifdef DEBUG_GAS
debug_print_profiledata(pi);