[PATCH] Show MOD, EAD, END and EADD

Jan Schubert Jan.Schubert at GMX.li
Sun Jan 13 12:43:43 PST 2013


This adds support to display MOD, EAD, AND and EADD in the mouse over dialog:

- MOD: Maximum Operation Depth based on a configurable limit
- EAD: Equivalent Air Depth considering N2 and (!) O2 narcotic
- END: Equivalent Nitrogen (Narcotic) Depth considering just N2 narcotic
(ignoring O2)
- EADD: Equivalent Air Density Depth

Please note that some people and even diving organisations have opposite definitions for EAD and END, but considering A stands for Air, lets choose the above. And considerung N for Nitrogen it also fits in this scheme.

This patch moves N2_IN_AIR from deco.c to dive.h as this is already used in several places and might be useful for future use also. It also respecifies N2_IN_AIR to a more
correct value of 78,084%, the former one also included all other gases than oxygen appearing in air. If someone needs to use the former value it would be more correct to use 1-O2_IN_AIR instead.

Signed-off-by: Jan Schubert / Jan.Schubert at GMX.li


--
diff --git a/deco.c b/deco.c
index 0005ba1..1a2d13a 100644
--- a/deco.c
+++ b/deco.c
@@ -78,7 +78,6 @@ const double
buehlmann_He_factor_expositon_one_second[] = {
        1.00198406028040E-004, 7.83611475491108E-005,
6.13689891868496E-005, 4.81280465299827E-005};
 
 #define WV_PRESSURE 0.0627 /* water vapor pressure */
-#define N2_IN_AIR 0.7902
 #define DECO_STOPS_MULTIPLIER_MM 3000.0
 
 #define GF_LOW_AT_MAXDEPTH 0
diff --git a/dive.h b/dive.h
index b80e6bf..40c83b8 100644
--- a/dive.h
+++ b/dive.h
@@ -11,6 +11,13 @@
 #include <libxml/tree.h>
 #include <openssl/sha.h>
 
+#define O2_IN_AIR 0.20942
+#define N2_IN_AIR 0.78084 // has been set to 0.7902 before to ignore
other components of air
+#define O2_DENSITY 1.429  // Gramm/Liter
+#define N2_DENSITY 1.251
+#define HE_DENSITY 0.1786
+
+
 /*
  * Some silly typedefs to make our units very explicit.
  *
diff --git a/gtk-gui.c b/gtk-gui.c
index 1bc3388..600bb37 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -439,6 +439,8 @@ OPTIONCALLBACK(cylinder_toggle,
prefs.visible_cols.cylinder)
 OPTIONCALLBACK(po2_toggle, prefs.pp_graphs.po2)
 OPTIONCALLBACK(pn2_toggle, prefs.pp_graphs.pn2)
 OPTIONCALLBACK(phe_toggle, prefs.pp_graphs.phe)
+OPTIONCALLBACK(mod_toggle, prefs.mod)
+OPTIONCALLBACK(ead_toggle, prefs.ead)
 OPTIONCALLBACK(red_ceiling_toggle, prefs.profile_red_ceiling)
 OPTIONCALLBACK(calc_ceiling_toggle, prefs.profile_calc_ceiling)
 OPTIONCALLBACK(calc_ceiling_3m_toggle, prefs.calc_ceiling_3m_incr)
@@ -529,9 +531,9 @@ static void preferences_dialog(GtkWidget *w,
gpointer data)
 {
        int result;
        GtkWidget *dialog, *notebook, *font, *frame, *box, *vbox,
*button, *xmlfile_button;
-       GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_gflow,
*entry_gfhigh;
+       GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_mod,
*entry_ead, *entry_gflow, *entry_gfhigh;
        const char *current_default, *new_default;
-       char threshold_text[10], utf8_buf[128];
+       char threshold_text[10], mod_text[10], utf8_buf[128];
        struct preferences oldprefs = prefs;
 
        dialog = gtk_dialog_new_with_buttons(_("Preferences"),
@@ -722,6 +724,31 @@ static void preferences_dialog(GtkWidget *w,
gpointer data)
        box = gtk_hbox_new(FALSE, 6);
        gtk_container_add(GTK_CONTAINER(vbox), box);
 
+       button = gtk_check_button_new_with_label(_("Show MOD"));
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.mod);
+       gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
+       g_signal_connect(G_OBJECT(button), "toggled",
G_CALLBACK(mod_toggle), &entry_mod);
+
+       frame = gtk_frame_new(_("max ppO2"));
+       gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6);
+       entry_mod = gtk_entry_new();
+       gtk_entry_set_max_length(GTK_ENTRY(entry_mod), 4);
+       snprintf(mod_text, sizeof(mod_text), "%.1f", prefs.mod_ppO2);
+       gtk_entry_set_text(GTK_ENTRY(entry_mod), mod_text);
+       gtk_widget_set_sensitive(entry_mod, prefs.mod);
+       gtk_container_add(GTK_CONTAINER(frame), entry_mod);
+
+       box = gtk_hbox_new(FALSE, 6);
+       gtk_container_add(GTK_CONTAINER(vbox), box);
+
+       button = gtk_check_button_new_with_label(_("Show EAD, END, EADD"));
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.ead);
+       gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
+       g_signal_connect(G_OBJECT(button), "toggled",
G_CALLBACK(ead_toggle), NULL);
+
+       box = gtk_hbox_new(FALSE, 6);
+       gtk_container_add(GTK_CONTAINER(vbox), box);
+
        button = gtk_check_button_new_with_label(_("Show dc reported
ceiling in red"));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
prefs.profile_red_ceiling);
        gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
@@ -766,7 +793,7 @@ static void preferences_dialog(GtkWidget *w,
gpointer data)
        gtk_widget_show_all(dialog);
        result = gtk_dialog_run(GTK_DIALOG(dialog));
        if (result == GTK_RESPONSE_ACCEPT) {
-               const char *po2_threshold_text, *pn2_threshold_text,
*phe_threshold_text, *gflow_text, *gfhigh_text;
+               const char *po2_threshold_text, *pn2_threshold_text,
*phe_threshold_text, *mod_text, *gflow_text, *gfhigh_text;
                /* Make sure to flush any modified old dive data with
old units */
                update_dive(NULL);
 
