summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/dive.c10
-rw-r--r--core/gaspressures.c205
-rw-r--r--core/profile.c191
-rw-r--r--core/profile.h9
-rw-r--r--profile-widget/diveprofileitem.cpp131
-rw-r--r--profile-widget/profilewidget2.cpp2
-rw-r--r--profile-widget/tankitem.cpp10
-rw-r--r--qt-models/diveplotdatamodel.cpp2
8 files changed, 274 insertions, 286 deletions
diff --git a/core/dive.c b/core/dive.c
index 42ef687ef..d07a9d2aa 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -1498,24 +1498,26 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
/* Walk the samples from the beginning to find starting pressures.. */
for (i = 0; i < dc->samples; i++) {
+ int idx;
struct sample *sample = dc->sample + i;
if (sample->depth.mm < SURFACE_THRESHOLD)
continue;
- fixup_start_pressure(dive, sample->sensor[0], sample->pressure[0]);
- fixup_start_pressure(dive, sample->sensor[1], sample->pressure[1]);
+ for (idx = 0; idx < MAX_SENSORS; idx++)
+ fixup_start_pressure(dive, sample->sensor[idx], sample->pressure[idx]);
}
/* ..and from the end for ending pressures */
for (i = dc->samples; --i >= 0; ) {
+ int idx;
struct sample *sample = dc->sample + i;
if (sample->depth.mm < SURFACE_THRESHOLD)
continue;
- fixup_end_pressure(dive, sample->sensor[0], sample->pressure[0]);
- fixup_end_pressure(dive, sample->sensor[1], sample->pressure[1]);
+ for (idx = 0; idx < MAX_SENSORS; idx++)
+ fixup_end_pressure(dive, sample->sensor[idx], sample->pressure[idx]);
}
simplify_dc_pressures(dc);
diff --git a/core/gaspressures.c b/core/gaspressures.c
index 86ea8de7a..13196b61f 100644
--- a/core/gaspressures.c
+++ b/core/gaspressures.c
@@ -64,18 +64,20 @@ static void list_free(pr_track_t *list)
}
#ifdef DEBUG_PR_TRACK
-static void dump_pr_track(pr_track_t **track_pr)
+static void dump_pr_track(int cyl, pr_track_t *track_pr)
{
- int cyl;
pr_track_t *list;
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
- list = track_pr[cyl];
- while (list) {
- printf("cyl%d: start %d end %d t_start %d t_end %d pt %d\n", cyl,
- list->start, list->end, list->t_start, list->t_end, list->pressure_time);
- list = list->next;
- }
+ printf("cyl%d:\n", cyl);
+ list = track_pr;
+ while (list) {
+ printf(" start %d end %d t_start %d:%02d t_end %d:%02d pt %d\n",
+ mbar_to_PSI(list->start),
+ mbar_to_PSI(list->end),
+ FRACTION(list->t_start, 60),
+ FRACTION(list->t_end, 60),
+ list->pressure_time);
+ list = list->next;
}
}
#endif
@@ -197,32 +199,28 @@ static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment,
return interpolate;
}
-static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr, int sensoridx)
+static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t *track_pr, int cyl)
{
- int cyl, i;
+ int i;
struct plot_data *entry;
pr_interpolate_t interpolate = { 0, 0, 0, 0 };
pr_track_t *last_segment = NULL;
- int cur_pr[MAX_CYLINDERS]; // cur_pr[MAX_CYLINDERS] is the CCR diluent cylinder
+ int cur_pr;
+ enum interpolation_strategy strategy;
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
- enum interpolation_strategy strategy;
- if (!track_pr[cyl]) {
- /* no segment where this cylinder is used */
- cur_pr[cyl] = -1;
- continue;
- }
- if (dive->cylinder[cyl].cylinder_use == OC_GAS)
- strategy = SAC;
- else
- strategy = TIME;
- fill_missing_segment_pressures(track_pr[cyl], strategy); // Interpolate the missing tank pressure values ..
- cur_pr[cyl] = track_pr[cyl]->start; // in the pr_track_t lists of structures
- } // and keep the starting pressure for each cylinder.
+ /* no segment where this cylinder is used */
+ if (!track_pr)
+ return;
+ if (dive->cylinder[cyl].cylinder_use == OC_GAS)
+ strategy = SAC;
+ else
+ strategy = TIME;
+ fill_missing_segment_pressures(track_pr, strategy); // Interpolate the missing tank pressure values ..
+ cur_pr = track_pr->start; // in the pr_track_t lists of structures
+ // and keep the starting pressure for each cylinder.
#ifdef DEBUG_PR_TRACK
- /* another great debugging tool */
- dump_pr_track(track_pr);
+ dump_pr_track(cyl, track_pr);
#endif
/* Transfer interpolated cylinder pressures from pr_track strucktures to plotdata
@@ -243,27 +241,32 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
entry = pi->entry + i;
- cyl = entry->sensor[sensoridx];
- if (cyl < 0)
- continue;
- save_pressure = &(entry->pressure[sensoridx][SENSOR_PR]);
- save_interpolated = &(entry->pressure[sensoridx][INTERPOLATED_PR]);
+ save_pressure = &(entry->pressure[cyl][SENSOR_PR]);
+ save_interpolated = &(entry->pressure[cyl][INTERPOLATED_PR]);
pressure = *save_pressure ? *save_pressure : *save_interpolated;
if (pressure) { // If there is a valid pressure value,
last_segment = NULL; // get rid of interpolation data,
- cur_pr[cyl] = pressure; // set current pressure
+ cur_pr = pressure; // set current pressure
continue; // and skip to next point.
}
// If there is NO valid pressure value..
// Find the pressure segment corresponding to this entry..
- segment = track_pr[cyl];
+ segment = track_pr;
while (segment && segment->t_end < entry->sec) // Find the track_pr with end time..
segment = segment->next; // ..that matches the plot_info time (entry->sec)
- if (!segment || !segment->pressure_time) { // No (or empty) segment?
- *save_pressure = cur_pr[cyl]; // Just use our current pressure
- continue; // and skip to next point.
+ // After last segment? All done.
+ if (!segment)
+ break;
+
+ // Before first segment, or between segments.. Go on, no interpolation.
+ if (segment->t_start > entry->sec)
+ continue;
+
+ if (!segment->pressure_time) { // Empty segment?
+ *save_pressure = cur_pr; // Just use our current pressure
+ continue; // and skip to next point.
}
// If there is a valid segment but no tank pressure ..
@@ -283,13 +286,13 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time;
/* Use that overall pressure change to update the current pressure */
- cur_pr[cyl] = lrint(interpolate.start + magic * interpolate.acc_pressure_time);
+ cur_pr = lrint(interpolate.start + magic * interpolate.acc_pressure_time);
}
} else {
magic = (interpolate.end - interpolate.start) / (segment->t_end - segment->t_start);
- cur_pr[cyl] = lrint(segment->start + magic * (entry->sec - segment->t_start));
+ cur_pr = lrint(segment->start + magic * (entry->sec - segment->t_start));
}
- *save_interpolated = cur_pr[cyl]; // and store the interpolated data in plot_info
+ *save_interpolated = cur_pr; // and store the interpolated data in plot_info
}
}
@@ -328,6 +331,8 @@ static void debug_print_pressures(struct plot_info *pi)
}
#endif
+extern bool has_gaschange_event(struct dive *dive, struct divecomputer *dc, int idx);
+
/* This function goes through the list of tank pressures, either SENSOR_PRESSURE(entry) or O2CYLINDER_PRESSURE(entry),
* of structure plot_info for the dive profile where each item in the list corresponds to one point (node) of the
* profile. It finds values for which there are no tank pressures (pressure==0). For each missing item (node) of
@@ -338,78 +343,116 @@ static void debug_print_pressures(struct plot_info *pi)
* in the pr_track_alloc structures. If diluent_flag = 1, then DILUENT_PRESSURE(entry) is used instead of SENSOR_PRESSURE.
* This function is called by create_plot_info_new() in profile.c
*/
-void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, int sensoridx)
+void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, int sensor)
{
(void) dc;
- int i, cylinderid, cylinderindex = -1;
- pr_track_t *track_pr[MAX_CYLINDERS] = { NULL, };
+ int first, last, cyl;
+ cylinder_t *cylinder = dive->cylinder + sensor;
+ pr_track_t *track = NULL;
pr_track_t *current = NULL;
- bool missing_pr = false;
- bool found_any_pr_data = false;
+ struct plot_data *entry;
+ struct event *ev;
+ int missing_pr = 0, dense = 1;
/* if we have no pressure data whatsoever, this is pointless, so let's just return */
- for (i = 0; i < MAX_CYLINDERS; i++) {
- if (dive->cylinder[i].start.mbar || dive->cylinder[i].sample_start.mbar ||
- dive->cylinder[i].end.mbar || dive->cylinder[i].sample_end.mbar) {
- found_any_pr_data = true;
- break;
- }
- }
- if (!found_any_pr_data)
+ if (!cylinder->start.mbar && !cylinder->end.mbar &&
+ !cylinder->sample_start.mbar && !cylinder->sample_end.mbar)
return;
- for (i = 0; i < pi->nr; i++) {
+ /* Get a rough range of where we have any pressures at all */
+ first = last = -1;
+ for (int i = 0; i < pi->nr; i++) {
struct plot_data *entry = pi->entry + i;
- unsigned pressure;
+ unsigned pressure = SENSOR_PRESSURE(entry, sensor);
+
+ if (!pressure)
+ continue;
+ if (first < 0)
+ first = i;
+ last = i;
+ }
- pressure = SENSOR_PRESSURE(entry, sensoridx);
- cylinderid = entry->sensor[sensoridx];
- if (cylinderid < 0)
- goto GIVE_UP;
+ /* No sensor data at all? */
+ if (first == last)
+ return;
+
+ /*
+ * Split the range:
+ * - missing pressure data
+ * - gas change events to other cylinders
+ *
+ * Note that we only look at gas switches if this cylinder
+ * itself has a gas change event.
+ */
+ cyl = sensor;
+ ev = NULL;
+ if (has_gaschange_event(dive, dc, sensor))
+ ev = get_next_event(dc->events, "gaschange");
+
+ for (int i = first; i <= last; i++) {
+ struct plot_data *entry = pi->entry + i;
+ unsigned pressure = SENSOR_PRESSURE(entry, sensor);
+ int time = entry->sec;
+
+ while (ev && ev->time.seconds <= time) {
+ cyl = get_cylinder_index(dive, ev);
+ if (cyl < 0)
+ cyl = sensor;
+ ev = get_next_event(ev->next, "gaschange");
+ }
- /* If track_pr structure already exists, then update it: */
- /* discrete integration of pressure over time to get the SAC rate equivalent */
if (current) {
entry->pressure_time = calc_pressure_time(dive, entry - 1, entry);
current->pressure_time += entry->pressure_time;
current->t_end = entry->sec;
+ if (pressure)
+ current->end = pressure;
}
- /* If 1st record or different cylinder: Create a new track_pr structure: */
- /* track the segments per cylinder and their pressure/time integral */
- if (cylinderid != cylinderindex) {
- cylinderindex = entry->sensor[sensoridx];
- current = pr_track_alloc(pressure, entry->sec);
- track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current);
+ // If we have no pressure information, we will need to
+ // continue with or without a tracking entry. Mark any
+ // existing tracking entry as non-dense, and remember
+ // to fill in interpolated data.
+ if (!pressure) {
+ missing_pr = 1;
+ dense = 0;
continue;
}
- if (!pressure) {
- missing_pr = 1;
+ // We have a final pressure for 'current'
+ // If a gas switch has occurred, finish the
+ // current pressure track entry and continue
+ // until we get back to this cylinder.
+ if (cyl != sensor) {
+ current = NULL;
+ SENSOR_PRESSURE(entry, sensor) = 0;
continue;
}
- if (current)
- current->end = pressure;
- /* Was it continuous? */
- if (SENSOR_PRESSURE(entry - 1, sensoridx))
+ // If we already have a pressure tracking entry, and
+ // it has not had any missing samples, just continue
+ // using it - there's nothing to interpolate yet.
+ if (current && dense)
continue;
- /* transmitter stopped transmitting cylinder pressure data */
+ // We need to start a new tracking entry, either
+ // because the previous was interrupted by a gas
+ // switch event, or because the previous one has
+ // missing entries that need to be interpolated.
+ // Or maybe we didn't have a previous one at all,
+ // and this is the first pressure entry.
current = pr_track_alloc(pressure, entry->sec);
- if (cylinderindex >= 0)
- track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current);
+ track = list_add(track, current);
+ dense = 1;
}
if (missing_pr) {
- fill_missing_tank_pressures(dive, pi, track_pr, sensoridx);
+ fill_missing_tank_pressures(dive, pi, track, sensor);
}
#ifdef PRINT_PRESSURES_DEBUG
debug_print_pressures(pi);
#endif
-GIVE_UP:
- for (i = 0; i < MAX_CYLINDERS; i++)
- list_free(track_pr[i]);
+ list_free(track);
}
diff --git a/core/profile.c b/core/profile.c
index 1b5c36621..6e216ec04 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -170,15 +170,13 @@ static int get_local_sac(struct plot_data *entry1, struct plot_data *entry2, str
/* Get local sac-rate (in ml/min) between entry1 and entry2 */
static int get_local_sac(struct plot_data *entry1, struct plot_data *entry2, struct dive *dive)
{
- int index = entry1->sensor[0];
+ int index = 0;
cylinder_t *cyl;
int duration = entry2->sec - entry1->sec;
int depth, airuse;
pressure_t a, b;
double atm;
- if (entry2->sensor[0] != index)
- return 0;
if (duration <= 0)
return 0;
a.mbar = GET_PRESSURE(entry1, 0);
@@ -362,21 +360,6 @@ static int count_events(struct divecomputer *dc)
return result;
}
-static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, int end)
-{
- while (i < pi->nr) {
- struct plot_data *entry = pi->entry + i;
- if (entry->sec > end)
- break;
- if (entry->sensor[0] != cylinderindex) {
- entry->sensor[0] = cylinderindex;
- entry->pressure[0][0] = 0;
- }
- i++;
- }
- return i;
-}
-
static int set_setpoint(struct plot_info *pi, int i, int setpoint, int end)
{
while (i < pi->nr) {
@@ -389,40 +372,6 @@ static int set_setpoint(struct plot_info *pi, int i, int setpoint, int end)
return i;
}
-/* normally the first cylinder has index 0... if not, we need to fix this up here */
-static int set_first_cylinder_index(struct plot_info *pi, int i, int cylinderindex, int end)
-{
- while (i < pi->nr) {
- struct plot_data *entry = pi->entry + i;
- if (entry->sec > end)
- break;
- entry->sensor[0] = cylinderindex;
- i++;
- }
- return i;
-}
-
-static void check_gas_change_events(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
-{
- int i = 0, cylinderindex = 0;
- struct event *ev = get_next_event(dc->events, "gaschange");
-
- // for dive computers that tell us their first gas as an event on the first sample
- // we need to make sure things are setup correctly
- cylinderindex = explicit_first_cylinder(dive, dc);
- set_first_cylinder_index(pi, 0, cylinderindex, INT_MAX);
-
- if (!ev)
- return;
-
- do {
- i = set_cylinder_index(pi, i, cylinderindex, ev->time.seconds);
- cylinderindex = get_cylinder_index(dive, ev);
- ev = get_next_event(ev->next, "gaschange");
- } while (ev);
- set_cylinder_index(pi, i, cylinderindex, INT_MAX);
-}
-
static void check_setpoint_events(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{
int i = 0;
@@ -639,11 +588,10 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
} else {
entry->pressures.o2 = sample->setpoint.mbar / 1000.0;
}
- /* FIXME! sensor index -> cylinder index translation! */
- entry->sensor[0] = sample->sensor[0];
- entry->sensor[1] = sample->sensor[1];
- SENSOR_PRESSURE(entry, 0) = sample->pressure[0].mbar;
- SENSOR_PRESSURE(entry, 1) = sample->pressure[1].mbar;
+ if (sample->pressure[0].mbar)
+ SENSOR_PRESSURE(entry, sample->sensor[0]) = sample->pressure[0].mbar;
+ if (sample->pressure[1].mbar)
+ SENSOR_PRESSURE(entry, sample->sensor[1]) = sample->pressure[1].mbar;
if (sample->temperature.mkelvin)
entry->temperature = lasttemp = sample->temperature.mkelvin;
else
@@ -686,38 +634,6 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
#undef INSERT_ENTRY
-static void populate_cylinder_pressure_data(int idx, int start, int end, struct plot_info *pi, int sensoridx)
-{
- int i;
-
- /* First: check that none of the entries has sensor pressure for this cylinder index */
- for (i = 0; i < pi->nr; i++) {
- struct plot_data *entry = pi->entry + i;
- if (entry->sensor[sensoridx] != idx)
- continue;
- if (SENSOR_PRESSURE(entry, sensoridx))
- return;
- }
-
- /* Then: populate the first entry with the beginning cylinder pressure */
- for (i = 0; i < pi->nr; i++) {
- struct plot_data *entry = pi->entry + i;
- if (entry->sensor[sensoridx] != idx)
- continue;
- SENSOR_PRESSURE(entry, sensoridx) = start;
- break;
- }
-
- /* .. and the last entry with the ending cylinder pressure */
- for (i = pi->nr; --i >= 0; /* nothing */) {
- struct plot_data *entry = pi->entry + i;
- if (entry->sensor[sensoridx] != idx)
- continue;
- SENSOR_PRESSURE(entry, sensoridx) = end;
- break;
- }
-}
-
/*
* Calculate the sac rate between the two plot entries 'first' and 'last'.
*
@@ -726,6 +642,7 @@ static void populate_cylinder_pressure_data(int idx, int start, int end, struct
*/
static int sac_between(struct dive *dive, struct plot_data *first, struct plot_data *last)
{
+ int sensor = 0;
int airuse;
double pressuretime;
pressure_t a, b;
@@ -735,9 +652,9 @@ static int sac_between(struct dive *dive, struct plot_data *first, struct plot_d
return 0;
/* Calculate air use - trivial */
- a.mbar = GET_PRESSURE(first, 0);
- b.mbar = GET_PRESSURE(last, 0);
- cyl = dive->cylinder + first->sensor[0];
+ a.mbar = GET_PRESSURE(first, sensor);
+ b.mbar = GET_PRESSURE(last, sensor);
+ cyl = dive->cylinder + sensor;
airuse = gas_volume(cyl, a) - gas_volume(cyl, b);
if (airuse <= 0)
return 0;
@@ -767,6 +684,7 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
{
struct plot_data *entry = pi->entry + idx;
struct plot_data *first, *last;
+ int sensor = 0;
int time;
if (entry->sac)
@@ -783,13 +701,12 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
time = entry->sec - 30;
while (idx > 0) {
struct plot_data *prev = first-1;
- if (prev->sensor[0] != first->sensor[0])
- break;
+
if (prev->depth < SURFACE_THRESHOLD && first->depth < SURFACE_THRESHOLD)
break;
if (prev->sec < time)
break;
- if (!GET_PRESSURE(prev, 0))
+ if (!GET_PRESSURE(prev, sensor))
break;
idx--;
first = prev;
@@ -800,13 +717,11 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
time = first->sec + 60;
while (++idx < pi->nr) {
struct plot_data *next = last+1;
- if (next->sensor[0] != last->sensor[0])
- break;
if (next->depth < SURFACE_THRESHOLD && last->depth < SURFACE_THRESHOLD)
break;
if (next->sec > time)
break;
- if (!GET_PRESSURE(next, 0))
+ if (!GET_PRESSURE(next, sensor))
break;
last = next;
}
@@ -828,21 +743,66 @@ static void populate_secondary_sensor_data(struct divecomputer *dc, struct plot_
/* We should try to see if it has interesting pressure data here */
}
+/*
+ * This adds a pressure entry to the plot_info based on the gas change
+ * information and the manually filled in pressures.
+ */
+static void add_plot_pressure(struct plot_info *pi, int time, int cyl, int mbar)
+{
+ for (int i = 0; i < pi->nr; i++) {
+ struct plot_data *entry = pi->entry + i;
+
+ if (entry->sec < time)
+ continue;
+ SENSOR_PRESSURE(entry, cyl) = mbar;
+ return;
+ }
+}
+
static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{
- int i;
+ int prev = -1, i;
+ struct event *ev;
+ unsigned int seen[MAX_CYLINDERS] = { 0, };
+ unsigned int first[MAX_CYLINDERS] = { 0, };
+ unsigned int last[MAX_CYLINDERS] = { 0, };
struct divecomputer *secondary;
- /* First, populate the pressures with the manual cylinder data.. */
- for (i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = dive->cylinder + i;
- int start = cyl->start.mbar ?: cyl->sample_start.mbar;
- int end = cyl->end.mbar ?: cyl->sample_end.mbar;
+ for (ev = get_next_event(dc->events, "gaschange"); ev != NULL; ev = get_next_event(ev->next, "gaschange")) {
+ int cyl = ev->gas.index;
+ int sec = ev->time.seconds;
- if (!start || !end)
+ if (cyl < 0)
continue;
- populate_cylinder_pressure_data(i, start, end, pi, dive->cylinder[i].cylinder_use == OXYGEN);
+ if (prev >= 0)
+ last[prev] = sec;
+ prev = cyl;
+
+ last[cyl] = sec;
+ if (!seen[cyl]) {
+ int endtime = sec;
+ if (dc->samples)
+ endtime = dc->sample[dc->samples-1].time.seconds;
+
+ // The end time may be updated by a subsequent cylinder change
+ first[cyl] = sec;
+ last[cyl] = endtime;
+ seen[cyl] = 1;
+ }
+ }
+
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ if (seen[i]) {
+ cylinder_t *cyl = dive->cylinder + i;
+ int start = cyl->start.mbar;
+ int end = cyl->end.mbar;
+
+ if (start)
+ add_plot_pressure(pi, first[i], i, start);
+ if (end)
+ add_plot_pressure(pi, last[i], i, end);
+ }
}
/*
@@ -862,6 +822,7 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc
/* calculate DECO STOP / TTS / NDL */
static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double surface_pressure)
{
+ int cylinderindex = 0;
/* FIXME: This should be configurable */
/* ascent speed up to first deco stop */
const int ascent_s_per_step = 1;
@@ -877,7 +838,6 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
surface_pressure, dive, 1), deco_stepsize);
int ascent_depth = entry->depth;
/* at what time should we give up and say that we got enuff NDL? */
- int cylinderindex = entry->sensor[0];
/* If iterating through a dive, entry->tts_calc needs to be reset */
entry->tts_calc = 0;
@@ -971,7 +931,7 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
add_segment(depth_to_bar(depth, dive),
- &dive->cylinder[entry->sensor[0]].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
+ &dive->cylinder[0].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
if ((t1 - j < time_stepsize) && (j < t1))
time_stepsize = t1 - j;
}
@@ -1125,7 +1085,7 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
for (i = 1; i < pi->nr; i++) {
int fn2, fhe;
struct plot_data *entry = pi->entry + i;
- int cylinderindex = entry->sensor[0];
+ int cylinderindex = 0;
amb_pressure = depth_to_bar(entry->depth, dive);
@@ -1249,13 +1209,11 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
last_pi_entry_new = populate_plot_entries(dive, dc, pi);
- check_gas_change_events(dive, dc, pi); /* Populate the gas index from the gas change events */
check_setpoint_events(dive, dc, pi); /* Populate setpoints */
setup_gas_sensor_pressure(dive, dc, pi); /* Try to populate our gas pressure knowledge */
if (!fast) {
- populate_pressure_information(dive, dc, pi, false); /* .. calculate missing pressure entries for all gasses except o2 */
- if (dc->divemode == CCR) /* For CCR dives.. */
- populate_pressure_information(dive, dc, pi, true); /* .. calculate missing o2 gas pressure entries */
+ for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++)
+ populate_pressure_information(dive, dc, pi, cyl);
}
fill_o2_values(dc, pi, dive); /* .. and insert the O2 sensor data having 0 values. */
calculate_sac(dive, pi); /* Calculate sac */
@@ -1477,7 +1435,6 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
last_sec = start->sec;
last_pressure = GET_PRESSURE(start, 0);
- last_cylidx = start->sensor[0];
data = start;
while (data != stop) {
@@ -1501,10 +1458,6 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
if (GET_PRESSURE(data, 0) < last_pressure + 2000)
bar_used += last_pressure - GET_PRESSURE(data, 0);
- if (data->sensor[0] != last_cylidx)
- /* if we change tanks, don't try to do SAC rate later */
- crossed_tankchange = true;
-
count += 1;
last_sec = data->sec;
last_pressure = GET_PRESSURE(data, 0);
@@ -1548,7 +1501,7 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
pressurevalue = get_pressure_units(bar_used, &pressure_unit);
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, translate("gettextFromC", "%s %sP:%d %s"), buf2, UTF8_DELTA, pressurevalue, pressure_unit);
- cylinder_t *cyl = displayed_dive.cylinder + start->sensor[0];
+ cylinder_t *cyl = displayed_dive.cylinder + 0;
/* if we didn't cross a tank change and know the cylidner size as well, show SAC rate */
if (!crossed_tankchange && cyl->type.size.mliter) {
double volume_value;
diff --git a/core/profile.h b/core/profile.h
index 988736f30..1cbcd30fd 100644
--- a/core/profile.h
+++ b/core/profile.h
@@ -21,15 +21,12 @@ struct divecomputer;
struct plot_info;
struct plot_data {
unsigned int in_deco : 1;
- char sensor[2];
int sec;
- /* pressure[0] is main sensor pressure (diluent for CCR)
- * pressure[1] is secondary sensor pressure (O2 for CCR)
- *
- * pressure[x][0] is sensor pressure
+ /*
+ * pressure[x][0] is sensor pressure for cylinder x
* pressure[x][1] is interpolated pressure
*/
- int pressure[2][2];
+ int pressure[MAX_CYLINDERS][2];
int temperature;
/* Depth info */
int depth;
diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp
index fcaca3a88..6f2bf98b0 100644
--- a/profile-widget/diveprofileitem.cpp
+++ b/profile-widget/diveprofileitem.cpp
@@ -683,108 +683,99 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
// We don't have enougth data to calculate things, quit.
if (!shouldCalculateStuff(topLeft, bottomRight))
return;
- int last_index = -1;
- QPolygonF boundingPoly, o2Poly; // This is the "Whole Item", but a pressure can be divided in N Polygons.
+
+ int plotted_cyl[MAX_CYLINDERS] = { false, };
+ int last_plotted[MAX_CYLINDERS] = { 0, };
+ QPolygonF poly[MAX_CYLINDERS];
+ QPolygonF boundingPoly;
polygons.clear();
- polygons.append(o2Poly);
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
- plot_data *entry = dataModel->data().entry + i;
- int mbar = GET_PRESSURE(entry, 0);
- int o2mbar = GET_PRESSURE(entry, 1);
+ struct plot_data *entry = dataModel->data().entry + i;
- if ((int)entry->sensor[0] != last_index) {
- polygons.append(QPolygonF()); // this is the polygon that will be actually drawn on screen.
- last_index = entry->sensor[0];
- }
- if (!mbar) {
- continue;
- }
- if (o2mbar) {
- QPointF o2point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(o2mbar));
- boundingPoly.push_back(o2point);
- polygons.first().push_back(o2point);
+ for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
+ int mbar = GET_PRESSURE(entry, cyl);
+ int time = entry->sec;
+
+ if (!mbar)
+ continue;
+
+ QPointF point(hAxis->posAtValue(time), vAxis->posAtValue(mbar));
+ boundingPoly.push_back(point);
+
+ if (plotted_cyl[cyl]) {
+ /* Have we used this culinder in the last two minutes? Continue */
+ if (time - last_plotted[cyl] <= 2*60) {
+ poly[cyl].push_back(point);
+ last_plotted[cyl] = time;
+ continue;
+ }
+
+ /* Finish the previous one, start a new one */
+ polygons.append(poly[cyl]);
+ poly[cyl] = QPolygonF();
+ }
+
+ plotted_cyl[cyl] = true;
+ last_plotted[cyl] = time;
+ poly[cyl].push_back(point);
}
+ }
- QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar));
- boundingPoly.push_back(point); // The BoundingRect
- polygons.last().push_back(point); // The polygon thta will be plotted.
+ for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
+ if (!plotted_cyl[cyl])
+ continue;
+ polygons.append(poly[cyl]);
}
+
setPolygon(boundingPoly);
qDeleteAll(texts);
texts.clear();
- int mbar, cyl, lastcyl;
- int o2mbar, o2cyl;
+
int seen_cyl[MAX_CYLINDERS] = { false, };
int last_pressure[MAX_CYLINDERS] = { 0, };
int last_time[MAX_CYLINDERS] = { 0, };
- struct plot_data *entry;
-
- cyl = o2cyl = lastcyl = -1;
- mbar = o2mbar = 0;
double print_y_offset[8][2] = { { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } ,{ 0, -0.5 }, { 0, -0.5 }, { 0, -0.5 } };
- // CCR dives: These are offset values used to print the gas lables and pressures on a CCR dive profile at
- // appropriate Y-coordinates: One doublet of values for each of 8 cylinders.
+ // These are offset values used to print the gas lables and pressures on a
+ // dive profile at appropriate Y-coordinates: One doublet of values for each
+ // of 8 cylinders.
// Order of offsets within a doublet: gas lable offset; gas pressure offset.
// The array is initialised with default values that apply to non-CCR dives.
- bool offsets_initialised = false;
- QFlags<Qt::AlignmentFlag> alignVar= Qt::AlignTop, align_dil = Qt::AlignBottom, align_o2 = Qt::AlignTop;
+ QFlags<Qt::AlignmentFlag> alignVar = Qt::AlignTop;
+ QFlags<Qt::AlignmentFlag> align[MAX_CYLINDERS];
+
double axisRange = (vAxis->maximum() - vAxis->minimum())/1000; // Convert axis pressure range to bar
double axisLog = log10(log10(axisRange));
+
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
- entry = dataModel->data().entry + i;
-
- cyl = entry->sensor[0];
- o2cyl = entry->sensor[1];
- mbar = GET_PRESSURE(entry, 0);
- o2mbar = GET_PRESSURE(entry, 1);
-
- if (o2mbar) { // Do we have a second cylinder pressure? If so, do
- // The first time an o2 value is detected, see if the oxygen cyl pressure graph starts above or below the dil graph
- if (!offsets_initialised) { // Initialise the parameters for placing the text correctly near the graph line:
- if ((o2mbar > mbar)) { // If above, write o2 start cyl pressure above graph and diluent pressure below graph:
- print_y_offset[o2cyl][0] = -7 * axisLog; // y offset for oxygen gas lable (above); pressure offsets=-0.5, already initialised
- print_y_offset[cyl][0] = 5 * axisLog; // y offset for diluent gas lable (below)
- } else { // ... else write o2 start cyl pressure below graph:
- print_y_offset[o2cyl][0] = 5 * axisLog; // o2 lable & pressure below graph; pressure offsets=-0.5, already initialised
- print_y_offset[cyl][0] = -7.8 * axisLog; // and diluent lable above graph.
- align_dil = Qt::AlignTop;
- align_o2 = Qt::AlignBottom;
- }
- offsets_initialised = true;
- }
+ struct plot_data *entry = dataModel->data().entry + i;
- if (!seen_cyl[o2cyl]) { //For o2, on the left of profile, write lable and pressure
- plotPressureValue(o2mbar, entry->sec, align_o2, print_y_offset[o2cyl][1]);
- plotGasValue(o2mbar, entry->sec, displayed_dive.cylinder[o2cyl].gasmix, align_o2, print_y_offset[o2cyl][0]);
- seen_cyl[o2cyl] = true;
- }
- last_pressure[o2cyl] = o2mbar;
- last_time[o2cyl] = entry->sec;
- alignVar = align_dil;
- }
+ for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
+ int mbar = GET_PRESSURE(entry, cyl);
- if (!mbar)
- continue;
+ if (!mbar)
+ continue;
- if (cyl != lastcyl) { // Pressure value near the left hand edge of the profile - other cylinders:
- lastcyl = cyl; // For each other cylinder, write the gas lable and pressure
if (!seen_cyl[cyl]) {
plotPressureValue(mbar, entry->sec, alignVar, print_y_offset[cyl][1]);
- plotGasValue(mbar, entry->sec, displayed_dive.cylinder[cyl].gasmix, align_dil, print_y_offset[cyl][0]);
+ plotGasValue(mbar, entry->sec, displayed_dive.cylinder[cyl].gasmix, alignVar, print_y_offset[cyl][0]);
seen_cyl[cyl] = true;
+
+ /* Alternate alignment as we see cylinder use.. */
+ align[cyl] = alignVar;
+ alignVar ^= Qt::AlignTop | Qt::AlignBottom;
}
+ last_pressure[cyl] = mbar;
+ last_time[cyl] = entry->sec;
}
- last_pressure[cyl] = mbar;
- last_time[cyl] = entry->sec;
}
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { // For each cylinder, on right hand side of profile, write cylinder pressure
- alignVar = ((o2cyl >= 0) && (cyl == o2cyl)) ? align_o2 : align_dil;
+ // For each cylinder, on right hand side of profile, write cylinder pressure
+ for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
if (last_time[cyl]) {
- plotPressureValue(last_pressure[cyl], last_time[cyl], (alignVar | Qt::AlignLeft), print_y_offset[cyl][1]);
+ plotPressureValue(last_pressure[cyl], last_time[cyl], align[cyl] | Qt::AlignLeft, print_y_offset[cyl][1]);
}
}
}
diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp
index 17f3544f3..d8fd8da2c 100644
--- a/profile-widget/profilewidget2.cpp
+++ b/profile-widget/profilewidget2.cpp
@@ -1407,8 +1407,6 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
action->setText(model->data(model->index(i, 0), Qt::DisplayRole).toString() + QString(tr(" (Tank %1)")).arg(i + 1));
connect(action, SIGNAL(triggered(bool)), this, SLOT(changeGas()));
action->setData(event->globalPos());
- if (i == entry->sensor[0])
- action->setDisabled(true);
gasChange->addAction(action);
}
}
diff --git a/profile-widget/tankitem.cpp b/profile-widget/tankitem.cpp
index 89ddffed9..e2b528eb2 100644
--- a/profile-widget/tankitem.cpp
+++ b/profile-widget/tankitem.cpp
@@ -98,20 +98,24 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b
// walk the list and figure out which tanks go where
struct plot_data *entry = pInfoEntry;
struct plot_data *lastentry = pInfoEntry;
- int cylIdx = entry->sensor[0];
+ int cylIdx = 0; // explicit_first_cylinder(dive, dc)
int i = -1;
int startTime = 0;
struct gasmix *gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
qreal width, left;
+
+ // FIXME! This used to depend on the sensor indexes that we no longer have
+ // We should use gaschange events or something
while (++i < pInfoNr) {
+ int newIdx = 0; // get_next_event(dc->events, "gaschange");
entry = &pInfoEntry[i];
lastentry = &pInfoEntry[i-1];
- if (entry->sensor[0] == cylIdx)
+ if (newIdx == cylIdx)
continue;
width = hAxis->posAtValue(lastentry->sec) - hAxis->posAtValue(startTime);
left = hAxis->posAtValue(startTime);
createBar(left, width, gas);
- cylIdx = entry->sensor[0];
+ cylIdx = newIdx;
gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
startTime = lastentry->sec;
}
diff --git a/qt-models/diveplotdatamodel.cpp b/qt-models/diveplotdatamodel.cpp
index b4e72b2df..3e0ae57f1 100644
--- a/qt-models/diveplotdatamodel.cpp
+++ b/qt-models/diveplotdatamodel.cpp
@@ -40,7 +40,7 @@ QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
case USERENTERED:
return false;
case CYLINDERINDEX:
- return item.sensor[0];
+ return 0;
case SENSOR_PRESSURE:
return item.pressure[0][0];
case INTERPOLATED_PRESSURE: