summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deco.c44
-rw-r--r--dive.h2
-rw-r--r--planner.c22
3 files changed, 60 insertions, 8 deletions
diff --git a/deco.c b/deco.c
index 05adba555..cd8f417d1 100644
--- a/deco.c
+++ b/deco.c
@@ -11,8 +11,11 @@
* deco_allowed_depth(tissues_tolerance, surface_pressure, dive, smooth)
* - ceiling based on lead tissue, surface pressure, 3m increments or smooth
* set_gf(gflow, gfhigh) - set Buehlmann gradient factors
+ * void cache_deco_state(tissue_tolerance, char **datap) - cache the relevant data allocate memory if needed
+ * double restore_deco_state(char *data) - restore the state and return the tissue_tolerance
*/
#include <math.h>
+#include <string.h>
#include "dive.h"
//! Option structure for Buehlmann decompression.
@@ -88,6 +91,7 @@ double tissue_he_sat[16];
double tissue_tolerated_ambient_pressure[16];
int ci_pointing_to_guiding_tissue;
double gf_low_position_this_dive;
+#define TISSUE_ARRAY_SZ sizeof(tissue_n2_sat)
static double actual_gradient_limit(const struct dive_data *data)
{
@@ -222,6 +226,46 @@ void clear_deco(double surface_pressure)
gf_low_position_this_dive = buehlmann_config.gf_low_position_min;
}
+void cache_deco_state(double tissue_tolerance, char **cached_datap)
+{
+ char *data = *cached_datap;
+
+ if (!data) {
+ data = malloc(3 * TISSUE_ARRAY_SZ + 2 * sizeof(double) + sizeof(int));
+ *cached_datap = data;
+ }
+ memcpy(data, tissue_n2_sat, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(data, tissue_he_sat, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(data, tissue_tolerated_ambient_pressure, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(data, &gf_low_position_this_dive, sizeof(double));
+ data += sizeof(double);
+ memcpy(data, &tissue_tolerance, sizeof(double));
+ data += sizeof(double);
+ memcpy(data, &ci_pointing_to_guiding_tissue, sizeof(int));
+}
+
+double restore_deco_state(char *data)
+{
+ double tissue_tolerance;
+
+ memcpy(tissue_n2_sat, data, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(tissue_he_sat, data, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(tissue_tolerated_ambient_pressure, data, TISSUE_ARRAY_SZ);
+ data += TISSUE_ARRAY_SZ;
+ memcpy(&gf_low_position_this_dive, data, sizeof(double));
+ data += sizeof(double);
+ memcpy(&tissue_tolerance, data, sizeof(double));
+ data += sizeof(double);
+ memcpy(&ci_pointing_to_guiding_tissue, data, sizeof(int));
+
+ return tissue_tolerance;
+}
+
unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, gboolean smooth)
{
unsigned int depth, multiples_of_3m;
diff --git a/dive.h b/dive.h
index d1f091e7a..aae57e8b7 100644
--- a/dive.h
+++ b/dive.h
@@ -577,6 +577,8 @@ extern void clear_deco(double surface_pressure);
extern void dump_tissues(void);
extern unsigned int deco_allowed_depth(double tissues_tolerance, double surface_pressure, struct dive *dive, gboolean smooth);
extern void set_gf(double gflow, double gfhigh);
+extern void cache_deco_state(double, char **datap);
+extern double restore_deco_state(char *data);
struct divedatapoint {
int time;
diff --git a/planner.c b/planner.c
index 02c746989..9d20d376f 100644
--- a/planner.c
+++ b/planner.c
@@ -11,7 +11,7 @@
int stoplevels[] = { 3000, 6000, 9000, 12000, 15000, 21000, 30000, 42000, 60000, 90000 };
/* returns the tissue tolerance at the end of this (partial) dive */
-double tissue_at_end(struct dive *dive)
+double tissue_at_end(struct dive *dive, char **cached_datap)
{
struct divecomputer *dc;
struct sample *sample, *psample;
@@ -20,11 +20,15 @@ double tissue_at_end(struct dive *dive)
if (!dive)
return 0.0;
- tissue_tolerance = init_decompression(dive);
-
+ if (*cached_datap) {
+ tissue_tolerance = restore_deco_state(*cached_datap);
+ } else {
+ tissue_tolerance = init_decompression(dive);
+ cache_deco_state(tissue_tolerance, cached_datap);
+ }
dc = &dive->dc;
if (!dc->samples)
- return 0.0;
+ return tissue_tolerance;
psample = sample = dc->sample;
t0 = 0;
for (i = 0; i < dc->samples; i++, sample++) {
@@ -41,7 +45,7 @@ double tissue_at_end(struct dive *dive)
}
/* how many seconds until we can ascend to the next stop? */
-int time_at_last_depth(struct dive *dive, int next_stop)
+int time_at_last_depth(struct dive *dive, int next_stop, char **cached_data_p)
{
int depth;
double surface_pressure, tissue_tolerance;
@@ -51,7 +55,7 @@ int time_at_last_depth(struct dive *dive, int next_stop)
if (!dive)
return 0;
surface_pressure = dive->surface_pressure.mbar / 1000.0;
- tissue_tolerance = tissue_at_end(dive);
+ tissue_tolerance = tissue_at_end(dive, cached_data_p);
sample = &dive->dc.sample[dive->dc.samples - 1];
depth = sample->depth.mm;
while (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) > next_stop) {
@@ -171,6 +175,7 @@ void plan(struct diveplan *diveplan)
int ceiling, depth, transitiontime;
int stopidx;
double tissue_tolerance;
+ char *cached_data = NULL;
if (!diveplan->surface_pressure)
diveplan->surface_pressure = 1013;
@@ -183,7 +188,7 @@ void plan(struct diveplan *diveplan)
o2 = dive->cylinder[sample->sensor].gasmix.o2.permille;
he = dive->cylinder[sample->sensor].gasmix.he.permille;
- tissue_tolerance = tissue_at_end(dive);
+ tissue_tolerance = tissue_at_end(dive, &cached_data);
ceiling = deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1);
for (stopidx = 0; stopidx < sizeof(stoplevels) / sizeof(int); stopidx++)
@@ -200,7 +205,7 @@ void plan(struct diveplan *diveplan)
dive = create_dive_from_plan(diveplan);
record_dive(dive);
}
- wait_time = time_at_last_depth(dive, stoplevels[stopidx - 1]);
+ wait_time = time_at_last_depth(dive, stoplevels[stopidx - 1], &cached_data);
if (wait_time)
plan_add_segment(diveplan, wait_time, stoplevels[stopidx], o2, he);
transitiontime = (stoplevels[stopidx] - stoplevels[stopidx - 1]) / 150;
@@ -212,6 +217,7 @@ void plan(struct diveplan *diveplan)
stopidx--;
}
/* now make the dive visible as last dive of the dive list */
+ free(cached_data);
report_dives(FALSE, FALSE);
}