Start cleaning up sensor indexing for multiple sensors

This is a very timid start at making us actually use multiple sensors
without the magical special case for just CCR oxygen tracking.

It mainly does:

 - turn the "sample->sensor" index into an array of two indexes, to
   match the pressures themselves.

 - get rid of dive->{oxygen_cylinder_index,diluent_cylinder_index},
   since a CCR dive should now simply set the sample->sensor[] indices
   correctly instead.

 - in a couple of places, start actually looping over the sensors rather
   than special-case the O2 case (although often the small "loops" are
   just unrolled, since it's just two cases.

but in many cases we still end up only covering the zero sensor case,
because the CCR O2 sensor code coverage was fairly limited.

It's entirely possible (even likely) that this migth break some existing
case: it tries to be a fairly direct ("stupid") translation of the old
code, but unlike the preparatory patch this does actually does change
some semantics.

For example, right now the git loader code assumes that if the git save
data contains a o2pressure entry, it just hardcodes the O2 sensor index
to 1.

In fact, one issue is going to simply be that our file formats do not
have that multiple sensor format, but instead had very clearly encoded
things as being the CCR O2 pressure sensor.

But this is hopefully close to usable, and I will need feedback (and
maybe test cases) from people who have existing CCR dives with pressure
data.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Linus Torvalds 2017-07-20 19:49:45 -07:00 committed by Dirk Hohndel
parent 11a0c0cc70
commit 1e38d9239a
19 changed files with 174 additions and 188 deletions

View file

@ -584,7 +584,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
sample->stoptime.seconds = deco_time;
sample->stopdepth.mm = lrint(deco_ceiling * FEET * 1000);
sample->temperature.mkelvin = C_to_mkelvin((temp - 32) / 1.8);
sample->sensor = 0;
sample->sensor[0] = 0;
sample->pressure[0].mbar = lrint(psi * PSI / 100);
finish_sample(dc);

View file

@ -1207,12 +1207,6 @@ unsigned int dc_airtemp(struct divecomputer *dc)
return (sum + nr / 2) / nr;
}
static void fixup_cylinder_use(struct dive *dive) // for CCR dives, store the indices
{ // of the oxygen and diluent cylinders
dive->oxygen_cylinder_index = get_cylinder_idx_by_use(dive, OXYGEN);
dive->diluent_cylinder_index = get_cylinder_idx_by_use(dive, DILUENT);
}
static void fixup_airtemp(struct dive *dive)
{
if (!dive->airtemp.mkelvin)
@ -1354,26 +1348,25 @@ static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc)
static void simplify_dc_pressures(struct divecomputer *dc)
{
int i;
int lastindex = -1;
int lastpressure = 0, lasto2pressure = 0;
int lastindex[2] = { -1, -1 };
int lastpressure[2] = { 0 };
for (i = 0; i < dc->samples; i++) {
int j;
struct sample *sample = dc->sample + i;
int pressure = sample->pressure[0].mbar;
int o2_pressure = sample->pressure[1].mbar;
int index;
index = sample->sensor;
if (index == lastindex) {
/* Remove duplicate redundant pressure information */
if (pressure == lastpressure)
sample->pressure[0].mbar = 0;
if (o2_pressure == lasto2pressure)
sample->pressure[1].mbar = 0;
for (j = 0; j < 2; j++) {
int pressure = sample->pressure[j].mbar;
int index = sample->sensor[j];
if (index == lastindex[j]) {
/* Remove duplicate redundant pressure information */
if (pressure == lastpressure[j])
sample->pressure[j].mbar = 0;
}
lastindex[j] = index;
lastpressure[j] = pressure;
}
lastindex = index;
lastpressure = pressure;
lasto2pressure = o2_pressure;
}
}
@ -1411,10 +1404,7 @@ static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
*/
static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
{
int i, o2index = -1;
if (dive->dc.divemode == CCR)
o2index = get_cylinder_idx_by_use(dive, OXYGEN);
int i;
/* Walk the samples from the beginning to find starting pressures.. */
for (i = 0; i < dc->samples; i++) {
@ -1423,8 +1413,8 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
if (sample->depth.mm < SURFACE_THRESHOLD)
continue;
fixup_start_pressure(dive, sample->sensor, sample->pressure[0]);
fixup_start_pressure(dive, o2index, sample->pressure[1]);
fixup_start_pressure(dive, sample->sensor[0], sample->pressure[0]);
fixup_start_pressure(dive, sample->sensor[1], sample->pressure[1]);
}
/* ..and from the end for ending pressures */
@ -1434,8 +1424,8 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc)
if (sample->depth.mm < SURFACE_THRESHOLD)
continue;
fixup_end_pressure(dive, sample->sensor, sample->pressure[0]);
fixup_end_pressure(dive, o2index, sample->pressure[1]);
fixup_end_pressure(dive, sample->sensor[0], sample->pressure[0]);
fixup_end_pressure(dive, sample->sensor[1], sample->pressure[1]);
}
simplify_dc_pressures(dc);
@ -1575,7 +1565,6 @@ struct dive *fixup_dive(struct dive *dive)
fixup_duration(dive);
fixup_watertemp(dive);
fixup_airtemp(dive);
fixup_cylinder_use(dive); // store indices for CCR oxygen and diluent cylinders
for (i = 0; i < MAX_CYLINDERS; i++) {
cylinder_t *cyl = dive->cylinder + i;
add_cylinder_description(&cyl->type);
@ -1715,8 +1704,12 @@ static void merge_samples(struct divecomputer *res, struct divecomputer *a, stru
sample.temperature = as->temperature;
if (as->pressure[0].mbar)
sample.pressure[0] = as->pressure[0];
if (as->sensor)
sample.sensor = as->sensor;
if (as->sensor[0])
sample.sensor[0] = as->sensor[0];
if (as->pressure[1].mbar)
sample.pressure[1] = as->pressure[1];
if (as->sensor[1])
sample.sensor[1] = as->sensor[1];
if (as->cns)
sample.cns = as->cns;
if (as->setpoint.mbar)
@ -1950,11 +1943,15 @@ void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, int mappin
/* Remap the sensor indexes */
for (i = 0; i < dc->samples; i++) {
struct sample *s = dc->sample + i;
int sensor;
int j;
sensor = mapping[s->sensor];
if (sensor >= 0)
s->sensor = sensor;
for (j = 0; j < 2; j++) {
int sensor;
sensor = mapping[s->sensor[j]];
if (sensor >= 0)
s->sensor[j] = sensor;
}
}
/* Remap the gas change indexes */
@ -2627,7 +2624,7 @@ static int same_sample(struct sample *a, struct sample *b)
return 0;
if (a->pressure[0].mbar != b->pressure[0].mbar)
return 0;
return a->sensor == b->sensor;
return a->sensor[0] == b->sensor[0];
}
static int same_dc(struct divecomputer *a, struct divecomputer *b)

View file

@ -198,7 +198,7 @@ struct sample // BASE TYPE BYTES UNITS RANGE DE
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
uint8_t sensor; // uint8_t 1 sensorID (0-255) ID of cylinder pressure sensor
uint8_t sensor[2]; // uint8_t 1 sensorID (0-255) ID of cylinder pressure sensor
uint8_t cns; // uint8_t 1 % (0-255 %) cns% accumulated
uint8_t heartbeat; // uint8_t 1 beats/m (0-255) heart rate measurement
volume_t sac; // 4 ml/min predefined SAC
@ -352,7 +352,6 @@ struct dive {
struct divecomputer dc;
int id; // unique ID for this dive
struct picture *picture_list;
int oxygen_cylinder_index, diluent_cylinder_index; // CCR dive cylinder indices
unsigned char git_id[20];
};

View file

@ -330,7 +330,7 @@ static void add_dive_to_deco(struct dive *dive)
for (j = t0; j < t1; j++) {
int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0);
add_segment(depth_to_bar(depth, dive),
&dive->cylinder[sample->sensor].gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
&dive->cylinder[sample->sensor[0]].gasmix, 1, sample->setpoint.mbar, dive, dive->sac);
}
}
}

