summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/CMakeLists.txt2
-rw-r--r--core/dive.c106
-rw-r--r--core/dive.h34
-rw-r--r--core/equipment.c31
-rw-r--r--core/equipment.h13
-rw-r--r--core/gas.c79
-rw-r--r--core/gas.h57
7 files changed, 173 insertions, 149 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 5121222cc..3a0806454 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -86,6 +86,8 @@ set(SUBSURFACE_CORE_LIB_SRCS
file.h
format.cpp
format.h
+ gas.c
+ gas.h
gas-model.c
gaspressures.c
gaspressures.h
diff --git a/core/dive.c b/core/dive.c
index 2d82f5565..a54c3aa00 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -866,13 +866,6 @@ static void update_min_max_temperatures(struct dive *dive, temperature_t tempera
}
}
-int gas_volume(const cylinder_t *cyl, pressure_t p)
-{
- double bar = p.mbar / 1000.0;
- double z_factor = gas_compressibility_factor(cyl->gasmix, bar);
- return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
-}
-
/*
* If the cylinder tank pressures are within half a bar
* (about 8 PSI) of the sample pressures, we consider it
@@ -948,31 +941,6 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
}
}
-void sanitize_gasmix(struct gasmix *mix)
-{
- unsigned int o2, he;
-
- o2 = mix->o2.permille;
- he = mix->he.permille;
-
- /* Regular air: leave empty */
- if (!he) {
- if (!o2)
- return;
- /* 20.8% to 21% O2 is just air */
- if (gasmix_is_air(*mix)) {
- mix->o2.permille = 0;
- return;
- }
- }
-
- /* Sane mix? */
- if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000)
- return;
- fprintf(stderr, "Odd gasmix: %u O2 %u He\n", o2, he);
- memset(mix, 0, sizeof(*mix));
-}
-
/*
* See if the size/workingpressure looks like some standard cylinder
* size, eg "AL80".
@@ -1059,23 +1027,6 @@ static void sanitize_cylinder_info(struct dive *dive)
}
}
-/* Perform isobaric counterdiffusion calculations for gas changes in trimix dives.
- * Here we use the rule-of-fifths where, during a change involving trimix gas, the increase in nitrogen
- * should not exceed one fifth of the decrease in helium.
- * Parameters: 1) pointers to two gas mixes, the gas being switched from and the gas being switched to.
- * 2) a pointer to an icd_data structure.
- * Output: i) The icd_data stucture is filled with the delta_N2 and delta_He numbers (as permille).
- * ii) Function returns a boolean indicating an exceeding of the rule-of-fifths. False = no icd problem.
- */
-bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results)
-{
- if (!prefs.show_icd)
- return false;
- results->dN2 = get_he(oldgasmix) + get_o2(oldgasmix) - get_he(newgasmix) - get_o2(newgasmix);
- results->dHe = get_he(newgasmix) - get_he(oldgasmix);
- return get_he(oldgasmix) > 0 && results->dN2 > 0 && results->dHe < 0 && get_he(oldgasmix) && results->dN2 > 0 && 5 * results->dN2 > -results->dHe;
-}
-
/* some events should never be thrown away */
static bool is_potentially_redundant(const struct event *event)
{
@@ -1464,29 +1415,6 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
simplify_dc_pressures(dc);
}
-int find_best_gasmix_match(struct gasmix mix, const 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
*/
@@ -2031,17 +1959,6 @@ extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cyl
return -1; // negative number means cylinder_use_type not found in list of cylinders
}
-int gasmix_distance(struct gasmix a, struct gasmix b)
-{
- int a_o2 = get_o2(a), b_o2 = get_o2(b);
- int a_he = get_he(a), b_he = get_he(b);
- int delta_o2 = a_o2 - b_o2, delta_he = a_he - b_he;
-
- delta_he = delta_he * delta_he;
- delta_o2 = delta_o2 * delta_o2;
- return delta_he + delta_o2;
-}
-
/* fill_pressures(): Compute partial gas pressures in bar from gasmix and ambient pressures, possibly for OC or CCR, to be
* extended to PSCT. This function does the calculations of gas pressures applicable to a single point on the dive profile.
* The structure "pressures" is used to return calculated gas pressures to the calling software.
@@ -2052,7 +1969,7 @@ int gasmix_distance(struct gasmix a, struct gasmix b)
* divemode = the dive mode pertaining to this point in the dive profile.
* This function called by: calculate_gas_information_new() in profile.c; add_segment() in deco.c.
*/
-extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t divemode)
+void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t divemode)
{
if ((divemode != OC) && po2) { // This is a rebreather dive where pressures->o2 is defined
if (po2 >= amb_pressure) {
@@ -2180,20 +2097,6 @@ void cylinder_renumber(struct dive *dive, int mapping[])
dc_cylinder_renumber(dive, dc, mapping);
}
-static bool gasmix_is_invalid(struct gasmix mix)
-{
- return mix.o2.permille < 0;
-}
-
-int same_gasmix(struct gasmix a, struct gasmix b)
-{
- if (gasmix_is_invalid(a) || gasmix_is_invalid(b))
- return 0;
- if (gasmix_is_air(a) && gasmix_is_air(b))
- return 1;
- return a.o2.permille == b.o2.permille && a.he.permille == b.he.permille;
-}
-
int same_gasmix_cylinder(cylinder_t *cyl, int cylid, struct dive *dive, bool check_unused)
{
struct gasmix mygas = cyl->gasmix;
@@ -3922,13 +3825,6 @@ fraction_t best_he(depth_t depth, const struct dive *dive)
return fhe;
}
-bool gasmix_is_air(struct gasmix gasmix)
-{
- int o2 = gasmix.o2.permille;
- int he = gasmix.he.permille;
- return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
-}
-
void invalidate_dive_cache(struct dive *dive)
{
memset(dive->git_id, 0, 20);
diff --git a/core/dive.h b/core/dive.h
index c6b08abd4..042f825f4 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -27,13 +27,6 @@ extern const char *cylinderuse_text[];
extern const char *divemode_text_ui[];
extern const char *divemode_text[];
-struct icd_data { // This structure provides communication between function isobaric_counterdiffusion() and the calling software.
- int dN2; // The change in fraction (permille) of nitrogen during the change
- int dHe; // The change in fraction (permille) of helium during the change
-};
-
-extern bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results);
-
/*
* Events are currently based straight on what libdivecomputer gives us.
* We need to wrap these into our own events at some point to remove some of the limitations.
@@ -63,35 +56,8 @@ struct event {
extern int event_is_gaschange(const struct event *ev);
-/* Volume in mliter of a cylinder at pressure 'p' */
-extern int gas_volume(const cylinder_t *cyl, pressure_t p);
-extern double gas_compressibility_factor(struct gasmix gas, double bar);
-extern double isothermal_pressure(struct gasmix gas, double p1, int volume1, int volume2);
-extern double gas_density(struct gasmix gas, int pressure);
-extern int same_gasmix(struct gasmix a, struct gasmix b);
-
-static inline int get_o2(struct gasmix mix)
-{
- return mix.o2.permille ?: O2_IN_AIR;
-}
-
-static inline int get_he(struct gasmix mix)
-{
- return mix.he.permille;
-}
-
-struct gas_pressures {
- double o2, n2, he;
-};
-
extern void fill_pressures(struct gas_pressures *pressures, const double amb_pressure, struct gasmix mix, double po2, enum divemode_t dctype);
-extern void sanitize_gasmix(struct gasmix *mix);
-extern int gasmix_distance(struct gasmix a, struct gasmix b);
-extern int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used);
-
-extern bool gasmix_is_air(struct gasmix gasmix);
-
/* Linear interpolation between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
static inline int interpolate(int a, int b, int part, int whole)
{
diff --git a/core/equipment.c b/core/equipment.c
index 325c57cb7..81033ace6 100644
--- a/core/equipment.c
+++ b/core/equipment.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
+#include <limits.h>
#include "equipment.h"
#include "gettext.h"
#include "dive.h"
@@ -101,6 +102,36 @@ const char *gasname(struct gasmix gasmix)
return gas;
}
+int gas_volume(const cylinder_t *cyl, pressure_t p)
+{
+ double bar = p.mbar / 1000.0;
+ double z_factor = gas_compressibility_factor(cyl->gasmix, bar);
+ return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
+}
+
+int find_best_gasmix_match(struct gasmix mix, const 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;
+}
+
bool weightsystem_none(const weightsystem_t *ws)
{
return !ws->weight.grams && !ws->description;
diff --git a/core/equipment.h b/core/equipment.h
index 73e21b8ed..eb789ede8 100644
--- a/core/equipment.h
+++ b/core/equipment.h
@@ -2,7 +2,7 @@
#ifndef EQUIPMENT_H
#define EQUIPMENT_H
-#include "units.h"
+#include "gas.h"
#ifdef __cplusplus
extern "C" {
@@ -10,15 +10,6 @@ extern "C" {
struct dive;
-// o2 == 0 && he == 0 -> air
-// o2 < 0 -> invalid
-struct gasmix {
- fraction_t o2;
- fraction_t he;
-};
-static const struct gasmix gasmix_invalid = { { -1 }, { -1 } };
-static const struct gasmix gasmix_air = { { 0 }, { 0 } };
-
enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NOT_USED, NUM_GAS_USE}; // The different uses for cylinders
typedef struct
@@ -63,6 +54,8 @@ extern bool weightsystem_none(const weightsystem_t *ws);
extern void remove_cylinder(struct dive *dive, int idx);
extern void remove_weightsystem(struct dive *dive, int idx);
extern void reset_cylinders(struct dive *dive, bool track_gas);
+extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */
+extern int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[], unsigned int used);
#ifdef DEBUG_CYL
extern void dump_cylinders(struct dive *dive, bool verbose);
#endif
diff --git a/core/gas.c b/core/gas.c
new file mode 100644
index 000000000..9f67d0b92
--- /dev/null
+++ b/core/gas.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "gas.h"
+#include "pref.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Perform isobaric counterdiffusion calculations for gas changes in trimix dives.
+ * Here we use the rule-of-fifths where, during a change involving trimix gas, the increase in nitrogen
+ * should not exceed one fifth of the decrease in helium.
+ * Parameters: 1) pointers to two gas mixes, the gas being switched from and the gas being switched to.
+ * 2) a pointer to an icd_data structure.
+ * Output: i) The icd_data stucture is filled with the delta_N2 and delta_He numbers (as permille).
+ * ii) Function returns a boolean indicating an exceeding of the rule-of-fifths. False = no icd problem.
+ */
+bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results)
+{
+ if (!prefs.show_icd)
+ return false;
+ results->dN2 = get_he(oldgasmix) + get_o2(oldgasmix) - get_he(newgasmix) - get_o2(newgasmix);
+ results->dHe = get_he(newgasmix) - get_he(oldgasmix);
+ return get_he(oldgasmix) > 0 && results->dN2 > 0 && results->dHe < 0 && get_he(oldgasmix) && results->dN2 > 0 && 5 * results->dN2 > -results->dHe;
+}
+
+static bool gasmix_is_invalid(struct gasmix mix)
+{
+ return mix.o2.permille < 0;
+}
+
+int same_gasmix(struct gasmix a, struct gasmix b)
+{
+ if (gasmix_is_invalid(a) || gasmix_is_invalid(b))
+ return 0;
+ if (gasmix_is_air(a) && gasmix_is_air(b))
+ return 1;
+ return a.o2.permille == b.o2.permille && a.he.permille == b.he.permille;
+}
+
+void sanitize_gasmix(struct gasmix *mix)
+{
+ unsigned int o2, he;
+
+ o2 = mix->o2.permille;
+ he = mix->he.permille;
+
+ /* Regular air: leave empty */
+ if (!he) {
+ if (!o2)
+ return;
+ /* 20.8% to 21% O2 is just air */
+ if (gasmix_is_air(*mix)) {
+ mix->o2.permille = 0;
+ return;
+ }
+ }
+
+ /* Sane mix? */
+ if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000)
+ return;
+ fprintf(stderr, "Odd gasmix: %u O2 %u He\n", o2, he);
+ memset(mix, 0, sizeof(*mix));
+}
+
+int gasmix_distance(struct gasmix a, struct gasmix b)
+{
+ int a_o2 = get_o2(a), b_o2 = get_o2(b);
+ int a_he = get_he(a), b_he = get_he(b);
+ int delta_o2 = a_o2 - b_o2, delta_he = a_he - b_he;
+
+ delta_he = delta_he * delta_he;
+ delta_o2 = delta_o2 * delta_o2;
+ return delta_he + delta_o2;
+}
+
+bool gasmix_is_air(struct gasmix gasmix)
+{
+ int o2 = gasmix.o2.permille;
+ int he = gasmix.he.permille;
+ return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
+}
diff --git a/core/gas.h b/core/gas.h
new file mode 100644
index 000000000..f5d948da0
--- /dev/null
+++ b/core/gas.h
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef GAS_H
+#define GAS_H
+
+#include "units.h"
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+// o2 == 0 && he == 0 -> air
+// o2 < 0 -> invalid
+struct gasmix {
+ fraction_t o2;
+ fraction_t he;
+};
+static const struct gasmix gasmix_invalid = { { -1 }, { -1 } };
+static const struct gasmix gasmix_air = { { 0 }, { 0 } };
+
+struct icd_data { // This structure provides communication between function isobaric_counterdiffusion() and the calling software.
+ int dN2; // The change in fraction (permille) of nitrogen during the change
+ int dHe; // The change in fraction (permille) of helium during the change
+};
+
+extern bool isobaric_counterdiffusion(struct gasmix oldgasmix, struct gasmix newgasmix, struct icd_data *results);
+
+extern double gas_compressibility_factor(struct gasmix gas, double bar);
+extern double isothermal_pressure(struct gasmix gas, double p1, int volume1, int volume2);
+extern double gas_density(struct gasmix gas, int pressure);
+extern int same_gasmix(struct gasmix a, struct gasmix b);
+
+static inline int get_o2(struct gasmix mix)
+{
+ return mix.o2.permille ?: O2_IN_AIR;
+}
+
+static inline int get_he(struct gasmix mix)
+{
+ return mix.he.permille;
+}
+
+struct gas_pressures {
+ double o2, n2, he;
+};
+
+extern void sanitize_gasmix(struct gasmix *mix);
+extern int gasmix_distance(struct gasmix a, struct gasmix b);
+
+extern bool gasmix_is_air(struct gasmix gasmix);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif