summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/dive.c60
-rw-r--r--core/dive.h5
-rw-r--r--core/plannernotes.c16
-rw-r--r--core/profile.c16
m---------libdivecomputer0
5 files changed, 89 insertions, 8 deletions
diff --git a/core/dive.c b/core/dive.c
index 1ce8421fe..680635e8f 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -241,6 +241,63 @@ void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
}
}
+struct event *get_next_divemodechange(struct event **evd)
+{ /* Starting at the event pointed to by evd, find the next divemode change event and initialise its
+ * type and divemode. Requires an external pointer (evd) to a divemode change event, usually
+ * initialised to dc->events. This function is self-tracking and the value of evd needs no
+ * setting or manipulation outside of this function. */
+ struct event *ev = *evd;
+ while (ev) { // Step through the events.
+ for (int i=0; i<3; i++) { // For each event name search for one of the above strings
+ if (!strcmp(ev->name,divemode_text[i])) { // if the event name is one of the divemode names
+ ev->type = DIVEMODECHANGE_EVENTTYPE + i;
+ ev->divemode = i; // set the event type to the dive mode
+ *evd = ev->next;
+ return (ev);
+ }
+ }
+ ev = ev->next;
+ }
+ *evd = NULL;
+ return (NULL);
+}
+
+struct event *peek_next_divemodechange(struct event *evd)
+{ // Starting at event evd, return the subsequent divemode change event, remembering its divemode.
+ struct event *ev = evd;
+ while (ev) { // Step through the events.
+ for (int i=0; i<3; i++) { // For each event name search for one of the above strings
+ if (!strcmp(ev->name,divemode_text[i])) { // if the event name is one of the divemode names
+ ev->divemode = i;
+ return (ev); // ... then return the event.
+ }
+ }
+ ev = ev->next;
+ }
+ return (NULL);
+}
+
+enum dive_comp_type get_divemode_at_time(struct divecomputer *dc, int dtime, struct event **ev_dmc)
+{ /* For a particular dive computer and its linked list of events, find the divemode dtime seconds
+ * into the dive. Requires an external pointer (ev_dmc) to a divemode change event, usually
+ * initialised by a call to get_next_divemodechange(dc->events). This function is self-tracking
+ * and the value of ev_dmc needs no setting or manipulation outside of this function. */
+ enum dive_comp_type mode;
+ struct event *ev = *ev_dmc; // ev_dmc points to event initialised by get_next_divemodechange()
+ if (!ev)
+ mode = dc->divemode; // if there is no divemodechange event, default to dc->divemode
+ else {
+ mode = ev->divemode; // If there is a starting divemodechange event, use the divemode of that event.
+ while (ev && (dtime >= ev->time.seconds)) { // If dtime is AFTER this event time, store divemode
+ mode = ev->divemode;
+ *ev_dmc = ev;
+ ev = peek_next_divemodechange(ev->next); // peek at the time of the following divemode change event
+ }
+ }
+ return (mode);
+}
+
+
/* this returns a pointer to static variable - so use it right away after calling */
struct gasmix *get_gasmix_from_event(struct dive *dive, struct event *ev)
{
@@ -2050,11 +2107,12 @@ int gasmix_distance(const struct gasmix *a, const struct gasmix *b)
* amb_pressure = ambient pressure applicable to the record in calling function
* *pressures = structure for communicating o2 sensor values from and gas pressures to the calling function.
* *mix = structure containing cylinder gas mixture information.
+ * 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, const struct gasmix *mix, double po2, enum dive_comp_type divemode)
{
- if (po2) { // This is probably a CCR dive where pressures->o2 is defined
+ if ((divemode != OC) && po2) { // This is a rebreather dive where pressures->o2 is defined
if (po2 >= amb_pressure) {
pressures->o2 = amb_pressure;
pressures->n2 = pressures->he = 0.0;
diff --git a/core/dive.h b/core/dive.h
index 9d1805b86..4e45ca860 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -14,7 +14,6 @@
#include <string.h>
#include <sys/stat.h>
#include "divesite.h"
-
#include <libxml/tree.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
@@ -92,6 +91,7 @@ struct event {
* case, the get_cylinder_index() function will give the best
* match with the cylinders in the dive based on gasmix.
*/
+ enum dive_comp_type divemode;
struct {
int index;
struct gasmix mix;
@@ -364,6 +364,9 @@ struct dive_components {
unsigned int weights : 1;
};
+extern struct event *get_next_divemodechange(struct event **evd);
+extern enum dive_comp_type get_divemode_at_time(struct divecomputer *dc, int dtime, struct event **ev_dmc);
+
/* picture list and methods related to dive picture handling */
struct picture {
char *filename;
diff --git a/core/plannernotes.c b/core/plannernotes.c
index 1b28252d3..269b391a8 100644
--- a/core/plannernotes.c
+++ b/core/plannernotes.c
@@ -537,12 +537,26 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
/* Print warnings for pO2 */
dp = diveplan->dp;
bool o2warning_exist = false;
+ enum dive_comp_type current_divemode;
+ double amb;
+ struct event *nextev, *evd = dive->dc.events;
+
+ current_divemode = dive->dc.divemode;
+ nextev = get_next_divemodechange(&evd);
+
if (dive->dc.divemode != CCR) {
while (dp) {
if (dp->time != 0) {
struct gas_pressures pressures;
struct gasmix *gasmix = &dive->cylinder[dp->cylinderid].gasmix;
- fill_pressures(&pressures, depth_to_atm(dp->depth.mm, dive), gasmix, 0.0, dive->dc.divemode);
+
+ if (nextev && (dp->time >= nextev->time.seconds)) { // If there are divemode changes and divedatapoint time
+ current_divemode = nextev->divemode; // has reached that of the current divemode event, then set the
+ nextev = get_next_divemodechange(&evd); // current divemode and find the next divemode event
+ }
+
+ amb = depth_to_atm(dp->depth.mm, dive);
+ fill_pressures(&pressures, amb, gasmix, (current_divemode == OC) ? 0.0 : amb * gasmix->o2.permille / 1000.0, current_divemode);
if (pressures.o2 > (dp->entered ? prefs.bottompo2 : prefs.decopo2) / 1000.0) {
const char *depth_unit;
diff --git a/core/profile.c b/core/profile.c
index 1bdb8e956..bfe8c223c 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -1200,19 +1200,25 @@ static int calculate_ccr_po2(struct plot_data *entry, struct divecomputer *dc)
static void calculate_gas_information_new(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{
int i;
+ enum dive_comp_type current_divemode;
double amb_pressure;
struct gasmix *gasmix = NULL;
- struct event *ev = NULL;
+ struct event *nextev, *evg = NULL, *evd = dc->events;
+
+ current_divemode = dc->divemode;
+ nextev = get_next_divemodechange(&evd);
for (i = 1; i < pi->nr; i++) {
int fn2, fhe;
struct plot_data *entry = pi->entry + i;
- gasmix = get_gasmix(dive, dc, entry->sec, &ev, gasmix);
-
+ gasmix = get_gasmix(dive, dc, entry->sec, &evg, gasmix);
+ if (nextev && (entry->sec > nextev->time.seconds)) { // If there are divemode changes and sample time
+ current_divemode = nextev->divemode; // has reached that of the current divemode event, then set the
+ nextev = get_next_divemodechange(&evd); // current divemode and find the next divemode event
+ }
amb_pressure = depth_to_bar(entry->depth, dive);
-
- fill_pressures(&entry->pressures, amb_pressure, gasmix, entry->o2pressure.mbar / 1000.0, dive->dc.divemode);
+ fill_pressures(&entry->pressures, amb_pressure, gasmix, (current_divemode == OC) ? 0.0 : entry->o2pressure.mbar / 1000.0, current_divemode);
fn2 = (int)(1000.0 * entry->pressures.n2 / amb_pressure);
fhe = (int)(1000.0 * entry->pressures.he / amb_pressure);
if (dc->divemode == PSCR) // OC pO2 is calulated for PSCR with or without external PO2 monitoring.
diff --git a/libdivecomputer b/libdivecomputer
-Subproject e0761561e959dbfa7922ac2942fce4c044eef71
+Subproject e97a47cca55973199715df0f818b4955e60d3a3