View file

@ -197,7 +197,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, bool o2_flag)
static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr, int sensoridx)
{
int cyl, i;
struct plot_data *entry;
@ -243,20 +243,12 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
entry = pi->entry + i;
if (o2_flag) {
// Find the cylinder index (cyl) and pressure
cyl = dive->oxygen_cylinder_index;
if (cyl < 0)
return; // Can we do this?!?
pressure = O2CYLINDER_PRESSURE(entry);
save_pressure = &(entry->pressure[1][SENSOR_PR]);
save_interpolated = &(entry->pressure[1][INTERPOLATED_PR]);
} else {
pressure = SENSOR_PRESSURE(entry);
save_pressure = &(entry->pressure[0][SENSOR_PR]);
save_interpolated = &(entry->pressure[0][INTERPOLATED_PR]);
cyl = entry->cylinderindex;
}
cyl = entry->sensor[sensoridx];
if (cyl < 0)
continue;
save_pressure = &(entry->pressure[sensoridx][SENSOR_PR]);
save_interpolated = &(entry->pressure[sensoridx][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,
@ -346,7 +338,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 o2_flag)
void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, int sensoridx)
{
(void) dc;
int i, cylinderid, cylinderindex = -1;
@ -369,15 +361,12 @@ 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 (o2_flag) { // if this is a diluent cylinder:
pressure = O2CYLINDER_PRESSURE(entry);
cylinderid = dive->oxygen_cylinder_index;
if (cylinderid < 0)
goto GIVE_UP;
} else {
pressure = SENSOR_PRESSURE(entry);
cylinderid = entry->cylinderindex;
}
pressure = SENSOR_PRESSURE(entry, sensoridx);
cylinderid = entry->sensor[sensoridx];
if (cylinderid < 0)
goto GIVE_UP;
/* If track_pr structure already exists, then update it: */
/* discrete integration of pressure over time to get the SAC rate equivalent */
if (current) {
@ -389,10 +378,7 @@ 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 (o2_flag) // For CCR dives:
cylinderindex = dive->oxygen_cylinder_index; // indicate o2 cylinder
else
cylinderindex = entry->cylinderindex;
cylinderindex = entry->sensor[sensoridx];
current = pr_track_alloc(pressure, entry->sec);
track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current);
continue;
@ -406,9 +392,7 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
current->end = pressure;
/* Was it continuous? */
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
if (SENSOR_PRESSURE(entry - 1, sensoridx))
continue;
/* transmitter stopped transmitting cylinder pressure data */
@ -418,7 +402,7 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
}
if (missing_pr) {
fill_missing_tank_pressures(dive, pi, track_pr, o2_flag);
fill_missing_tank_pressures(dive, pi, track_pr, sensoridx);
}
#ifdef PRINT_PRESSURES_DEBUG

View file

@ -352,17 +352,15 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata)
case DC_SAMPLE_DEPTH:
sample->depth.mm = lrint(value.depth * 1000);
break;
case DC_SAMPLE_PRESSURE:
case DC_SAMPLE_PRESSURE: {
int sensoridx = 0;
/* Do we already have a pressure reading? */
if (sample->pressure[0].mbar) {
/* Do we prefer the one we already have? */
/* If so, just ignore the new one */
if (sample->sensor == current_gas_index)
break;
}
sample->sensor = value.pressure.tank;
sample->pressure[0].mbar = lrint(value.pressure.value * 1000);
if (sample->pressure[0].mbar)
sensoridx = 1;
sample->sensor[sensoridx] = value.pressure.tank;
sample->pressure[sensoridx].mbar = lrint(value.pressure.value * 1000);
break;
}
case DC_SAMPLE_GASMIX:
handle_gasmix(dc, sample, value.gasmix);
break;

