diff options
-rw-r--r-- | subsurface-core/dive.c | 275 |
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); } |