summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subsurface-core/dive.c275
1 files changed, 173 insertions, 102 deletions
diff --git a/subsurface-core/dive.c b/subsurface-core/dive.c
index 8fc9e993b..12154704f 100644
--- a/subsurface-core/dive.c
+++ b/subsurface-core/dive.c
@@ -798,45 +798,6 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me
}
}
-static void fixup_pressure(struct dive *dive, struct sample *sample, enum cylinderuse cyl_use)
-{
- int pressure, index;
- cylinder_t *cyl;
-
- if (cyl_use != OXYGEN) {
- pressure = sample->cylinderpressure.mbar;
- index = sample->sensor;
- } else { // for the CCR oxygen cylinder:
- pressure = sample->o2cylinderpressure.mbar;
- index = get_cylinder_idx_by_use(dive, OXYGEN);
- }
- if (index < 0)
- return;
- if (!pressure)
- return;
-
- /*
- * Ignore surface samples for tank pressure information.
- *
- * At the beginning of the dive, let the cylinder cool down
- * if the diver starts off at the surface. And at the end
- * of the dive, there may be surface pressures where the
- * diver has already turned off the air supply (especially
- * for computers like the Uemis Zurich that end up saving
- * quite a bit of samples after the dive has ended).
- */
- if (sample->depth.mm < SURFACE_THRESHOLD)
- return;
-
- /* FIXME! sensor -> cylinder mapping? */
- if (index >= MAX_CYLINDERS)
- return;
- cyl = dive->cylinder + index;
- if (!cyl->sample_start.mbar)
- cyl->sample_start.mbar = pressure;
- cyl->sample_end.mbar = pressure;
-}
-
static void update_min_max_temperatures(struct dive *dive, temperature_t temperature)
{
if (temperature.mkelvin) {
@@ -1262,47 +1223,105 @@ static int interpolate_depth(struct divecomputer *dc, int idx, int lastdepth, in
return interpolate(lastdepth, nextdepth, now-lasttime, nexttime-lasttime);
}
-static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
+static void fixup_dc_depths(struct dive *dive, struct divecomputer *dc)
{
- int i, j;
- double depthtime = 0;
- int lasttime = 0;
- int lastindex = -1;
+ int i;
int maxdepth = dc->maxdepth.mm;
- int mintemp = 0;
- int lastdepth = 0;
- int lasttemp = 0;
- int lastpressure = 0, lasto2pressure = 0;
- int pressure_delta[MAX_CYLINDERS] = { INT_MAX, };
- int first_cylinder;
-
- /* Add device information to table */
- if (dc->deviceid && (dc->serial || dc->fw_version))
- create_device_node(dc->model, dc->deviceid, dc->serial, dc->fw_version, "");
-
- /* Fixup duration and mean depth */
- fixup_dc_duration(dc);
- update_min_max_temperatures(dive, dc->watertemp);
+ int lasttime = 0, lastdepth = 0;
- /* make sure we know for which tank the pressure values are intended */
- first_cylinder = explicit_first_cylinder(dive, dc);
for (i = 0; i < dc->samples; i++) {
struct sample *sample = dc->sample + i;
int time = sample->time.seconds;
int depth = sample->depth.mm;
- int temp = sample->temperature.mkelvin;
- int pressure = sample->cylinderpressure.mbar;
- int o2_pressure = sample->o2cylinderpressure.mbar;
- int index;
if (depth < 0) {
depth = interpolate_depth(dc, i, lastdepth, lasttime, time);
sample->depth.mm = depth;
}
- /* if we have an explicit first cylinder */
- if (sample->sensor == 0 && first_cylinder != 0)
+ if (depth > SURFACE_THRESHOLD) {
+ if (depth > maxdepth)
+ maxdepth = depth;
+ }
+
+ lastdepth = depth;
+ lasttime = time;
+ if (sample->cns > dive->maxcns)
+ dive->maxcns = sample->cns;
+ }
+
+ update_depth(&dc->maxdepth, maxdepth);
+ if (maxdepth > dive->maxdepth.mm)
+ dive->maxdepth.mm = maxdepth;
+}
+
+static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc)
+{
+ int i;
+ int mintemp = 0, lasttemp = 0;
+
+ for (i = 0; i < dc->samples; i++) {
+ struct sample *sample = dc->sample + i;
+ int temp = sample->temperature.mkelvin;
+
+ if (temp) {
+ /*
+ * If we have consecutive identical
+ * temperature readings, throw away
+ * the redundant ones.
+ */
+ if (lasttemp == temp)
+ sample->temperature.mkelvin = 0;
+ else
+ lasttemp = temp;
+
+ if (!mintemp || temp < mintemp)
+ mintemp = temp;
+ }
+
+ update_min_max_temperatures(dive, sample->temperature);
+ }
+ update_temperature(&dc->watertemp, mintemp);
+ update_min_max_temperatures(dive, dc->watertemp);
+}
+
+/*
+ * Fix up cylinder sensor information in the samples if we have
+ * an explicit first cylinder
+ */
+static void fixup_dc_cylinder_index(struct dive *dive, struct divecomputer *dc)
+{
+ int i;
+ int first_cylinder = explicit_first_cylinder(dive, dc);
+
+ if (!first_cylinder)
+ return;
+
+ for (i = 0; i < dc->samples; i++) {
+ struct sample *sample = dc->sample + i;
+
+ if (sample->sensor == 0)
sample->sensor = first_cylinder;
+ }
+}
+
+/*
+ * Simplify dc pressure information:
+ * (a) Remove redundant pressure information
+ * (b) Remove linearly interpolated pressure data
+ */
+static void simplify_dc_pressures(struct dive *dive, struct divecomputer *dc)
+{
+ int i, j;
+ int lastindex = -1;
+ int lastpressure = 0, lasto2pressure = 0;
+ int pressure_delta[MAX_CYLINDERS] = { INT_MAX, };
+
+ for (i = 0; i < dc->samples; i++) {
+ struct sample *sample = dc->sample + i;
+ int pressure = sample->cylinderpressure.mbar;
+ int o2_pressure = sample->o2cylinderpressure.mbar;
+ int index;
index = sample->sensor;
@@ -1330,38 +1349,6 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
lastindex = index;
lastpressure = pressure;
lasto2pressure = o2_pressure;
-
- if (depth > SURFACE_THRESHOLD) {
- if (depth > maxdepth)
- maxdepth = depth;
- }
-
- fixup_pressure(dive, sample, OC_GAS);
- if (dive->dc.divemode == CCR)
- fixup_pressure(dive, sample, OXYGEN);
-
- if (temp) {
- /*
- * If we have consecutive identical
- * temperature readings, throw away
- * the redundant ones.
- */
- if (lasttemp == temp)
- sample->temperature.mkelvin = 0;
- else
- lasttemp = temp;
-
- if (!mintemp || temp < mintemp)
- mintemp = temp;
- }
-
- update_min_max_temperatures(dive, sample->temperature);
-
- depthtime += (time - lasttime) * (lastdepth + depth) / 2;
- lastdepth = depth;
- lasttime = time;
- if (sample->cns > dive->maxcns)
- dive->maxcns = sample->cns;
}
/* if all the samples for a cylinder have pressure data that
@@ -1391,11 +1378,95 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
cyl->sample_end.mbar = 0;
}
}
+}
+
+/* FIXME! sensor -> cylinder mapping? */
+static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
+{
+ if (idx >= 0 && idx < MAX_CYLINDERS) {
+ cylinder_t *cyl = dive->cylinder + idx;
+ if (p.mbar && !cyl->sample_start.mbar)
+ cyl->sample_start = p;
+ }
+}
+
+static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
+{
+ if (idx >= 0 && idx < MAX_CYLINDERS) {
+ cylinder_t *cyl = dive->cylinder + idx;
+ if (p.mbar && !cyl->sample_end.mbar)
+ cyl->sample_end = p;
+ }
+}
+
+/*
+ * Check the cylinder pressure sample information and fill in the
+ * overall cylinder pressures from those.
+ *
+ * We ignore surface samples for tank pressure information.
+ *
+ * At the beginning of the dive, let the cylinder cool down
+ * if the diver starts off at the surface. And at the end
+ * of the dive, there may be surface pressures where the
+ * diver has already turned off the air supply (especially
+ * for computers like the Uemis Zurich that end up saving
+ * quite a bit of samples after the dive has ended).
+ */
+static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
+{
+ int i, o2index = -1;
+
+ if (dive->dc.divemode == CCR)
+ o2index = get_cylinder_idx_by_use(dive, OXYGEN);
+
+ /* Walk the samples from the beginning to find starting pressures.. */
+ for (i = 0; i < dc->samples; i++) {
+ struct sample *sample = dc->sample + i;
+
+ if (sample->depth.mm < SURFACE_THRESHOLD)
+ continue;
+
+ fixup_start_pressure(dive, sample->sensor, sample->cylinderpressure);
+ fixup_start_pressure(dive, o2index, sample->o2cylinderpressure);
+ }
+
+ /* ..and from the end for ending pressures */
+ for (i = dc->samples; --i >= 0; ) {
+ struct sample *sample = dc->sample + i;
+
+ if (sample->depth.mm < SURFACE_THRESHOLD)
+ continue;
+
+ fixup_end_pressure(dive, sample->sensor, sample->cylinderpressure);
+ fixup_end_pressure(dive, o2index, sample->o2cylinderpressure);
+ }
+
+ simplify_dc_pressures(dive, dc);
+}
+
+static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
+{
+ int i;
+
+ /* Add device information to table */
+ if (dc->deviceid && (dc->serial || dc->fw_version))
+ create_device_node(dc->model, dc->deviceid, dc->serial, dc->fw_version, "");
+
+ /* Fixup duration and mean depth */
+ fixup_dc_duration(dc);
+
+ /* Fix up sample depth data */
+ fixup_dc_depths(dive, dc);
+
+ /* Fix up dive temperatures based on dive computer samples */
+ fixup_dc_temp(dive, dc);
+
+ /* Fix up cylinder sensor data */
+ fixup_dc_cylinder_index(dive, dc);
+
+ /* Fix up cylinder pressures based on DC info */
+ fixup_dive_pressures(dive, dc);
- update_temperature(&dc->watertemp, mintemp);
- update_depth(&dc->maxdepth, maxdepth);
- if (maxdepth > dive->maxdepth.mm)
- dive->maxdepth.mm = maxdepth;
fixup_dc_events(dc);
}