View file

@ -334,7 +334,7 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int
sample->time.seconds = event.time;
sample->depth.mm = array_uint16_le(ds + (d - 1) * 2) * 10; // cm->mm
sample->temperature.mkelvin = C_to_mkelvin((float) array_uint16_le(ts + (d - 1) * 2) / 10); // dC->mK
sample->sensor = event.pressure.sensor;
sample->sensor[0] = event.pressure.sensor;
sample->pressure[0].mbar = event.pressure.mbar;
finish_sample(dc);
@ -352,7 +352,7 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int
sample->time.seconds = sample_time;
sample->depth.mm = depth_mm;
sample->temperature.mkelvin = temp_mk;
sample->sensor = event.pressure.sensor;
sample->sensor[0] = event.pressure.sensor;
sample->pressure[0].mbar = event.pressure.mbar;
finish_sample(dc);
d++;
@ -360,7 +360,7 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int
break;
} else { // Event is prior to sample
sample->time.seconds = event.time;
sample->sensor = event.pressure.sensor;
sample->sensor[0] = event.pressure.sensor;
sample->pressure[0].mbar = event.pressure.mbar;
if (last_time == sample_time) {
sample->depth.mm = depth_mm;

View file

@ -485,7 +485,7 @@ static void parse_sample_keyvalue(void *_sample, const char *key, const char *va
struct sample *sample = _sample;
if (!strcmp(key, "sensor")) {
sample->sensor = atoi(value);
sample->sensor[0] = atoi(value);
return;
}
if (!strcmp(key, "ndl")) {
@ -540,6 +540,11 @@ static void parse_sample_keyvalue(void *_sample, const char *key, const char *va
}
if (!strcmp(key, "o2pressure")) {
pressure_t p = get_pressure(value);
//
// FIXME!!! What's the O2 cylinder index?
// get_cylinder_idx_by_use(dive, OXYGEN)
//
sample->sensor[1] = 1;
sample->pressure[1].mbar = p.mbar;
return;
}

View file

@ -151,7 +151,7 @@ static bool in_userid = false;
static struct tm cur_tm;
static int cur_cylinder_index, cur_ws_index;
static int lastndl, laststoptime, laststopdepth, lastcns, lastpo2, lastindeco;
static int lastcylinderindex, lastsensor, next_o2_sensor;
static int lastcylinderindex, lastsensor, lasto2sensor = 1, next_o2_sensor;
static struct extra_data cur_extra_data;
/*
@ -352,8 +352,12 @@ static void pressure(char *buffer, pressure_t *pressure)
static void cylinder_use(char *buffer, enum cylinderuse *cyl_use)
{
if (trimspace(buffer))
*cyl_use = cylinderuse_from_text(buffer);
if (trimspace(buffer)) {
int use = cylinderuse_from_text(buffer);
*cyl_use = use;
if (use == OXYGEN)
lasto2sensor = cur_cylinder_index;
}
}
static void salinity(char *buffer, int *salinity)
@ -935,9 +939,9 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return;
if (MATCH("o2pressure.sample", pressure, &sample->pressure[1]))
return;
if (MATCH("cylinderindex.sample", get_cylinderindex, &sample->sensor))
if (MATCH("cylinderindex.sample", get_cylinderindex, &sample->sensor[0]))
return;
if (MATCH("sensor.sample", get_sensor, &sample->sensor))
if (MATCH("sensor.sample", get_sensor, &sample->sensor[0]))
return;
if (MATCH("depth.sample", depth, &sample->depth))
return;
@ -1524,6 +1528,7 @@ static void reset_dc_info(struct divecomputer *dc)
(void) dc;
lastcns = lastpo2 = lastndl = laststoptime = laststopdepth = lastindeco = 0;
lastsensor = lastcylinderindex = 0;
lasto2sensor = 1;
}
static void reset_dc_settings(void)
@ -1718,7 +1723,8 @@ static void sample_start(void)
cur_sample->stopdepth.mm = laststopdepth;
cur_sample->cns = lastcns;
cur_sample->setpoint.mbar = lastpo2;
cur_sample->sensor = lastsensor;
cur_sample->sensor[0] = lastsensor;
cur_sample->sensor[1] = lasto2sensor;
next_o2_sensor = 0;
}

View file

@ -47,7 +47,7 @@ static void dump_pi(struct plot_info *pi)
struct plot_data *entry = &pi->entry[i];
printf(" entry[%d]:{cylinderindex:%d sec:%d pressure:{%d,%d}\n"
" time:%d:%02d temperature:%d depth:%d stopdepth:%d stoptime:%d ndl:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n",
i, entry->cylinderindex, entry->sec,
i, entry->sensor[0], entry->sec,
entry->pressure[0], entry->pressure[1],
entry->sec / 60, entry->sec % 60,
entry->temperature, entry->depth, entry->stopdepth, entry->stoptime, entry->ndl, entry->smoothed,
@ -170,19 +170,19 @@ 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->cylinderindex;
int index = entry1->sensor[0];
cylinder_t *cyl;
int duration = entry2->sec - entry1->sec;
int depth, airuse;
pressure_t a, b;
double atm;
if (entry2->cylinderindex != index)
if (entry2->sensor[0] != index)
return 0;
if (duration <= 0)
return 0;
a.mbar = GET_PRESSURE(entry1);
b.mbar = GET_PRESSURE(entry2);
a.mbar = GET_PRESSURE(entry1, 0);
b.mbar = GET_PRESSURE(entry2, 0);
if (!b.mbar || a.mbar <= b.mbar)
return 0;
@ -368,8 +368,8 @@ static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, in
struct plot_data *entry = pi->entry + i;
if (entry->sec > end)
break;
if (entry->cylinderindex != cylinderindex) {
entry->cylinderindex = cylinderindex;
if (entry->sensor[0] != cylinderindex) {
entry->sensor[0] = cylinderindex;
entry->pressure[0][0] = 0;
}
i++;
@ -396,7 +396,7 @@ static int set_first_cylinder_index(struct plot_info *pi, int i, int cylinderind
struct plot_data *entry = pi->entry + i;
if (entry->sec > end)
break;
entry->cylinderindex = cylinderindex;
entry->sensor[0] = cylinderindex;
i++;
}
return i;
@ -545,7 +545,7 @@ struct plot_info calculate_max_limits_new(struct dive *dive, struct divecomputer
entry->sec = _time; \
entry->depth = _depth; \
entry->running_sum = (entry - 1)->running_sum + (_time - (entry - 1)->sec) * (_depth + (entry - 1)->depth) / 2; \
SENSOR_PRESSURE(entry) = 0; \
SENSOR_PRESSURE(entry, 0) = 0; \
entry->sac = _sac; \
entry++; \
idx++
@ -640,9 +640,10 @@ 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;
SENSOR_PRESSURE(entry) = sample->pressure[0].mbar;
O2CYLINDER_PRESSURE(entry) = sample->pressure[1].mbar;
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->temperature.mkelvin)
entry->temperature = lasttemp = sample->temperature.mkelvin;
else
@ -685,40 +686,34 @@ 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, bool o2flag)
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->cylinderindex != idx && !o2flag)
if (entry->sensor[sensoridx] != idx)
continue;
if (CYLINDER_PRESSURE(o2flag, entry))
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->cylinderindex != idx && !o2flag)
if (entry->sensor[sensoridx] != idx)
continue;
if (o2flag)
O2CYLINDER_PRESSURE(entry) = start;
else
SENSOR_PRESSURE(entry) = start;
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->cylinderindex != idx && !o2flag)
if (entry->sensor[sensoridx] != idx)
continue;
if (o2flag)
O2CYLINDER_PRESSURE(entry) = end;
else
SENSOR_PRESSURE(entry) = end;
SENSOR_PRESSURE(entry, sensoridx) = end;
break;
}
}
@ -740,9 +735,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);
b.mbar = GET_PRESSURE(last);
cyl = dive->cylinder + first->cylinderindex;
a.mbar = GET_PRESSURE(first, 0);
b.mbar = GET_PRESSURE(last, 0);
cyl = dive->cylinder + first->sensor[0];
airuse = gas_volume(cyl, a) - gas_volume(cyl, b);
if (airuse <= 0)
return 0;
@ -777,7 +772,7 @@ static void fill_sac(struct dive *dive, struct plot_info *pi, int idx)
if (entry->sac)
return;
if (!GET_PRESSURE(entry))
if (!GET_PRESSURE(entry, 0))
return;
/*
@ -788,13 +783,13 @@ 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->cylinderindex != first->cylinderindex)
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))
if (!GET_PRESSURE(prev, 0))
break;
idx--;
first = prev;
@ -805,13 +800,13 @@ 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->cylinderindex != last->cylinderindex)
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))
if (!GET_PRESSURE(next, 0))
break;
last = next;
}
@ -882,7 +877,7 @@ 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->cylinderindex;
int cylinderindex = entry->sensor[0];
/* If iterating through a dive, entry->tts_calc needs to be reset */
entry->tts_calc = 0;
@ -976,7 +971,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->cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
&dive->cylinder[entry->sensor[0]].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
if ((t1 - j < time_stepsize) && (j < t1))
time_stepsize = t1 - j;
}
@ -1130,7 +1125,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->cylinderindex;
int cylinderindex = entry->sensor[0];
amb_pressure = depth_to_bar(entry->depth, dive);
@ -1299,8 +1294,8 @@ static void plot_string(struct plot_info *pi, struct plot_data *entry, struct me
depthvalue = get_depth_units(entry->depth, NULL, &depth_unit);
put_format(b, translate("gettextFromC", "@: %d:%02d\nD: %.1f%s\n"), FRACTION(entry->sec, 60), depthvalue, depth_unit);
if (GET_PRESSURE(entry)) {
pressurevalue = get_pressure_units(GET_PRESSURE(entry), &pressure_unit);
if (GET_PRESSURE(entry, 0)) {
pressurevalue = get_pressure_units(GET_PRESSURE(entry, 0), &pressure_unit);
put_format(b, translate("gettextFromC", "P: %d%s\n"), pressurevalue, pressure_unit);
}
if (entry->temperature) {
@ -1481,8 +1476,8 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
bar_used = 0;
last_sec = start->sec;
last_pressure = GET_PRESSURE(start);
last_cylidx = start->cylinderindex;
last_pressure = GET_PRESSURE(start, 0);
last_cylidx = start->sensor[0];
data = start;
while (data != stop) {
@ -1503,16 +1498,16 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
if (data->depth > max_depth)
max_depth = data->depth;
/* Try to detect gas changes - this hack might work for some side mount scenarios? */
if (GET_PRESSURE(data) < last_pressure + 2000)
bar_used += last_pressure - GET_PRESSURE(data);
if (GET_PRESSURE(data, 0) < last_pressure + 2000)
bar_used += last_pressure - GET_PRESSURE(data, 0);
if (data->cylinderindex != last_cylidx)
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);
last_pressure = GET_PRESSURE(data, 0);
}
avg_depth /= stop->sec - start->sec;
avg_speed /= stop->sec - start->sec;
@ -1553,7 +1548,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->cylinderindex;
cylinder_t *cyl = displayed_dive.cylinder + start->sensor[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;
@ -1561,13 +1556,13 @@ void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int
const char *volume_unit;
struct plot_data *first = start;
struct plot_data *last = stop;
while (first < stop && GET_PRESSURE(first) == 0)
while (first < stop && GET_PRESSURE(first, 0) == 0)
first++;
while (last > first && GET_PRESSURE(last) == 0)
while (last > first && GET_PRESSURE(last, 0) == 0)
last--;
pressure_t first_pressure = { GET_PRESSURE(first) };
pressure_t stop_pressure = { GET_PRESSURE(last) };
pressure_t first_pressure = { GET_PRESSURE(first, 0) };
pressure_t stop_pressure = { GET_PRESSURE(last, 0) };
int volume_used = gas_volume(cyl, first_pressure) - gas_volume(cyl, stop_pressure);
/* Mean pressure in ATM */

View file

@ -21,7 +21,7 @@ struct divecomputer;
struct plot_info;
struct plot_data {
unsigned int in_deco : 1;
int cylinderindex;
char sensor[2];
int sec;
/* pressure[0] is main sensor pressure (diluent for CCR)
* pressure[1] is secondary sensor pressure (O2 for CCR)
@ -98,13 +98,9 @@ int get_maxdepth(struct plot_info *pi);
#define SENSOR_PR 0
#define INTERPOLATED_PR 1
#define SENSOR_PRESSURE(_entry) (_entry)->pressure[0][SENSOR_PR]
#define O2CYLINDER_PRESSURE(_entry) (_entry)->pressure[1][SENSOR_PR]
#define CYLINDER_PRESSURE(_o2, _entry) (_o2 ? O2CYLINDER_PRESSURE(_entry) : SENSOR_PRESSURE(_entry))
#define INTERPOLATED_PRESSURE(_entry) (_entry)->pressure[0][INTERPOLATED_PR]
#define INTERPOLATED_O2CYLINDER_PRESSURE(_entry) (_entry)->pressure[1][INTERPOLATED_PR]
#define GET_PRESSURE(_entry) (SENSOR_PRESSURE(_entry) ? SENSOR_PRESSURE(_entry) : INTERPOLATED_PRESSURE(_entry))
#define GET_O2CYLINDER_PRESSURE(_entry) (O2CYLINDER_PRESSURE(_entry) ? O2CYLINDER_PRESSURE(_entry) : INTERPOLATED_O2CYLINDER_PRESSURE(_entry))
#define SENSOR_PRESSURE(_entry,_idx) (_entry)->pressure[_idx][SENSOR_PR]
#define INTERPOLATED_PRESSURE(_entry,_idx) (_entry)->pressure[_idx][INTERPOLATED_PR]
#define GET_PRESSURE(_entry,_idx) (SENSOR_PRESSURE(_entry,_idx) ? SENSOR_PRESSURE(_entry,_idx) : INTERPOLATED_PRESSURE(_entry,_idx))
#define SAC_WINDOW 45 /* sliding window in seconds for current SAC calculation */
#ifdef __cplusplus

View file

@ -253,9 +253,9 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl
* We only show sensor information for samples with pressure, and only if it
* changed from the previous sensor we showed.
*/
if (sample->pressure[0].mbar && sample->sensor != old->sensor) {
put_format(b, " sensor=%d", sample->sensor);
old->sensor = sample->sensor;
if (sample->pressure[0].mbar && sample->sensor[0] != old->sensor[0]) {
put_format(b, " sensor=%d", sample->sensor[0]);
old->sensor[0] = sample->sensor[0];
}
/* the deco/ndl values are stored whenever they change */

View file

@ -207,9 +207,9 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl
* We only show sensor information for samples with pressure, and only if it
* changed from the previous sensor we showed.
*/
if (sample->pressure[0].mbar && sample->sensor != old->sensor) {
put_format(b, " sensor='%d'", sample->sensor);
old->sensor = sample->sensor;
if (sample->pressure[0].mbar && sample->sensor[0] != old->sensor[0]) {
put_format(b, " sensor='%d'", sample->sensor[0]);
old->sensor[0] = sample->sensor[0];
}
/* the deco/ndl values are stored whenever they change */

View file

@ -305,7 +305,8 @@ void get_selected_dives_text(char *buffer, size_t size)
#define SOME_GAS 5000 // 5bar drop in cylinder pressure makes cylinder used
bool has_gaschange_event(struct dive *dive, struct divecomputer *dc, int idx) {
bool has_gaschange_event(struct dive *dive, struct divecomputer *dc, int idx)
{
bool first_gas_explicit = false;
struct event *event = get_next_event(dc->events, "gaschange");
while (event) {
@ -316,8 +317,12 @@ bool has_gaschange_event(struct dive *dive, struct divecomputer *dc, int idx) {
return true;
event = get_next_event(event->next, "gaschange");
}
if (dc->divemode == CCR && (idx == dive->diluent_cylinder_index || idx == dive->oxygen_cylinder_index))
return true;
if (dc->divemode == CCR) {
if (idx == get_cylinder_idx_by_use(dive, DILUENT))
return true;
if (idx == get_cylinder_idx_by_use(dive, OXYGEN))
return true;
}
return !first_gas_explicit && idx == 0;
}

View file

@ -359,7 +359,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap)
sample->time.seconds = u_sample->dive_time;
sample->depth.mm = rel_mbar_to_depth(u_sample->water_pressure, dive);
sample->temperature.mkelvin = C_to_mkelvin(u_sample->dive_temperature / 10.0);
sample->sensor = active;
sample->sensor[0] = active;
sample->pressure[0].mbar =
(u_sample->tank_pressure_high * 256 + u_sample->tank_pressure_low) * 10;
sample->cns = u_sample->cns;

View file

@ -693,13 +693,13 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
o2mbar = 0;
plot_data *entry = dataModel->data().entry + i;
int mbar = GET_PRESSURE(entry);
int mbar = GET_PRESSURE(entry, 0);
if (displayed_dive.dc.divemode == CCR)
o2mbar = GET_O2CYLINDER_PRESSURE(entry);
o2mbar = GET_PRESSURE(entry, 1);
if ((int)entry->cylinderindex != last_index) {
if ((int)entry->sensor[0] != last_index) {
polygons.append(QPolygonF()); // this is the polygon that will be actually drawn on screen.
last_index = entry->cylinderindex;
last_index = entry->sensor[0];
}
if (!mbar) {
continue;
@ -739,15 +739,16 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
double axisLog = log10(log10(axisRange));
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
entry = dataModel->data().entry + i;
mbar = GET_PRESSURE(entry);
if (displayed_dive.dc.divemode == CCR && displayed_dive.oxygen_cylinder_index >= 0)
o2mbar = GET_O2CYLINDER_PRESSURE(entry);
if (o2mbar) { // If there is an o2mbar value then this is a CCR dive. Then do:
// The first time an o2 value is detected, see if the oxygen cyl pressure graph starts above or below the dil graph
dilcyl = entry->sensor[0];
o2cyl = entry->sensor[1];
mbar = GET_PRESSURE(entry, 0);
if (o2cyl >= 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:
o2cyl = displayed_dive.oxygen_cylinder_index;
dilcyl = displayed_dive.diluent_cylinder_index;
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[dilcyl][0] = 5 * axisLog; // y offset for diluent gas lable (below)
@ -760,21 +761,21 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
offsets_initialised = true;
}
if (!seen_cyl[displayed_dive.oxygen_cylinder_index]) { //For o2, on the left of profile, write lable and pressure
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[displayed_dive.oxygen_cylinder_index].gasmix, align_o2, print_y_offset[o2cyl][0]);
seen_cyl[displayed_dive.oxygen_cylinder_index] = true;
plotGasValue(o2mbar, entry->sec, displayed_dive.cylinder[o2cyl].gasmix, align_o2, print_y_offset[o2cyl][0]);
seen_cyl[o2cyl] = true;
}
last_pressure[displayed_dive.oxygen_cylinder_index] = o2mbar;
last_time[displayed_dive.oxygen_cylinder_index] = entry->sec;
last_pressure[o2cyl] = o2mbar;
last_time[o2cyl] = entry->sec;
alignVar = align_dil;
}
if (!mbar)
continue;
if (cyl != (int)entry->cylinderindex) { // Pressure value near the left hand edge of the profile - other cylinders:
cyl = entry->cylinderindex; // For each other cylinder, write the gas lable and pressure
if (cyl != dilcyl) { // Pressure value near the left hand edge of the profile - other cylinders:
cyl = dilcyl; // 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]);
@ -786,7 +787,7 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
}
for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { // For each cylinder, on right hand side of profile, write cylinder pressure
alignVar = ((o2cyl >= 0) && (cyl == displayed_dive.oxygen_cylinder_index)) ? align_o2 : align_dil;
alignVar = ((o2cyl >= 0) && (cyl == o2cyl)) ? align_o2 : align_dil;
if (last_time[cyl]) {
plotPressureValue(last_pressure[cyl], last_time[cyl], (alignVar | Qt::AlignLeft), print_y_offset[cyl][1]);
}

View file

@ -1407,7 +1407,7 @@ 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->cylinderindex)
if (i == entry->sensor[0])
action->setDisabled(true);
gasChange->addAction(action);
}
@ -1457,21 +1457,21 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
if (gasChangeEntry + 1 <= plotInfo.entry + plotInfo.nr) {
newGasEntry = gasChangeEntry + 1;
qDebug() << "after gas change at " << newGasEntry->sec << ": sensor pressure" << newGasEntry->pressure[0] << "interpolated" << newGasEntry->pressure[1];
if (SENSOR_PRESSURE(gasChangeEntry) == 0 || displayed_dive.cylinder[gasChangeEntry->cylinderindex].sample_start.mbar == 0) {
if (SENSOR_PRESSURE(gasChangeEntry) == 0 || displayed_dive.cylinder[gasChangeEntry->sensor[0]].sample_start.mbar == 0) {
// if we have no sensorpressure or if we have no pressure from samples we can assume that
// we only have interpolated pressure (the pressure in the entry may be stored in the sensor
// pressure field if this is the first or last entry for this tank... see details in gaspressures.c
pressure_t pressure;
pressure.mbar = INTERPOLATED_PRESSURE(gasChangeEntry) ? : SENSOR_PRESSURE(gasChangeEntry);
QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)")
.arg(gasChangeEntry->cylinderindex + 1).arg(get_pressure_string(pressure)));
.arg(gasChangeEntry->sensor[0] + 1).arg(get_pressure_string(pressure)));
}
if (SENSOR_PRESSURE(newGasEntry) == 0 || displayed_dive.cylinder[newGasEntry->cylinderindex].sample_start.mbar == 0) {
if (SENSOR_PRESSURE(newGasEntry) == 0 || displayed_dive.cylinder[newGasEntry->sensor[0]].sample_start.mbar == 0) {
// we only have interpolated press -- see commend above
pressure_t pressure;
pressure.mbar = INTERPOLATED_PRESSURE(newGasEntry) ? : SENSOR_PRESSURE(newGasEntry);
QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of tank %1 (currently interpolated as %2)")
.arg(newGasEntry->cylinderindex + 1).arg(get_pressure_string(pressure)));
.arg(newGasEntry->sensor[0] + 1).arg(get_pressure_string(pressure)));
}
}
}

View file

@ -98,7 +98,7 @@ 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->cylinderindex;
int cylIdx = entry->sensor[0];
int i = -1;
int startTime = 0;
struct gasmix *gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
@ -106,12 +106,12 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b
while (++i < pInfoNr) {
entry = &pInfoEntry[i];
lastentry = &pInfoEntry[i-1];
if (entry->cylinderindex == cylIdx)
if (entry->sensor[0] == cylIdx)
continue;
width = hAxis->posAtValue(lastentry->sec) - hAxis->posAtValue(startTime);
left = hAxis->posAtValue(startTime);
createBar(left, width, gas);
cylIdx = entry->cylinderindex;
cylIdx = entry->sensor[0];
gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
startTime = lastentry->sec;
}

View file

@ -40,7 +40,7 @@ QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
case USERENTERED:
return false;
case CYLINDERINDEX:
return item.cylinderindex;
return item.sensor[0];
case SENSOR_PRESSURE:
return item.pressure[0][0];
case INTERPOLATED_PRESSURE: