summaryrefslogtreecommitdiffstats
path: root/core/dive.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/dive.c')
-rw-r--r--core/dive.c137
1 files changed, 94 insertions, 43 deletions
diff --git a/core/dive.c b/core/dive.c
index 6d4f8603c..915a04fe5 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -40,28 +40,6 @@ int event_is_gaschange(struct event *ev)
ev->type == SAMPLE_EVENT_GASCHANGE2;
}
-/*
- * Does the gas mix data match the legacy
- * libdivecomputer event format? If so,
- * we can skip saving it, in order to maintain
- * the old save formats. We'll re-generate the
- * gas mix when loading.
- */
-int event_gasmix_redundant(struct event *ev)
-{
- struct gasmix *mix = &ev->gas.mix;
- int value = ev->value;
- int o2, he;
-
- if (value == 21)
- return gasmix_is_air(mix);
-
- o2 = (value & 0xffff) * 10;
- he = (value >> 16) * 10;
- return o2 == get_o2(mix) &&
- he == get_he(mix);
-}
-
struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name)
{
int gas_index = -1;
@@ -178,7 +156,7 @@ void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
}
/* this returns a pointer to static variable - so use it right away after calling */
-struct gasmix *get_gasmix_from_event(struct event *ev)
+struct gasmix *get_gasmix_from_event(struct dive *dive, struct event *ev)
{
static struct gasmix dummy;
if (ev && event_is_gaschange(ev))
@@ -849,7 +827,7 @@ int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc)
/* this gets called when the dive mode has changed (so OC vs. CC)
* there are two places we might have setpoints... events or in the samples
*/
-void update_setpoint_events(struct divecomputer *dc)
+void update_setpoint_events(struct dive *dive, struct divecomputer *dc)
{
struct event *ev;
int new_setpoint = 0;
@@ -867,14 +845,14 @@ void update_setpoint_events(struct divecomputer *dc)
// So we make sure, this comes from a Predator or Petrel and we only remove
// pO2 values we would have computed anyway.
struct event *ev = get_next_event(dc->events, "gaschange");
- struct gasmix *gasmix = get_gasmix_from_event(ev);
+ struct gasmix *gasmix = get_gasmix_from_event(dive, ev);
struct event *next = get_next_event(ev, "gaschange");
for (int i = 0; i < dc->samples; i++) {
struct gas_pressures pressures;
if (next && dc->sample[i].time.seconds >= next->time.seconds) {
ev = next;
- gasmix = get_gasmix_from_event(ev);
+ gasmix = get_gasmix_from_event(dive, ev);
next = get_next_event(ev, "gaschange");
}
fill_pressures(&pressures, calculate_depth_to_mbar(dc->sample[i].depth.mm, dc->surface_pressure, 0), gasmix ,0, OC);
@@ -1401,6 +1379,92 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
simplify_dc_pressures(dive, dc);
}
+int find_best_gasmix_match(struct gasmix *mix, cylinder_t array[], unsigned int used)
+{
+ int i;
+ int best = -1, score = INT_MAX;
+
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ const cylinder_t *match;
+ int distance;
+
+ if (used & (1 << i))
+ continue;
+ match = array + i;
+ if (cylinder_nodata(match))
+ continue;
+ distance = gasmix_distance(mix, &match->gasmix);
+ if (distance >= score)
+ continue;
+ best = i;
+ score = distance;
+ }
+ return best;
+}
+
+/*
+ * Match a gas change event against the cylinders we have
+ */
+static bool validate_gaschange(struct dive *dive, struct divecomputer *dc, struct event *event)
+{
+ int index;
+ int o2, he, value;
+
+ /* We'll get rid of the per-event gasmix, but for now sanitize it */
+ if (gasmix_is_air(&event->gas.mix))
+ event->gas.mix.o2.permille = 0;
+
+ /* Do we already have a cylinder index for this gasmix? */
+ if (event->gas.index >= 0)
+ return true;
+
+ index = find_best_gasmix_match(&event->gas.mix, dive->cylinder, 0);
+ if (index < 0)
+ return false;
+
+ /* Fix up the event to have the right information */
+ event->gas.index = index;
+ event->gas.mix = dive->cylinder[index].gasmix;
+
+ /* Convert to odd libdivecomputer format */
+ o2 = get_o2(&event->gas.mix);
+ he = get_he(&event->gas.mix);
+
+ o2 = (o2 + 5) / 10;
+ he = (he + 5) / 10;
+ value = o2 + (he << 16);
+
+ event->value = value;
+ if (he)
+ event->type = SAMPLE_EVENT_GASCHANGE2;
+
+ return true;
+}
+
+/* Clean up event, return true if event is ok, false if it should be dropped as bogus */
+static bool validate_event(struct dive *dive, struct divecomputer *dc, struct event *event)
+{
+ if (event_is_gaschange(event))
+ return validate_gaschange(dive, dc, event);
+ return true;
+}
+
+static void fixup_dc_gasswitch(struct dive *dive, struct divecomputer *dc)
+{
+ struct event **evp, *event;
+
+ evp = &dc->events;
+ while ((event = *evp) != NULL) {
+ if (validate_event(dive, dc, event)) {
+ evp = &event->next;
+ continue;
+ }
+
+ /* Delete this event and try the next one */
+ *evp = event->next;
+ }
+}
+
static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
{
int i;
@@ -1418,6 +1482,9 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
/* Fix up dive temperatures based on dive computer samples */
fixup_dc_temp(dive, dc);
+ /* Fix up gas switch events */
+ fixup_dc_gasswitch(dive, dc);
+
/* Fix up cylinder sensor data */
fixup_dc_cylinder_index(dive, dc);
@@ -1804,25 +1871,9 @@ extern void fill_pressures(struct gas_pressures *pressures, const double amb_pre
static int find_cylinder_match(cylinder_t *cyl, cylinder_t array[], unsigned int used)
{
- int i;
- int best = -1, score = INT_MAX;
-
if (cylinder_nodata(cyl))
return -1;
- for (i = 0; i < MAX_CYLINDERS; i++) {
- const cylinder_t *match;
- int distance;
-
- if (used & (1 << i))
- continue;
- match = array + i;
- distance = gasmix_distance(&cyl->gasmix, &match->gasmix);
- if (distance >= score)
- continue;
- best = i;
- score = distance;
- }
- return best;
+ return find_best_gasmix_match(&cyl->gasmix, array, used);
}
/* Force an initial gaschange event to the (old) gas #0 */