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 <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Linus Torvalds 2015-10-25 12:02:08 +09:00 committed by Dirk Hohndel
parent cd1884b29c
commit 2b1017c986
2 changed files with 29 additions and 4 deletions

22
dive.c
View file

@ -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) static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
{ {
int i, j; 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 o2_pressure = sample->o2cylinderpressure.mbar;
int index; 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 we have an explicit first cylinder */
if (sample->sensor == 0 && first_cylinder != 0) if (sample->sensor == 0 && first_cylinder != 0)
sample->sensor = first_cylinder; sample->sensor = first_cylinder;

View file

@ -231,7 +231,6 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp
void void
sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata)
{ {
unsigned int mm;
static unsigned int nsensor = 0; static unsigned int nsensor = 0;
struct divecomputer *dc = userdata; struct divecomputer *dc = userdata;
struct sample *sample; struct sample *sample;
@ -252,7 +251,10 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata)
switch (type) { switch (type) {
case DC_SAMPLE_TIME: case DC_SAMPLE_TIME:
nsensor = 0; 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) { if (sample) {
sample->in_deco = in_deco; sample->in_deco = in_deco;
sample->ndl.seconds = ndl; 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->stopdepth.mm = stopdepth;
sample->setpoint.mbar = po2; sample->setpoint.mbar = po2;
sample->cns = cns; sample->cns = cns;
mm = sample->depth.mm;
} }
// Create a new sample.
// Mark depth as negative
sample = prepare_sample(dc); sample = prepare_sample(dc);
sample->time.seconds = value.time; sample->time.seconds = value.time;
sample->depth.mm = mm; sample->depth.mm = -1;
finish_sample(dc); finish_sample(dc);
break; break;
case DC_SAMPLE_DEPTH: case DC_SAMPLE_DEPTH: