aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/dive.c2
-rw-r--r--core/dive.h3
-rw-r--r--core/profile.c107
3 files changed, 83 insertions, 29 deletions
diff --git a/core/dive.c b/core/dive.c
index d07a9d2aa..7f89e5063 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -2071,7 +2071,7 @@ static void cylinder_renumber(struct dive *dive, int mapping[])
dc_cylinder_renumber(dive, dc, mapping);
}
-static int same_gasmix(struct gasmix *a, struct gasmix *b)
+int same_gasmix(struct gasmix *a, struct gasmix *b)
{
if (gasmix_is_air(a) && gasmix_is_air(b))
return 1;
diff --git a/core/dive.h b/core/dive.h
index d19ccca4d..350331d95 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -140,8 +140,7 @@ extern int gas_volume(cylinder_t *cyl, pressure_t p);
extern double gas_compressibility_factor(struct gasmix *gas, double bar);
extern double isothermal_pressure(struct gasmix *gas, double p1, int volume1, int volume2);
extern double gas_density(struct gasmix *gas, int pressure);
-
-
+extern int same_gasmix(struct gasmix *a, struct gasmix *b);
static inline int get_o2(const struct gasmix *mix)
{
diff --git a/core/profile.c b/core/profile.c
index 6e62ac499..cb11251cf 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -637,26 +637,34 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
/*
* Calculate the sac rate between the two plot entries 'first' and 'last'.
*
- * Everything in between has a cylinder pressure, and it's all the same
- * cylinder.
+ * Everything in between has a cylinder pressure for at least some of the cylinders.
*/
-static int sac_between(struct dive *dive, struct plot_data *first, struct plot_data *last)
+static int sac_between(struct dive *dive, struct plot_data *first, struct plot_data *last, unsigned int gases)
{
- int sensor = 0;
- int airuse;
+ int i, airuse;
double pressuretime;
- pressure_t a, b;
- cylinder_t *cyl;
if (first == last)
return 0;
- /* Calculate air use - trivial */
- a.mbar = GET_PRESSURE(first, sensor);
- b.mbar = GET_PRESSURE(last, sensor);
- cyl = dive->cylinder + sensor;
- airuse = gas_volume(cyl, a) - gas_volume(cyl, b);
- if (airuse <= 0)
+ /* Get airuse for the set of cylinders over the range */
+ airuse = 0;
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ pressure_t a, b;
+ cylinder_t *cyl;
+ int cyluse;
+
+ if (!(gases & (1u << i)))
+ continue;
+
+ a.mbar = GET_PRESSURE(first, i);
+ b.mbar = GET_PRESSURE(last, i);
+ cyl = dive->cylinder + i;
+ cyluse = gas_volume(cyl, a) - gas_volume(cyl, b);
+ if (cyluse > 0)
+ airuse += cyluse;
+ }
+ if (!airuse)
return 0;
/* Calculate depthpressure integrated over time */
@@ -676,26 +684,45 @@ static int sac_between(struct dive *dive, struct plot_data *first, struct plot_d
return lrint(airuse / pressuretime);
}
+/* Which of the set of gases have pressure data */
+static unsigned int have_pressures(struct plot_data *entry, unsigned int gases)
+{
+ int i;
+
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ unsigned int mask = 1 << i;
+ if (gases & mask) {
+ if (!GET_PRESSURE(entry, i))
+ gases &= ~mask;
+ }
+ }
+ return gases;
+}
+
/*
* Try to do the momentary sac rate for this entry, averaging over one
* minute.
*/
-static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
+static void fill_sac(struct dive *dive, struct plot_info *pi, int idx, unsigned int gases)
{
struct plot_data *entry = pi->entry + idx;
struct plot_data *first, *last;
- int sensor = 0;
int time;
if (entry->sac)
return;
- if (!GET_PRESSURE(entry, 0))
+ /*
+ * We may not have pressure data for all the cylinders,
+ * but we'll calculate the SAC for the ones we do have.
+ */
+ gases = have_pressures(entry, gases);
+ if (!gases)
return;
/*
* Try to go back 30 seconds to get 'first'.
- * Stop if the sensor changed, or if we went back too far.
+ * Stop if the cylinder pressure data set changes.
*/
first = entry;
time = entry->sec - 30;
@@ -706,7 +733,7 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
break;
if (prev->sec < time)
break;
- if (!GET_PRESSURE(prev, sensor))
+ if (have_pressures(prev, gases) != gases)
break;
idx--;
first = prev;
@@ -721,19 +748,47 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
break;
if (next->sec > time)
break;
- if (!GET_PRESSURE(next, sensor))
+ if (have_pressures(next, gases) != gases)
break;
last = next;
}
/* Ok, now calculate the SAC between 'first' and 'last' */
- entry->sac = sac_between(dive, first, last);
+ entry->sac = sac_between(dive, first, last, gases);
}
-static void calculate_sac(struct dive *dive, struct plot_info *pi)
+/*
+ * Create a bitmap of cylinders that match our current gasmix
+ */
+static unsigned int matching_gases(struct dive *dive, struct gasmix *gasmix)
+{
+ int i;
+ unsigned int gases = 0;
+
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ cylinder_t *cyl = dive->cylinder + i;
+ if (same_gasmix(gasmix, &cyl->gasmix))
+ gases |= 1 << i;
+ }
+ return gases;
+}
+
+static void calculate_sac(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{
- for (int i = 0; i < pi->nr; i++)
- fill_sac(dive, pi, i);
+ struct gasmix *gasmix = NULL;
+ struct event *ev = NULL;
+ unsigned int gases = 0;
+
+ for (int i = 0; i < pi->nr; i++) {
+ struct plot_data *entry = pi->entry + i;
+ struct gasmix *newmix = get_gasmix(dive, dc, entry->sec, &ev, gasmix);
+ if (newmix != gasmix) {
+ gasmix = newmix;
+ gases = matching_gases(dive, newmix);
+ }
+
+ fill_sac(dive, pi, i, gases);
+ }
}
static void populate_secondary_sensor_data(struct divecomputer *dc, struct plot_info *pi)
@@ -1125,7 +1180,7 @@ static void calculate_gas_information_new(struct dive *dive, struct divecomputer
}
}
-void fill_o2_values(struct divecomputer *dc, struct plot_info *pi, struct dive *dive)
+void fill_o2_values(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
/* In the samples from each dive computer, there may be uninitialised oxygen
* sensor or setpoint values, e.g. when events were inserted into the dive log
* or if the dive computer does not report o2 values with every sample. But
@@ -1222,8 +1277,8 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++)
populate_pressure_information(dive, dc, pi, cyl);
}
- fill_o2_values(dc, pi, dive); /* .. and insert the O2 sensor data having 0 values. */
- calculate_sac(dive, pi); /* Calculate sac */
+ fill_o2_values(dive, dc, pi); /* .. and insert the O2 sensor data having 0 values. */
+ calculate_sac(dive, dc, pi); /* Calculate sac */
#ifndef SUBSURFACE_MOBILE
calculate_deco_information(dive, dc, pi, false); /* and ceiling information, using gradient factor values in Preferences) */
#endif