diff options
-rw-r--r-- | dive.c | 55 | ||||
-rw-r--r-- | dive.h | 46 | ||||
-rw-r--r-- | divelist.c | 6 | ||||
-rw-r--r-- | planner.c | 8 | ||||
-rw-r--r-- | profile.c | 14 | ||||
-rw-r--r-- | save-xml.c | 2 | ||||
-rw-r--r-- | uemis.c | 4 |
7 files changed, 85 insertions, 50 deletions
@@ -230,27 +230,6 @@ int get_duration_in_sec(struct dive *dive) return duration; } -int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null) -{ - unsigned int count = 0, sum = 0; - const struct divecomputer *dc = &dive->dc; - - do { - if (!dc->surface_pressure.mbar) - continue; - sum += dc->surface_pressure.mbar; - count++; - } while ((dc = dc->next) != NULL); - - /* Did we have any dive computers with surface pressure information */ - if (count) - return (sum + count/2) / count; - - if (non_null) - return SURFACE_PRESSURE; - return 0; -} - static void update_temperature(temperature_t *temperature, int new) { if (new) { @@ -445,6 +424,36 @@ static struct event *find_previous_event(struct divecomputer *dc, struct event * return previous; } +static void fixup_surface_pressure(struct dive *dive) +{ + struct divecomputer *dc; + int sum, nr; + + for_each_dc(dive, dc) { + if (dc->surface_pressure.mbar) { + sum += dc->surface_pressure.mbar; + nr++; + } + } + if (nr) + dive->surface_pressure.mbar = (sum + nr/2)/nr; +} + +static void fixup_water_salinity(struct dive *dive) +{ + struct divecomputer *dc; + int sum, nr; + + for_each_dc(dive, dc) { + if (dc->salinity) { + sum += dc->salinity; + nr++; + } + } + if (nr) + dive->salinity = (sum + nr/2)/nr; +} + /* right now this only operates on the first divecomputer */ struct dive *fixup_dive(struct dive *dive) { @@ -466,6 +475,10 @@ struct dive *fixup_dive(struct dive *dive) add_suit(dive->suit); sanitize_cylinder_info(dive); dive->maxcns = dive->cns; + + fixup_water_salinity(dive); + fixup_surface_pressure(dive); + dc = &dive->dc; for (i = 0; i < dc->samples; i++) { struct sample *sample = dc->sample + i; @@ -20,6 +20,10 @@ #define SURFACE_PRESSURE_STRING "1013" #define ZERO_C_IN_MKELVIN 273150 // mKelvin +/* Salinity is expressed in weight in grams per 10l */ +#define SEAWATER_SALINITY 10300 +#define FRESHWATER_SALINITY 10000 + /* * Some silly typedefs to make our units very explicit. @@ -314,9 +318,12 @@ struct dive { weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; char *suit; int sac, otu, cns, maxcns; + + /* Calculated based on dive computer data */ temperature_t mintemp, maxtemp; + pressure_t surface_pressure; + int salinity; // kg per 10000 l - /* Eventually we'll do multiple dive computers */ struct divecomputer dc; }; @@ -333,22 +340,34 @@ static inline void copy_gps_location(struct dive *from, struct dive *to) } } -extern int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null); +static inline int get_surface_pressure_in_mbar(const struct dive *dive, gboolean non_null) +{ + int mbar = dive->surface_pressure.mbar; + if (!mbar && non_null) + mbar = SURFACE_PRESSURE; + return mbar; +} /* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m * of water (and use standard salt water at 1.03kg per liter if we don't know salinity) * and add that to the surface pressure (or to 1013 if that's unknown) */ -static inline int depth_to_mbar(int depth, struct dive *dive, struct divecomputer *dc) +static inline int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity) { - double specific_weight = 1.03 * 0.981; - int surface_pressure; - if (dc->salinity) - specific_weight = dc->salinity / 10000.0 * 0.981; - if (dc->surface_pressure.mbar) - surface_pressure = dc->surface_pressure.mbar; - else - surface_pressure = get_surface_pressure_in_mbar(dive, TRUE); - return depth / 10.0 * specific_weight + surface_pressure + 0.5; + double specific_weight; + int mbar = surface_pressure.mbar; + + if (!mbar) + mbar = SURFACE_PRESSURE; + if (!salinity) + salinity = SEAWATER_SALINITY; + specific_weight = salinity / 10000.0 * 0.981; + mbar += depth / 10.0 * specific_weight + 0.5; + return mbar; +} + +static inline int depth_to_mbar(int depth, struct dive *dive) +{ + return calculate_depth_to_mbar(depth, dive->surface_pressure, dive->salinity); } /* for the inverse calculation we use just the relative pressure @@ -468,6 +487,9 @@ static inline struct dive *get_dive(int nr) #define for_each_dive(_i,_x) \ for ((_i) = 0; ((_x) = get_dive(_i)) != NULL; (_i)++) +#define for_each_dc(_dive,_dc) \ + for (_dc = &_dive->dc; _dc; _dc = _dc->next) + #define for_each_gps_location(_i,_x) \ for ((_i) = 0; ((_x) = get_gps_location(_i, &gps_location_table)) != NULL; (_i)++) diff --git a/divelist.c b/divelist.c index 97981a0f2..417cb1b77 100644 --- a/divelist.c +++ b/divelist.c @@ -655,7 +655,7 @@ static int calculate_otu(struct dive *dive) po2 = sample->po2; } else { int o2 = active_o2(dive, dc, sample->time); - po2 = o2 / 1000.0 * depth_to_mbar(sample->depth.mm, dive, &dive->dc); + po2 = o2 / 1000.0 * depth_to_mbar(sample->depth.mm, dive); } if (po2 >= 500) otu += pow((po2 - 500) / 1000.0, 0.83) * t / 30.0; @@ -720,7 +720,7 @@ static int calculate_sac(struct dive *dive) } } /* Mean pressure in bar (SAC calculations are in bar*l/min) */ - pressure = depth_to_mbar(dive->dc.meandepth.mm, dive, &dive->dc) / 1000.0; + pressure = depth_to_mbar(dive->dc.meandepth.mm, dive) / 1000.0; sac = airuse / pressure * 60 / duration; /* milliliters per minute.. */ @@ -744,7 +744,7 @@ static void add_dive_to_deco(struct dive *dive) for (j = t0; j < t1; j++) { int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0); - (void) add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0, + (void) add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[sample->sensor].gasmix, 1, sample->po2, dive); } } @@ -112,7 +112,7 @@ double tissue_at_end(struct dive *dive, char **cached_datap) lastdepth = psample->depth.mm; for (j = t0; j < t1; j++) { int depth = interpolate(lastdepth, sample->depth.mm, j - t0, t1 - t0); - tissue_tolerance = add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0, + tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive); } psample = sample; @@ -139,7 +139,7 @@ int time_at_last_depth(struct dive *dive, int next_stop, char **cached_data_p) gasidx = get_gasidx(dive, o2, he); while (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) > next_stop) { wait++; - tissue_tolerance = add_segment(depth_to_mbar(depth, dive, &dive->dc) / 1000.0, + tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive); } return wait; @@ -504,7 +504,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive) gasidx = get_gasidx(dive, o2, he); len = strlen(buffer); if (dp->depth != lastdepth) { - used = diveplan->bottomsac / 1000.0 * depth_to_mbar((dp->depth + lastdepth) / 2, dive, &dive->dc) * + used = diveplan->bottomsac / 1000.0 * depth_to_mbar((dp->depth + lastdepth) / 2, dive) * (dp->time - lasttime) / 60; snprintf(buffer + len, sizeof(buffer) - len, _("Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s\n"), decimals, depthvalue, depth_unit, @@ -514,7 +514,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive) } else { /* we use deco SAC rate during the calculated deco stops, bottom SAC rate everywhere else */ int sac = dp->entered ? diveplan->bottomsac : diveplan->decosac; - used = sac / 1000.0 * depth_to_mbar(dp->depth, dive, &dive->dc) * (dp->time - lasttime) / 60; + used = sac / 1000.0 * depth_to_mbar(dp->depth, dive) * (dp->time - lasttime) / 60; snprintf(buffer + len, sizeof(buffer) - len, _("Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s\n"), decimals, depthvalue, depth_unit, FRACTION(dp->time - lasttime, 60), @@ -1011,11 +1011,11 @@ static void set_sac_color(struct graphics_context *gc, int sac, int avg_sac) } /* calculate the current SAC in ml/min and convert to int */ -#define GET_LOCAL_SAC(_entry1, _entry2, _dive, _dc) (int) \ +#define GET_LOCAL_SAC(_entry1, _entry2, _dive) (int) \ ((GET_PRESSURE((_entry1)) - GET_PRESSURE((_entry2))) * \ (_dive)->cylinder[(_entry1)->cylinderindex].type.size.mliter / \ (((_entry2)->sec - (_entry1)->sec) / 60.0) / \ - depth_to_mbar(((_entry1)->depth + (_entry2)->depth) / 2.0, (_dive), (_dc))) + depth_to_mbar(((_entry1)->depth + (_entry2)->depth) / 2.0, (_dive))) #define SAC_WINDOW 45 /* sliding window in seconds for current SAC calculation */ @@ -1050,12 +1050,12 @@ static void plot_cylinder_pressure(struct graphics_context *gc, struct plot_info if (!last_entry) { last = i; last_entry = entry; - sac = GET_LOCAL_SAC(entry, pi->entry + i + 1, dive, dc); + sac = GET_LOCAL_SAC(entry, pi->entry + i + 1, dive); } else { int j; sac = 0; for (j = last; j < i; j++) - sac += GET_LOCAL_SAC(pi->entry + j, pi->entry + j + 1, dive, dc); + sac += GET_LOCAL_SAC(pi->entry + j, pi->entry + j + 1, dive); sac /= (i - last); if (entry->sec - last_entry->sec >= SAC_WINDOW) { last++; @@ -1405,7 +1405,7 @@ static inline int pressure_time(struct dive *dive, struct divecomputer *dc, stru int time = b->sec - a->sec; int depth = (a->depth + b->depth)/2; - return depth_to_mbar(depth, dive, dc) * time; + return depth_to_mbar(depth, dive) * time; } static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr) @@ -1822,7 +1822,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d struct plot_data *entry = pi->entry + i; int cylinderindex = entry->cylinderindex; - amb_pressure = depth_to_mbar(entry->depth, dive, dc) / 1000.0; + amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0; fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille ? : O2_IN_AIR; fhe = dive->cylinder[cylinderindex].gasmix.he.permille; double ratio = (double)fhe / (1000.0 - fo2); @@ -1876,7 +1876,7 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d tissue_tolerance = 0; for (j = t0+1; j <= t1; j++) { int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0); - double min_pressure = add_segment(depth_to_mbar(depth, dive, dc) / 1000.0, + double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[cylinderindex].gasmix, 1, entry->po2 * 1000, dive); tissue_tolerance = min_pressure; } diff --git a/save-xml.c b/save-xml.c index b95a38028..22059a178 100644 --- a/save-xml.c +++ b/save-xml.c @@ -172,7 +172,7 @@ static void save_airpressure(FILE *f, struct divecomputer *dc) static void save_salinity(FILE *f, struct divecomputer *dc) { /* only save if we have a value that isn't the default of sea water */ - if (!dc->salinity || dc->salinity == 10300) + if (!dc->salinity || dc->salinity == SEAWATER_SALINITY) return; fputs(" <water", f); show_salinity(f, dc->salinity, " salinity='", "'"); @@ -300,9 +300,9 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { dive->dc.airtemp.mkelvin = *(uint16_t *)(data + 45) * 100 + ZERO_C_IN_MKELVIN; dive->dc.surface_pressure.mbar = *(uint16_t *)(data + 43); if (*(uint8_t *)(data + 19)) - dive->dc.salinity = 10300; /* avg grams per 10l sea water */ + dive->dc.salinity = SEAWATER_SALINITY; /* avg grams per 10l sea water */ else - dive->dc.salinity = 10000; /* grams per 10l fresh water */ + dive->dc.salinity = FRESHWATER_SALINITY; /* grams per 10l fresh water */ /* this will allow us to find the last dive read so far from this computer */ dc->model = strdup("Uemis Zurich"); |