For CCR dives, the diluent cylinder is the current cylinder

Change the meaning that _the_ cylinder (as we treat it in OC dives) is the
diluent cylinder (rather than the O2 cylinder). This eliminates special
cases. Now, for CCR, we have to handle the O2 cylinder in addition
(rather than the diluent in addition).

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Robert C. Helling 2014-11-17 12:25:00 +01:00 committed by Dirk Hohndel
parent 5ed4876ad2
commit 0d7c192e6e
9 changed files with 1772 additions and 1773 deletions

25
dive.c
View file

@ -706,15 +706,14 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me
struct event *ev = get_next_event(dc->events, "gaschange");
if (!ev || (dc && dc->sample && ev->time.seconds == dc->sample[0].time.seconds && get_next_event(ev->next, "gaschange") == NULL)) {
// we have either no gas change or only one gas change and that's setting an explicit first cylinder
mean[explicit_first_cylinder(dive, dc)] = dc->meandepth.mm;
duration[explicit_first_cylinder(dive, dc)] = dc->duration.seconds;
if (dc->dctype == CCR) {
// Do the same for the O2 cylinder
int o2_cyl = get_cylinder_idx_by_use(dive, OXYGEN);
int diluent_cyl = get_cylinder_idx_by_use(dive, DILUENT);
mean[o2_cyl] = mean[diluent_cyl] = dc->meandepth.mm;
duration[o2_cyl] = duration[diluent_cyl] = dc->duration.seconds;
} else {
// OC, no real gas changes, it's all the first cylinder
mean[explicit_first_cylinder(dive, dc)] = dc->meandepth.mm;
duration[explicit_first_cylinder(dive, dc)] = dc->duration.seconds;
mean[o2_cyl] = dc->meandepth.mm;
duration[o2_cyl] = dc->duration.seconds;
}
return;
}
@ -831,6 +830,8 @@ int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc)
struct event *ev = get_next_event(dc->events, "gaschange");
if (ev && dc && dc->sample && ev->time.seconds == dc->sample[0].time.seconds)
return get_cylinder_index(dive, ev);
else if (dc->dctype == CCR)
return get_cylinder_idx_by_use(dive, DILUENT);
else
return 0;
}
@ -1151,7 +1152,7 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
int maxdepth = dc->maxdepth.mm;
int mintemp = 0;
int lastdepth = 0;
int lastpressure = 0, lastdiluentpressure = 0;
int lastpressure = 0, lasto2pressure = 0;
int pressure_delta[MAX_CYLINDERS] = { INT_MAX, };
int first_cylinder;
@ -1171,7 +1172,7 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
int depth = sample->depth.mm;
int temp = sample->temperature.mkelvin;
int pressure = sample->cylinderpressure.mbar;
int diluent_pressure = sample->diluentpressure.mbar;
int o2_pressure = sample->o2cylinderpressure.mbar;
int index;
/* if we have an explicit first cylinder */
@ -1184,8 +1185,8 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
/* Remove duplicate redundant pressure information */
if (pressure == lastpressure)
sample->cylinderpressure.mbar = 0;
if (diluent_pressure == lastdiluentpressure)
sample->diluentpressure.mbar = 0;
if (o2_pressure == lasto2pressure)
sample->o2cylinderpressure.mbar = 0;
/* check for simply linear data in the samples
+INT_MAX means uninitialized, -INT_MAX means not linear */
if (pressure_delta[index] != -INT_MAX && lastpressure) {
@ -1203,7 +1204,7 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
}
lastindex = index;
lastpressure = pressure;
lastdiluentpressure = diluent_pressure;
lasto2pressure = o2_pressure;
if (depth > SURFACE_THRESHOLD) {
if (depth > maxdepth)

2
dive.h
View file

@ -184,7 +184,7 @@ struct sample // BASE TYPE BYTES UNITS RANGE DE
depth_t stopdepth; // int32_t 4 mm (0-2000 km) depth of next deco stop
temperature_t temperature; // int32_t 4 mdegrK (0-2 MdegK) ambient temperature
pressure_t cylinderpressure; // int32_t 4 mbar (0-2 Mbar) main cylinder pressure
pressure_t diluentpressure; // int32_t 4 mbar (0-2 Mbar) CCR diluent pressure (rebreather)
pressure_t o2cylinderpressure; // int32_t 4 mbar (0-2 Mbar) CCR o2 cylinder pressure (rebreather)
o2pressure_t setpoint; // uint16_t 2 mbar (0-65 bar) O2 partial pressure (will be setpoint)
o2pressure_t o2sensor[3]; // uint16_t 6 mbar (0-65 bar) Up to 3 PO2 sensor values (rebreather)
bearing_t bearing; // int16_t 2 degrees (-32k to 32k deg) compass bearing

File diff suppressed because it is too large Load diff

30
file.c
View file

@ -242,7 +242,7 @@ enum csv_format {
POSEIDON_SENSOR1,
POSEIDON_SENSOR2,
POSEIDON_PRESSURE,
POSEIDON_DILUENT
POSEIDON_O2CYLINDER
};
static void add_sample_data(struct sample *sample, enum csv_format type, double val)
@ -275,8 +275,8 @@ static void add_sample_data(struct sample *sample, enum csv_format type, double
case POSEIDON_PRESSURE:
sample->cylinderpressure.mbar = val * 1000;
break;
case POSEIDON_DILUENT:
sample->diluentpressure.mbar = val * 1000;
case POSEIDON_O2CYLINDER:
sample->o2cylinderpressure.mbar = val * 1000;
break;
}
}
@ -480,7 +480,7 @@ int parse_txt_file(const char *filename, const char *csv)
int prev_depth = 0, cur_sampletime = 0, prev_setpoint = -1;
bool has_depth = false, has_setpoint = false;
char *lineptr, *key, *value;
int diluent_pressure = 0, cylinder_pressure = 0, cur_cylinder_index = 0;
int o2cylinder_pressure = 0, cylinder_pressure = 0, cur_cylinder_index = 0;
struct dive *dive;
struct divecomputer *dc;
@ -595,6 +595,14 @@ int parse_txt_file(const char *filename, const char *csv)
add_sample_data(sample, POSEIDON_DEPTH, value);
break;
case 13:
add_sample_data(sample, POSEIDON_O2CYLINDER, value);
if (!o2cylinder_pressure) {
dive->cylinder[1].sample_start.mbar = value * 1000;
o2cylinder_pressure = value;
} else
o2cylinder_pressure = value;
break;
case 14:
add_sample_data(sample, POSEIDON_PRESSURE, value);
if (!cylinder_pressure) {
dive->cylinder[0].sample_start.mbar = value * 1000;
@ -602,14 +610,6 @@ int parse_txt_file(const char *filename, const char *csv)
} else
cylinder_pressure = value;
break;
case 14:
add_sample_data(sample, POSEIDON_DILUENT, value);
if (!diluent_pressure) {
dive->cylinder[1].sample_start.mbar = value * 1000;
diluent_pressure = value;
} else
diluent_pressure = value;
break;
case 20:
has_setpoint = true;
prev_setpoint = value;
@ -643,9 +643,9 @@ int parse_txt_file(const char *filename, const char *csv)
if (!has_setpoint)
add_sample_data(sample, POSEIDON_SETPOINT, prev_setpoint);
if (cylinder_pressure)
dive->cylinder[0].sample_end.mbar = cylinder_pressure * 1000;
if (diluent_pressure)
dive->cylinder[1].sample_end.mbar = diluent_pressure * 1000;
dive->cylinder[1].sample_end.mbar = cylinder_pressure * 1000;
if (o2cylinder_pressure)
dive->cylinder[0].sample_end.mbar = o2cylinder_pressure * 1000;
finish_sample(dc);
if (!lineptr || !*lineptr)

