diff options
-rw-r--r-- | deco.c | 44 | ||||
-rw-r--r-- | dive.h | 2 | ||||
-rw-r--r-- | planner.c | 22 |
3 files changed, 60 insertions, 8 deletions
@@ -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; @@ -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; @@ -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); } |