@@ -778,6 +805,8 @@ static void preferences_dialog(GtkWidget *w,
gpointer data)
                sscanf(pn2_threshold_text, "%lf",
&prefs.pp_graphs.pn2_threshold);
                phe_threshold_text =
gtk_entry_get_text(GTK_ENTRY(entry_phe));
                sscanf(phe_threshold_text, "%lf",
&prefs.pp_graphs.phe_threshold);
+               mod_text = gtk_entry_get_text(GTK_ENTRY(entry_mod));
+               sscanf(mod_text, "%lf", &prefs.mod_ppO2);
                gflow_text = gtk_entry_get_text(GTK_ENTRY(entry_gflow));
                sscanf(gflow_text, "%lf", &prefs.gflow);
                gfhigh_text = gtk_entry_get_text(GTK_ENTRY(entry_gfhigh));
diff --git a/main.c b/main.c
index a0cd313..b96c39f 100644
--- a/main.c
+++ b/main.c
@@ -27,6 +27,9 @@ struct preferences default_prefs = {
                .pn2_threshold =  4.0,
                .phe_threshold = 13.0,
        },
+       .mod  = FALSE,
+       .mod_ppO2  = 1.6,
+       .ead  = FALSE,
        .profile_red_ceiling  = FALSE,
        .profile_calc_ceiling = FALSE,
        .calc_ceiling_3m_incr = FALSE,
diff --git a/pref.h b/pref.h
index 342c9f6..7dd0e5a 100644
--- a/pref.h
+++ b/pref.h
@@ -25,6 +25,9 @@ struct preferences {
        struct units units;
        visible_cols_t visible_cols;
        partial_pressure_graphs_t pp_graphs;
+       gboolean mod;
+       double mod_ppO2;
+       gboolean ead;
        gboolean profile_red_ceiling;
        gboolean profile_calc_ceiling;
        gboolean calc_ceiling_3m_incr;
diff --git a/prefs.c b/prefs.c
index b6ae4ee..04db630 100644
--- a/prefs.c
+++ b/prefs.c
@@ -85,6 +85,9 @@ void save_preferences(void)
        SAVE_DOUBLE("pn2threshold", pp_graphs.pn2_threshold);
        SAVE_DOUBLE("phethreshold", pp_graphs.phe_threshold);
 
+       SAVE_BOOL("mod", mod);
+       SAVE_DOUBLE("modppO2", mod_ppO2);
+       SAVE_BOOL("ead", ead);
        SAVE_BOOL("redceiling", profile_red_ceiling);
        SAVE_BOOL("calcceiling", profile_calc_ceiling);
        SAVE_BOOL("calcceiling3m", calc_ceiling_3m_incr);
@@ -149,6 +152,13 @@ void load_preferences(void)
                sscanf(conf_value, "%lf", &prefs.pp_graphs.phe_threshold);
                free((void *)conf_value);
        }