View file

@ -168,7 +168,7 @@ void dump_pr_interpolate(int i, pr_interpolate_t interpolate_pr)
static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment, struct plot_info *pi, int cur, int pressure)
{ // cur = index to pi->entry corresponding to t_end of segment; diluent_flag=1 indicates diluent cylinder
{ // cur = index to pi->entry corresponding to t_end of segment;
struct pr_interpolate_struct interpolate;
int i;
struct plot_data *entry;
@ -219,7 +219,7 @@ 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 diluent_flag)
static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr, int o2_flag)
{
int cyl, i;
struct plot_data *entry;
@ -264,12 +264,12 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
entry = pi->entry + i;
if (diluent_flag) {
if (o2_flag) {
// Find the cylinder index (cyl) and pressure
cyl = dive->diluent_cylinder_index;
pressure = DILUENT_PRESSURE(entry);
save_pressure = &(entry->diluentpressure[SENSOR_PR]);
save_interpolated = &(entry->diluentpressure[INTERPOLATED_PR]);
cyl = dive->oxygen_cylinder_index;
pressure = O2CYLINDER_PRESSURE(entry);
save_pressure = &(entry->o2cylinderpressure[SENSOR_PR]);
save_interpolated = &(entry->o2cylinderpressure[INTERPOLATED_PR]);
} else {
pressure = SENSOR_PRESSURE(entry);
save_pressure = &(entry->pressure[SENSOR_PR]);
@ -351,7 +351,7 @@ 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 diluent_flag)
void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, int o2_flag)
{
int i, cylinderid, cylinderindex = -1;
pr_track_t *track_pr[MAX_CYLINDERS] = { NULL, };
@ -361,9 +361,9 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
for (i = 0; i < pi->nr; i++) {
struct plot_data *entry = pi->entry + i;
unsigned pressure;
if (diluent_flag) { // if this is a diluent cylinder:
pressure = DILUENT_PRESSURE(entry);
cylinderid = dive->diluent_cylinder_index;
if (o2_flag) { // if this is a diluent cylinder:
pressure = O2CYLINDER_PRESSURE(entry);
cylinderid = dive->oxygen_cylinder_index;
} else {
pressure = SENSOR_PRESSURE(entry);
cylinderid = entry->cylinderindex;
@ -379,8 +379,8 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
/* 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) {
if (diluent_flag) // For CCR dives:
cylinderindex = dive->diluent_cylinder_index; // indicate diluent cylinder
if (o2_flag) // For CCR dives:
cylinderindex = dive->oxygen_cylinder_index; // indicate o2 cylinder
else
cylinderindex = entry->cylinderindex;
current = pr_track_alloc(pressure, entry->sec);
@ -395,7 +395,7 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
current->end = pressure;
/* Was it continuous? */
if ((diluent_flag) && (DILUENT_PRESSURE(entry - 1))) // in the case of CCR diluent pressure
if ((o2_flag) && (O2CYLINDER_PRESSURE(entry - 1))) // in the case of CCR o2 pressure
continue;
else if (SENSOR_PRESSURE(entry - 1)) // for all other cylinders
continue;
@ -406,7 +406,7 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
}
if (missing_pr) {
fill_missing_tank_pressures(dive, pi, track_pr, diluent_flag);
fill_missing_tank_pressures(dive, pi, track_pr, o2_flag);
}
#ifdef PRINT_PRESSURES_DEBUG

View file

@ -891,7 +891,9 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return;
if (MATCH("cylpress.sample", pressure, &sample->cylinderpressure))
return;
if (MATCH("pdiluent.sample", pressure, &sample->diluentpressure))
if (MATCH("pdiluent.sample", pressure, &sample->cylinderpressure))
return;
if (MATCH("o2pressure.sample", pressure, &sample->o2cylinderpressure))
return;
if (MATCH("cylinderindex.sample", get_cylinderindex, &sample->sensor))
return;

View file

@ -396,13 +396,13 @@ static void check_gas_change_events(struct dive *dive, struct divecomputer *dc,
int i = 0, cylinderindex = 0;
struct event *ev = get_next_event(dc->events, "gaschange");
if (!ev)
return;
// 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
if ((cylinderindex = explicit_first_cylinder(dive, dc)) != 0)
set_first_cylinder_index(pi, 0, cylinderindex, ~0u);
cylinderindex = explicit_first_cylinder(dive, dc);
set_first_cylinder_index(pi, 0, cylinderindex, ~0u);
if (!ev)
return;
do {
i = set_cylinder_index(pi, i, cylinderindex, ev->time.seconds);
@ -576,7 +576,7 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
entry->in_deco = sample->in_deco;
entry->cns = sample->cns;
if (dc->dctype == CCR) {
entry->o2setpoint = sample->setpoint.mbar / 1000.0; // for rebreathers
entry->o2pressure = sample->setpoint.mbar / 1000.0; // for rebreathers
entry->o2sensor[0] = sample->o2sensor[0].mbar / 1000.0; // for up to three rebreather O2 sensors
entry->o2sensor[1] = sample->o2sensor[1].mbar / 1000.0;
entry->o2sensor[2] = sample->o2sensor[2].mbar / 1000.0;
@ -584,9 +584,9 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
entry->pressures.o2 = sample->setpoint.mbar / 1000.0;
}
/* FIXME! sensor index -> cylinder index translation! */
entry->cylinderindex = sample->sensor;
// entry->cylinderindex = sample->sensor;
SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar;
DILUENT_PRESSURE(entry) = sample->diluentpressure.mbar;
O2CYLINDER_PRESSURE(entry) = sample->o2cylinderpressure.mbar;
if (sample->temperature.mkelvin)
entry->temperature = lasttemp = sample->temperature.mkelvin;
else
@ -735,7 +735,7 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
while (entry->ndl_calc < max_ndl && deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= 0) {
entry->ndl_calc += time_stepsize;
tissue_tolerance = add_segment(depth_to_mbar(entry->depth, dive) / 1000.0,
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2setpoint * 1000, dive, prefs.bottomsac);
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure * 1000, dive, prefs.bottomsac);
}
/* we don't need to calculate anything else */
return;
@ -747,7 +747,7 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
/* Add segments for movement to stopdepth */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->o2setpoint * 1000, dive, prefs.decosac);
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_step, entry->o2pressure * 1000, dive, prefs.decosac);
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1), deco_stepsize);
}
ascent_depth = next_stop;
@ -765,13 +765,13 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
entry->tts_calc += time_stepsize;
tissue_tolerance = add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2setpoint * 1000, dive, prefs.decosac);
&dive->cylinder[cylinderindex].gasmix, time_stepsize, entry->o2pressure * 1000, dive, prefs.decosac);
if (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) <= next_stop) {
/* move to the next stop and add the travel between stops */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step)
add_segment(depth_to_mbar(ascent_depth, dive) / 1000.0,
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_deco_step, entry->o2setpoint * 1000, dive, prefs.decosac);
&dive->cylinder[cylinderindex].gasmix, ascent_s_per_deco_step, entry->o2pressure * 1000, dive, prefs.decosac);
ascent_depth = next_stop;
next_stop -= deco_stepsize;
}
@ -799,7 +799,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);
double min_pressure = add_segment(depth_to_mbar(depth, dive) / 1000.0,
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2setpoint * 1000, dive, entry->sac);
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2pressure * 1000, dive, entry->sac);
tissue_tolerance = min_pressure;
if (j - t0 < time_stepsize)
time_stepsize = j - t0;
@ -864,7 +864,7 @@ double calculate_ccr_po2(struct plot_data *entry, struct divecomputer *dc) {
}
switch (np) {
case 0: // Uhoh
return entry->o2setpoint;
return entry->o2pressure;
case 1: // Return what we have
return sump;
case 2: // Take the average
@ -899,10 +899,6 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0;
// For CCR dives use the diluent gas composition for calculating partial gas pressures:
if (dive->dc.dctype == CCR && cylinderindex == dive->oxygen_cylinder_index && dive->diluent_cylinder_index != -1)
cylinderindex = dive->diluent_cylinder_index;
fill_pressures(&entry->pressures, amb_pressure, &dive->cylinder[cylinderindex].gasmix, entry->pressures.o2, dive->dc.dctype, entry->sac);
fn2 = (int) (1000.0 * entry->pressures.n2 / amb_pressure);
fhe = (int) (1000.0 * entry->pressures.he / amb_pressure);
@ -959,9 +955,9 @@ void fill_o2_values(struct divecomputer *dc, struct plot_info *pi, struct dive *
} // having initialised the empty o2 sensor values for this point on the profile,
amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0;
o2pressure = calculate_ccr_po2(entry,dc); // ...calculate the po2 based on the sensor data
entry->pressures.o2 = MIN(o2pressure, amb_pressure);
entry->o2pressure = MIN(o2pressure, amb_pressure);
} else {
entry->pressures.o2 = 0.0; // initialise po2 to zero for dctype = OC
entry->o2pressure = 0.0; // initialise po2 to zero for dctype = OC
}
}
}
@ -982,8 +978,8 @@ static void debug_print_profiledata(struct plot_info *pi)
for (i = 0; i < pi->nr; i++) {
entry = pi->entry + i;
fprintf(f1, "%d gas=%8d %8d ; dil=%8d %8d ; o2_sp= %f %f %f %f PO2= %f\n", i, SENSOR_PRESSURE(entry),
INTERPOLATED_PRESSURE(entry), DILUENT_PRESSURE(entry), INTERPOLATED_DILUENT_PRESSURE(entry),
entry->o2setpoint, entry->o2sensor[0], entry->o2sensor[1], entry->o2sensor[2], entry->pressures.o2);
INTERPOLATED_PRESSURE(entry), O2CYLINDER_PRESSURE(entry), INTERPOLATED_O2CYLINDER_PRESSURE(entry),
entry->o2pressure, entry->o2sensor[0], entry->o2sensor[1], entry->o2sensor[2], entry->pressures.o2);
}
fclose(f1);
}

