From 2b1017c986bf10a490592fba7e85b14df86cd58d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 25 Oct 2015 12:02:08 +0900 Subject: Interpolate depth for samples that have no depth When downloading from libdivecomputer, we used to initialize the depth of a sample to the previous depth. However, at least for the Suunto EON Steel, you can get sample times without any actual depth reading - the time might be associated with some ranbdom event rather than a new depth sample. Rather than initialize these samples to have the same depth as the previous one (and then perhaps getting a very sudden jump when the *real* depth event comes in a second later), initialize the depth samples to -1, and if that sample doesn't get a real depth, we'll create an interpolated depth. It is possible that we should just carry the sample around as not actually having a depth, and instead just interpolate in the plot_info generation, but at least right now we have a ton of code that "knows" that every sample has a depth. Not the least of which is our own save format. So generating an interpolated depth seems the path of least resistance, and at least makes the graph look correct - no odd staircase effect from other events that happen in between depth samples. Signed-off-by: Linus Torvalds Signed-off-by: Dirk Hohndel --- dive.c | 22 ++++++++++++++++++++++ libdivecomputer.c | 11 +++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/dive.c b/dive.c index dfd5b495c..2ae84ca1e 100644 --- a/dive.c +++ b/dive.c @@ -1243,6 +1243,23 @@ static void fixup_dc_events(struct divecomputer *dc) } } +static int interpolate_depth(struct divecomputer *dc, int idx, int lastdepth, int lasttime, int now) +{ + int i; + int nextdepth = lastdepth; + int nexttime = now; + + for (i = idx+1; i < dc->samples; i++) { + struct sample *sample = dc->sample + i; + if (sample->depth.mm < 0) + continue; + nextdepth = sample->depth.mm; + nexttime = sample->time.seconds; + break; + } + return interpolate(lastdepth, nextdepth, now-lasttime, nexttime-lasttime); +} + static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) { int i, j; @@ -1276,6 +1293,11 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) 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) sample->sensor = first_cylinder; diff --git a/libdivecomputer.c b/libdivecomputer.c index a9d90d837..b5f90cb35 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -231,7 +231,6 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp void sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) { - unsigned int mm; static unsigned int nsensor = 0; struct divecomputer *dc = userdata; struct sample *sample; @@ -252,7 +251,10 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) switch (type) { case DC_SAMPLE_TIME: nsensor = 0; - mm = 0; + + // The previous sample gets some sticky values + // that may have been around from before, even + // if there was no new data if (sample) { sample->in_deco = in_deco; sample->ndl.seconds = ndl; @@ -260,11 +262,12 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) sample->stopdepth.mm = stopdepth; sample->setpoint.mbar = po2; sample->cns = cns; - mm = sample->depth.mm; } + // Create a new sample. + // Mark depth as negative sample = prepare_sample(dc); sample->time.seconds = value.time; - sample->depth.mm = mm; + sample->depth.mm = -1; finish_sample(dc); break; case DC_SAMPLE_DEPTH: -- cgit v1.2.3-70-g09d2