+       GET_BOOL("mod", mod);
+       conf_value = subsurface_get_conf("modppO2");
+       if (conf_value) {
+               sscanf(conf_value, "%lf", &prefs.mod_ppO2);
+               free((void *)conf_value);
+       }
+       GET_BOOL("ead", ead);
        GET_BOOL("redceiling", profile_red_ceiling);
        GET_BOOL("calcceiling", profile_calc_ceiling);
        GET_BOOL("calcceiling3m", calc_ceiling_3m_incr);
diff --git a/profile.c b/profile.c
index ccca599..28fe22a 100644
--- a/profile.c
+++ b/profile.c
@@ -46,6 +46,7 @@ struct plot_data {
        int cns;
        int smoothed;
        double po2, pn2, phe;
+       double mod, ead, end, eadd;
        velocity_t velocity;
        struct plot_data *min[3];
        struct plot_data *max[3];
@@ -1820,6 +1821,7 @@ static void calculate_deco_information(struct dive
*dive, struct divecomputer *d
        int i;
        double amb_pressure;
        double surface_pressure = (dive->surface_pressure.mbar ?
dive->surface_pressure.mbar : 1013) / 1000.0;
+       const char *depth_unit;
 
        for (i = 1; i < pi->nr; i++) {
                int fo2, fhe, j, t0, t1;
@@ -1840,11 +1842,31 @@ static void calculate_deco_information(struct
dive *dive, struct divecomputer *d
                        entry->phe = (amb_pressure - po2) * ratio;
                        entry->pn2 = amb_pressure - po2 - entry->phe;
                        entry->po2 = po2;
+
+                        entry->ead  = (entry->depth/1000 + 10) *
(entry->po2+(amb_pressure-entry->po2)*(1-ratio))/amb_pressure - 10; //
no rounding! (equla to -9.5)
+                        entry->end  = (entry->depth/1000 + 10) *
(amb_pressure-entry->po2)*(1-ratio)/amb_pressure/N2_IN_AIR - 10;
+                        entry->eadd = (entry->depth/1000 + 10) *
(entry->po2/amb_pressure * O2_DENSITY + entry->pn2/amb_pressure *
N2_DENSITY + entry->phe/amb_pressure * HE_DENSITY) / (O2_IN_AIR *
O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10;
                } else {
                        entry->po2 = fo2 / 1000.0 * amb_pressure;
                        entry->phe = fhe / 1000.0 * amb_pressure;
                        entry->pn2 = (1000 - fo2 - fhe) / 1000.0 *
amb_pressure;
+
+                        entry->ead = (entry->depth/1000 + 10) * (1000 -
fhe) / 1000.0 - 10;
+                        entry->end = (entry->depth/1000 + 10) * (1000 -
fo2 - fhe) / 1000.0 / N2_IN_AIR - 10;
+                        entry->eadd = (entry->depth/1000 + 10) * (fo2 *
O2_DENSITY + (1-fo2-fhe) * N2_DENSITY + fhe * HE_DENSITY) / (O2_IN_AIR *
O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10;
                }
+               entry->mod = (prefs.mod_ppO2/fo2*1000 -1) *
(strcmp(depth_unit, "m") ? 33 : 10);
+
+               // Convert to Feet if necessary
+               get_depth_units(entry->depth, NULL, &depth_unit);
+               if(strcmp(depth_unit, "m"))
+               {
+                 entry->ead = mm_to_feet(entry->ead*1000);
+                 entry->end = mm_to_feet(entry->end*1000);
+                 entry->eadd = mm_to_feet(entry->eadd*1000);
+                 entry->mod = mm_to_feet(entry->mod*1000);
+               }
+
                if (entry->po2 > pi->maxpp)
                        pi->maxpp = entry->po2;
                if (entry->phe > pi->maxpp)
@@ -2141,6 +2163,14 @@ static void plot_string(struct plot_data *entry,
char *buf, size_t bufsize,
                memcpy(buf2, buf, bufsize);
                snprintf(buf, bufsize, "%s\npHe:%.2f", buf2, entry->phe);
        }
+       if (prefs.mod) {
+               memcpy(buf2, buf, bufsize);
+               snprintf(buf, bufsize, "%s\nMOD:%d%s", buf2,
(int)entry->mod, depth_unit);
+       }
+       if (prefs.ead) {
+               memcpy(buf2, buf, bufsize);
+               snprintf(buf, bufsize,
"%s\nEAD:%d%s\nEND:%d%s\nEADD:%d%s", buf2, (int)entry->ead, depth_unit,
(int)entry->end, depth_unit, (int)entry->eadd, depth_unit);
+       }
        free(buf2);
 }


More information about the subsurface mailing list