View file

@ -25,7 +25,7 @@ struct plot_data {
int pressure[2];
/* diluentpressure[0] is diluent pressure [CCR]
* diluentpressure[1] is interpolated diluent pressure [CCR] */
int diluentpressure[2];
int o2cylinderpressure[2];
int temperature;
/* Depth info */
int depth;
@ -40,7 +40,7 @@ struct plot_data {
int smoothed;
int sac;
struct gas_pressures pressures;
double o2setpoint, o2sensor[3]; //for rebreathers with up to 3 PO2 sensors
double o2pressure, o2sensor[3]; //for rebreathers with up to 3 PO2 sensors
double mod, ead, end, eadd;
velocity_t velocity;
int speed;
@ -91,9 +91,9 @@ int get_maxdepth(struct plot_info *pi);
#define SENSOR_PR 0
#define INTERPOLATED_PR 1
#define SENSOR_PRESSURE(_entry) (_entry)->pressure[SENSOR_PR]
#define DILUENT_PRESSURE(_entry) (_entry)->diluentpressure[SENSOR_PR]
#define O2CYLINDER_PRESSURE(_entry) (_entry)->o2cylinderpressure[SENSOR_PR]
#define INTERPOLATED_PRESSURE(_entry) (_entry)->pressure[INTERPOLATED_PR]
#define INTERPOLATED_DILUENT_PRESSURE(_entry) (_entry)->diluentpressure[INTERPOLATED_PR]
#define INTERPOLATED_O2CYLINDER_PRESSURE(_entry) (_entry)->o2cylinderpressure[INTERPOLATED_PR]
#define GET_PRESSURE(_entry) (SENSOR_PRESSURE(_entry) ? SENSOR_PRESSURE(_entry) : INTERPOLATED_PRESSURE(_entry))
#define SAC_WINDOW 45 /* sliding window in seconds for current SAC calculation */

View file

@ -215,7 +215,7 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl
put_milli(b, " depth='", sample->depth.mm, " m'");
put_temperature(b, sample->temperature, " temp='", " C'");
put_pressure(b, sample->cylinderpressure, " pressure='", " bar'");
put_pressure(b, sample->diluentpressure, " pdiluent='", " bar'");
put_pressure(b, sample->o2cylinderpressure, " pdiluent='", " bar'");
/*
* We only show sensor information for samples with pressure, and only if it