diff --git a/CHANGELOG.md b/CHANGELOG.md
index be63cb75d..42f8d88dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
+Planner: Add checkbox on considering oxygen narcotic
Desktop: register changes when clicking "done" on dive-site edit screen
Mobile: re-enable GPS location service icon in global drawer
Mobile: add support for editing the dive number of a dive
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index d7bf4606d..98fa5622f 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -3545,7 +3545,8 @@ image::images/PlannerWindow1.jpg["FIGURE: Dive planner startup window",align="ce
O~2~% according to the depth set. Set to ''*'' to calculate the best O~2~% for the dive maximum depth.
** MND: the gas Maximum Narcotic Depth (MND). Automatically calculated based on the Best Mix END
preference (default 30m / 98 ft). Editing this field will modify the He% according to the depth set.
- Set to ''*'' to calculate the best He% for the dive maximum depth.
+ Set to ''*'' to calculate the best He% for the dive maximum depth. Depending on the checkbox, oxygen
+ is considered narcotic (the END is used) or not (the EAD is used).
- The profile of the planned dive can be created in two ways:
* Drag the waypoints
diff --git a/core/dive.c b/core/dive.c
index d845d8077..9788e64c7 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -3761,13 +3761,17 @@ fraction_t best_o2(depth_t depth, const struct dive *dive)
}
//Calculate He in best mix. O2 is considered narcopic
-fraction_t best_he(depth_t depth, const struct dive *dive)
+fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2)
{
fraction_t fhe;
int pnarcotic, ambient;
pnarcotic = depth_to_mbar(prefs.bestmixend.mm, dive);
ambient = depth_to_mbar(depth.mm, dive);
- fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent
+ if (o2narcotic) {
+ fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent
+ } else {
+ fhe.permille = 1000 - fo2.permille - N2_IN_AIR * pnarcotic / ambient;
+ }
if (fhe.permille < 0)
fhe.permille = 0;
return fhe;
diff --git a/core/dive.h b/core/dive.h
index 87aa3e5fd..6d1bd450d 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -226,7 +226,7 @@ extern int explicit_first_cylinder(const struct dive *dive, const struct divecom
extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time);
extern fraction_t best_o2(depth_t depth, const struct dive *dive);
-extern fraction_t best_he(depth_t depth, const struct dive *dive);
+extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2);
extern int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null);
extern int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity);
diff --git a/core/pref.h b/core/pref.h
index 50e13a117..f7af35415 100644
--- a/core/pref.h
+++ b/core/pref.h
@@ -160,6 +160,7 @@ struct preferences {
bool display_variations;
bool doo2breaks;
bool dobailout;
+ bool o2narcotic;
bool drop_stone_mode;
bool last_stop; // At 6m?
int min_switch_duration; // seconds
diff --git a/core/settings/qPrefDivePlanner.cpp b/core/settings/qPrefDivePlanner.cpp
index f33b390cf..e094bfed0 100644
--- a/core/settings/qPrefDivePlanner.cpp
+++ b/core/settings/qPrefDivePlanner.cpp
@@ -35,6 +35,7 @@ void qPrefDivePlanner::loadSync(bool doSync)
disk_display_variations(doSync);
disk_doo2breaks(doSync);
disk_dobailout(doSync);
+ disk_o2narcotic(doSync);
disk_drop_stone_mode(doSync);
disk_last_stop(doSync);
disk_min_switch_duration(doSync);
@@ -76,6 +77,7 @@ HANDLE_PREFERENCE_BOOL(DivePlanner, "display_variations", display_variations);
HANDLE_PREFERENCE_BOOL(DivePlanner, "doo2breaks", doo2breaks);
HANDLE_PREFERENCE_BOOL(DivePlanner, "dobailbout", dobailout);
+HANDLE_PREFERENCE_BOOL(DivePlanner, "o2narcotic", o2narcotic);
HANDLE_PREFERENCE_BOOL(DivePlanner, "drop_stone_mode", drop_stone_mode);
diff --git a/core/settings/qPrefDivePlanner.h b/core/settings/qPrefDivePlanner.h
index 09d8fabae..7a75fa4ce 100644
--- a/core/settings/qPrefDivePlanner.h
+++ b/core/settings/qPrefDivePlanner.h
@@ -23,6 +23,7 @@ class qPrefDivePlanner : public QObject {
Q_PROPERTY(bool display_variations READ display_variations WRITE set_display_variations NOTIFY display_variationsChanged);
Q_PROPERTY(bool doo2breaks READ doo2breaks WRITE set_doo2breaks NOTIFY doo2breaksChanged);
Q_PROPERTY(bool dobailout READ dobailout WRITE set_dobailout NOTIFY dobailoutChanged);
+ Q_PROPERTY(bool o2narcotic READ o2narcotic WRITE set_o2narcotic NOTIFY o2narcoticChanged)
Q_PROPERTY(bool drop_stone_mode READ drop_stone_mode WRITE set_drop_stone_mode NOTIFY drop_stone_modeChanged);
Q_PROPERTY(bool last_stop READ last_stop WRITE set_last_stop NOTIFY last_stopChanged);
Q_PROPERTY(int min_switch_duration READ min_switch_duration WRITE set_min_switch_duration NOTIFY min_switch_durationChanged);
@@ -60,6 +61,7 @@ public:
static bool display_variations() { return prefs.display_variations; }
static bool doo2breaks() { return prefs.doo2breaks; }
static bool dobailout() { return prefs.dobailout; }
+ static bool o2narcotic() { return prefs.o2narcotic; }
static bool drop_stone_mode() { return prefs.drop_stone_mode; }
static bool last_stop() { return prefs.last_stop; }
static int min_switch_duration() { return prefs.min_switch_duration; }
@@ -89,6 +91,7 @@ public slots:
static void set_display_variations(bool value);
static void set_doo2breaks(bool value);
static void set_dobailout(bool value);
+ static void set_o2narcotic(bool value);
static void set_drop_stone_mode(bool value);
static void set_last_stop(bool value);
static void set_min_switch_duration(int value);
@@ -118,6 +121,7 @@ signals:
void display_variationsChanged(bool value);
void doo2breaksChanged(bool value);
void dobailoutChanged(bool value);
+ void o2narcoticChanged(bool value);
void drop_stone_modeChanged(bool value);
void last_stopChanged(bool value);
void min_switch_durationChanged(int value);
@@ -148,6 +152,7 @@ private:
static void disk_display_variations(bool doSync);
static void disk_doo2breaks(bool doSync);
static void disk_dobailout(bool doSync);
+ static void disk_o2narcotic(bool doSync);
static void disk_drop_stone_mode(bool doSync);
static void disk_last_stop(bool doSync);
static void disk_min_switch_duration(bool doSync);
diff --git a/core/subsurfacestartup.c b/core/subsurfacestartup.c
index 8b7c14179..920285b14 100644
--- a/core/subsurfacestartup.c
+++ b/core/subsurfacestartup.c
@@ -73,6 +73,7 @@ struct preferences default_prefs = {
.display_duration = true,
.display_transitions = true,
.display_variations = false,
+ .o2narcotic = true,
.safetystop = true,
.bottomsac = 20000,
.decosac = 17000,
diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp
index 33caffd0d..663bb03fb 100644
--- a/desktop-widgets/diveplanner.cpp
+++ b/desktop-widgets/diveplanner.cpp
@@ -451,6 +451,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
ui.backgasBreaks->setChecked(prefs.doo2breaks);
setBailout(false);
setBailoutVisibility(false);
+ ui.o2narcotic->setChecked(prefs.o2narcotic);
ui.drop_stone_mode->setChecked(prefs.drop_stone_mode);
ui.switch_at_req_stop->setChecked(prefs.switch_at_req_stop);
ui.min_switch_duration->setValue(prefs.min_switch_duration / 60);
@@ -496,6 +497,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
connect(ui.vpmb_conservatism, SIGNAL(valueChanged(int)), plannerModel, SLOT(setVpmbConservatism(int)));
connect(ui.backgasBreaks, SIGNAL(toggled(bool)), this, SLOT(setBackgasBreaks(bool)));
connect(ui.bailout, SIGNAL(toggled(bool)), this, SLOT(setBailout(bool)));
+ connect(ui.o2narcotic, SIGNAL(toggled(bool)), this, SLOT(setO2narcotic(bool)));
connect(ui.switch_at_req_stop, SIGNAL(toggled(bool)), plannerModel, SLOT(setSwitchAtReqStop(bool)));
connect(ui.min_switch_duration, SIGNAL(valueChanged(int)), plannerModel, SLOT(setMinSwitchDuration(int)));
connect(ui.surface_segment, SIGNAL(valueChanged(int)), plannerModel, SLOT(setSurfaceSegment(int)));
@@ -504,6 +506,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
connect(ui.bottompo2, SIGNAL(valueChanged(double)), CylindersModel::instance(), SLOT(updateBestMixes()));
connect(ui.bestmixEND, SIGNAL(valueChanged(int)), CylindersModel::instance(), SLOT(updateBestMixes()));
+ connect(ui.o2narcotic, SIGNAL(toggled(bool)), CylindersModel::instance(), SLOT(updateBestMixes()));
connect(modeMapper, SIGNAL(mapped(int)), this, SLOT(disableDecoElements(int)));
connect(ui.ascRate75, SIGNAL(valueChanged(int)), this, SLOT(setAscrate75(int)));
@@ -679,6 +682,12 @@ void PlannerSettingsWidget::setBailout(bool dobailout)
plannerModel->emitDataChanged();
}
+void PlannerSettingsWidget::setO2narcotic(bool o2narcotic)
+{
+ qPrefDivePlanner::instance()->set_o2narcotic(o2narcotic);
+ plannerModel->emitDataChanged();
+}
+
void PlannerSettingsWidget::setBailoutVisibility(int mode)
{
ui.bailout->setDisabled(!(mode == CCR || mode == PSCR));
diff --git a/desktop-widgets/diveplanner.h b/desktop-widgets/diveplanner.h
index 6d17c956b..e9e7808b9 100644
--- a/desktop-widgets/diveplanner.h
+++ b/desktop-widgets/diveplanner.h
@@ -86,6 +86,7 @@ slots:
void setBestmixEND(int depth);
void setBackgasBreaks(bool dobreaks);
void setBailout(bool dobailout);
+ void setO2narcotic(bool o2narcotic);
void disableDecoElements(int mode);
void disableBackgasBreaks(bool enabled);
void setDiveMode(int mode);
diff --git a/desktop-widgets/plannerSettings.ui b/desktop-widgets/plannerSettings.ui
index f22d0db45..33e3d2456 100644
--- a/desktop-widgets/plannerSettings.ui
+++ b/desktop-widgets/plannerSettings.ui
@@ -561,6 +561,83 @@
2
+ -
+
+
+ Notes
+
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
-
+
+
+ Verbatim dive plan
+
+
+
+ -
+
+
+ In diveplan, list transitions or treat them as implicit
+
+
+ Display transitions in deco
+
+
+
+ -
+
+
+ In dive plan, show runtime (absolute time) of stops
+
+
+ Display runtime
+
+
+
+ -
+
+
+ true
+
+
+ In dive plan, show duration (relative time) of stops
+
+
+ Display segment duration
+
+
+
+ -
+
+
+ true
+
+
+ Compute variations of plan (performance cost)
+
+
+ Display plan variations
+
+
+
+
+
+
-
@@ -581,7 +658,7 @@
- -
+
-
Qt::Vertical
@@ -594,7 +671,7 @@
- -
+
-
Qt::Vertical
@@ -692,83 +769,6 @@
- -
-
-
- Notes
-
-
-
- 2
-
-
- 2
-
-
- 2
-
-
- 2
-
-
- 2
-
-
-
-
-
- Verbatim dive plan
-
-
-
- -
-
-
- In diveplan, list transitions or treat them as implicit
-
-
- Display transitions in deco
-
-
-
- -
-
-
- In dive plan, show runtime (absolute time) of stops
-
-
- Display runtime
-
-
-
- -
-
-
- true
-
-
- In dive plan, show duration (relative time) of stops
-
-
- Display segment duration
-
-
-
- -
-
-
- true
-
-
- Compute variations of plan (performance cost)
-
-
- Display plan variations
-
-
-
-
-
-
-
@@ -831,6 +831,16 @@
+ -
+
+
+ Treat oxygen as narcotic when computing best mix
+
+
+ O₂ narcotic
+
+
+
diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp
index 95c6aace2..a05cef23f 100644
--- a/qt-models/cylindermodel.cpp
+++ b/qt-models/cylindermodel.cpp
@@ -391,11 +391,11 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
if (QString::compare(qPrintable(vString), "*") == 0) {
cyl->bestmix_he = true;
// Calculate fO2 for max. depth
- cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive);
+ cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
} else {
cyl->bestmix_he = false;
// Calculate fHe for input depth
- cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive);
+ cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
}
changed = true;
}
@@ -605,7 +605,7 @@ bool CylindersModel::updateBestMixes()
gasUpdated = true;
}
if (cyl->bestmix_he) {
- cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive);
+ cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
// fO2 + fHe must not be greater than 1
if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000)
cyl->gasmix.o2.permille = 1000 - get_he(cyl->gasmix);