aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGravatar Tim Segers <tsegers@pm.me>2023-01-04 12:58:59 +0100
committerGravatar Tim Segers <tsegers@pm.me>2023-01-07 15:24:51 +0100
commit70d7bb650ad46a4237afd27cfd595812eb040701 (patch)
tree88fa2889132c756ced9b86a87b8ea4e5d5204d47
parent5737a0996df3b9f11d541cc45c7e32ae3b9a7aac (diff)
downloadopendeco-70d7bb650ad46a4237afd27cfd595812eb040701.tar.gz
Add support for imperial units
Implements: https://todo.sr.ht/~tsegers/opendeco/1
-rw-r--r--opendeco.toml1
-rw-r--r--src/deco.c32
-rw-r--r--src/deco.h12
-rw-r--r--src/opendeco-cli.c4
-rw-r--r--src/opendeco-conf.c5
-rw-r--r--src/opendeco-conf.h3
-rw-r--r--src/opendeco.c14
-rw-r--r--src/output.c9
8 files changed, 70 insertions, 10 deletions
diff --git a/opendeco.toml b/opendeco.toml
index 4884ee5..e549e03 100644
--- a/opendeco.toml
+++ b/opendeco.toml
@@ -2,6 +2,7 @@
gas = "Air" # Bottom gas used during the dive
surface_pressure = 1.01325 # Surface air pressure [bar]
rmv = 20 # RMV during the dive portion of the dive [l/min]
+imperial = false # Use imperial units
[deco]
gflow = 30 # Gradient factor at the first stop
diff --git a/src/deco.c b/src/deco.c
index e1ea401..349c8e5 100644
--- a/src/deco.c
+++ b/src/deco.c
@@ -9,6 +9,7 @@
#define RND(x) (round((x) *10000) / 10000)
enum ALGO ALGO_VER = ALGO_VER_DEFAULT;
+enum UNITS UNITS = UNITS_DEFAULT;
double SURFACE_PRESSURE = SURFACE_PRESSURE_DEFAULT;
double P_WV = P_WV_DEFAULT;
@@ -77,6 +78,37 @@ double msw_to_bar(double msw)
return msw / 10;
}
+double bar_to_fsw(double bar)
+{
+ return (bar / 1.01325) * 33.0;
+}
+
+double fsw_to_bar(double fsw)
+{
+ return (fsw * 1.01325) / 33.0;
+}
+
+double msw_or_fsw(double msw, double fsw)
+{
+ assert(UNITS == METRIC || UNITS == IMPERIAL);
+
+ return (UNITS == METRIC) ? msw : fsw;
+}
+
+double xsw_to_bar(double xsw)
+{
+ assert(UNITS == METRIC || UNITS == IMPERIAL);
+
+ return (UNITS == METRIC) ? msw_to_bar(xsw) : fsw_to_bar(xsw);
+}
+
+double bar_to_xsw(double bar)
+{
+ assert(UNITS == METRIC || UNITS == IMPERIAL);
+
+ return (UNITS == METRIC) ? bar_to_msw(bar) : bar_to_fsw(bar);
+}
+
double abs_depth(double gd)
{
return gd + SURFACE_PRESSURE;
diff --git a/src/deco.h b/src/deco.h
index 35905ca..2500580 100644
--- a/src/deco.h
+++ b/src/deco.h
@@ -14,6 +14,7 @@
#define P_WV_SCHR 0.0493 /* Schreiner value, Rq = 0.8, most conservative */
#define ALGO_VER_DEFAULT ZHL_16C
+#define UNITS_DEFAULT METRIC
#define SURFACE_PRESSURE_DEFAULT 1.01325
#define P_WV_DEFAULT P_WV_BUHL
@@ -25,6 +26,11 @@
#define MOD_AUTO 0
/* types */
+enum UNITS {
+ METRIC,
+ IMPERIAL,
+};
+
enum ALGO {
ZHL_16A = 0,
ZHL_16B = 1,
@@ -50,6 +56,7 @@ typedef struct gas_t {
/* global variables */
extern enum ALGO ALGO_VER;
+extern enum UNITS UNITS;
extern double SURFACE_PRESSURE;
extern double P_WV;
@@ -61,6 +68,11 @@ extern int LAST_STOP_AT_SIX;
/* functions */
double bar_to_msw(double bar);
double msw_to_bar(double msw);
+double bar_to_fsw(double bar);
+double fsw_to_bar(double msw);
+double msw_or_fsw(double msw, double fsw);
+double xsw_to_bar(double xsw);
+double bar_to_xsw(double bar);
double abs_depth(double gd);
double gauge_depth(double ad);
diff --git a/src/opendeco-cli.c b/src/opendeco-cli.c
index 5f6b627..d8da388 100644
--- a/src/opendeco-cli.c
+++ b/src/opendeco-cli.c
@@ -26,6 +26,7 @@ static struct argp_option options[] = {
{"gas", 'g', "STRING", 0, "Set the bottom gas used during the dive, defaults to Air", 2 },
{"pressure", 'p', "NUMBER", 0, "Set the surface air pressure, defaults to 1.01325bar or 1atm", 3 },
{"rmv", 'r', "NUMBER", 0, "Set the RMV during the dive portion of the dive, defaults to 20", 4 },
+ {"imperial", 'i', 0, 0, "Use imperial units (fsw)", 5 },
{0, 0, 0, 0, "Deco options:", 0 },
{"gflow", 'L', "NUMBER", 0, "Set the gradient factor at the first stop, defaults to 30", 5 },
@@ -83,6 +84,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 'r':
arguments->RMV_DIVE = arg ? atof(arg) : -1;
break;
+ case 'i':
+ arguments->UNITS = IMPERIAL;
+ break;
case 'L':
arguments->gflow = arg ? atoi(arg) : -1;
break;
diff --git a/src/opendeco-conf.c b/src/opendeco-conf.c
index e044c90..977bfc5 100644
--- a/src/opendeco-conf.c
+++ b/src/opendeco-conf.c
@@ -49,6 +49,11 @@ int opendeco_conf_parse(const char *confpath, struct arguments *arguments)
if (r.ok)
arguments->RMV_DIVE = r.u.d;
+
+ toml_datum_t i = toml_bool_in(dive, "imperial");
+
+ if (i.ok)
+ arguments->UNITS = i.u.b ? IMPERIAL : METRIC;
}
toml_table_t *deco = toml_table_in(od_conf, "deco");
diff --git a/src/opendeco-conf.h b/src/opendeco-conf.h
index 8845409..359889a 100644
--- a/src/opendeco-conf.h
+++ b/src/opendeco-conf.h
@@ -3,6 +3,8 @@
#ifndef OPENDECOCONF_H
#define OPENDECOCONF_H
+#include "deco.h"
+
#ifndef VERSION
#define VERSION "unknown version"
#endif
@@ -21,6 +23,7 @@ struct arguments {
double RMV_DIVE;
double RMV_DECO;
int SHOW_TRAVEL;
+ enum UNITS UNITS;
};
int opendeco_conf_parse(const char *confpath, struct arguments *arguments);
diff --git a/src/opendeco.c b/src/opendeco.c
index 029a81f..fe9a1d1 100644
--- a/src/opendeco.c
+++ b/src/opendeco.c
@@ -12,7 +12,7 @@
#include "output.h"
#include "schedule.h"
-#define MOD_OXY (abs_depth(msw_to_bar(6)))
+#define MOD_OXY (abs_depth(xsw_to_bar(msw_or_fsw(6, 20))))
#define RMV_DIVE_DEFAULT 20
#define RMV_DECO_DEFAULT 15
@@ -154,6 +154,7 @@ int main(int argc, char *argv[])
.RMV_DIVE = RMV_DIVE_DEFAULT,
.RMV_DECO = RMV_DECO_DEFAULT,
.SHOW_TRAVEL = SHOW_TRAVEL_DEFAULT,
+ .UNITS = UNITS_DEFAULT,
};
opendeco_conf_parse("opendeco.toml", &arguments);
@@ -166,11 +167,12 @@ int main(int argc, char *argv[])
RMV_DIVE = arguments.RMV_DIVE;
RMV_DECO = arguments.RMV_DECO;
SHOW_TRAVEL = arguments.SHOW_TRAVEL;
+ UNITS = arguments.UNITS;
/* setup */
decostate_t ds;
- init_decostate(&ds, arguments.gflow, arguments.gfhigh, msw_to_bar(3));
- double dec_per_min = msw_to_bar(9);
+ init_decostate(&ds, arguments.gflow, arguments.gfhigh, xsw_to_bar(msw_or_fsw(3, 10)));
+ double dec_per_min = xsw_to_bar(msw_or_fsw(9, 30));
gas_t bottom_gas;
scan_gas(&bottom_gas, arguments.gas);
@@ -184,12 +186,12 @@ int main(int argc, char *argv[])
deco_gasses[i].mod = MOD_OXY;
/* simulate dive */
- double descent_time = msw_to_bar(arguments.depth) / dec_per_min;
+ double descent_time = xsw_to_bar(arguments.depth) / dec_per_min;
double bottom_time = max(1, arguments.time - descent_time);
waypoint_t waypoints[] = {
- {.depth = abs_depth(msw_to_bar(arguments.depth)), .time = descent_time, &bottom_gas},
- {.depth = abs_depth(msw_to_bar(arguments.depth)), .time = bottom_time, &bottom_gas},
+ {.depth = abs_depth(xsw_to_bar(arguments.depth)), .time = descent_time, &bottom_gas},
+ {.depth = abs_depth(xsw_to_bar(arguments.depth)), .time = bottom_time, &bottom_gas},
};
waypoint_callback_t print_segment_callback = {
diff --git a/src/output.c b/src/output.c
index 52b45dd..5997f31 100644
--- a/src/output.c
+++ b/src/output.c
@@ -69,8 +69,8 @@ void print_planline(wchar_t sign, double depth, double time, double runtime, con
static gas_t last_gas;
- const int depth_m = round(bar_to_msw(gauge_depth(depth)));
- const int ead_m = round(bar_to_msw(max(0, gauge_depth(ead(depth, gas)))));
+ const int depth_x = round(bar_to_xsw(gauge_depth(depth)));
+ const int ead_x = round(bar_to_xsw(max(0, gauge_depth(ead(depth, gas)))));
wchar_t swi = L' ';
@@ -86,14 +86,15 @@ void print_planline(wchar_t sign, double depth, double time, double runtime, con
/* only print ead and pO2 on stops */
if (sign == LVL) {
- snprintf(eadbuf, 4, "%3i", ead_m);
+ snprintf(eadbuf, 4, "%3i", ead_x);
snprintf(pO2buf, 5, "%4.2f", ppO2(depth, gas));
} else {
snprintf(eadbuf, 4, "%3s", "-");
snprintf(pO2buf, 5, "%4s", "-");
}
- wprintf(L" %lc %4im %8s %-7s %lc %-9s %s %s\n", sign, depth_m, timbuf, runbuf, swi, gasbuf, pO2buf, eadbuf);
+ wprintf(L" %lc %4i%s %8s %-7s %lc %-9s %s %s\n", sign, depth_x, (UNITS == METRIC) ? "m" : "ft", timbuf,
+ runbuf, swi, gasbuf, pO2buf, eadbuf);
}
void print_planfoot(const decostate_t *ds)