From 1e38d9239a7bac621eedcb2bab98b90d78b988af Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 20 Jul 2017 19:49:45 -0700 Subject: [PATCH] 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 Signed-off-by: Dirk Hohndel --- core/cochran.c | 2 +- core/dive.c | 71 +++++++++++------------ core/dive.h | 3 +- core/divelist.c | 2 +- core/gaspressures.c | 50 ++++++---------- core/libdivecomputer.c | 16 +++-- core/liquivision.c | 6 +- core/load-git.c | 7 ++- core/parse-xml.c | 18 ++++-- core/profile.c | 93 ++++++++++++++---------------- core/profile.h | 12 ++-- core/save-git.c | 6 +- core/save-xml.c | 6 +- core/statistics.c | 11 +++- core/uemis.c | 2 +- profile-widget/diveprofileitem.cpp | 39 +++++++------ profile-widget/profilewidget2.cpp | 10 ++-- profile-widget/tankitem.cpp | 6 +- qt-models/diveplotdatamodel.cpp | 2 +- 19 files changed, 174 insertions(+), 188 deletions(-) diff --git a/core/cochran.c b/core/cochran.c index 5929a7a27..f447a846a 100644 --- a/core/cochran.c +++ b/core/cochran.c @@ -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); diff --git a/core/dive.c b/core/dive.c index 229a04eba..6406242bf 100644 --- a/core/dive.c +++ b/core/dive.c @@ -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) diff --git a/core/dive.h b/core/dive.h index 73de24b61..2d1b761f0 100644 --- a/core/dive.h +++ b/core/dive.h @@ -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]; }; diff --git a/core/divelist.c b/core/divelist.c index 4f253039b..d51aedf78 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -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); } } } diff --git a/core/gaspressures.c b/core/gaspressures.c index 77a19429f..86ea8de7a 100644 --- a/core/gaspressures.c +++ b/core/gaspressures.c @@ -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 diff --git a/core/libdivecomputer.c b/core/libdivecomputer.c index 2d7778346..c935ecbce 100644 --- a/core/libdivecomputer.c +++ b/core/libdivecomputer.c @@ -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; diff --git a/core/liquivision.c b/core/liquivision.c index 3406bd3ab..dae9ae81b 100644 --- a/core/liquivision.c +++ b/core/liquivision.c @@ -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; diff --git a/core/load-git.c b/core/load-git.c index 4357e8f31..87f6ecb25 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -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; } diff --git a/core/parse-xml.c b/core/parse-xml.c index dd3e1cc0b..fdb2dab44 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -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; } diff --git a/core/profile.c b/core/profile.c index 0d3646ece..1b5c36621 100644 --- a/core/profile.c +++ b/core/profile.c @@ -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 */ diff --git a/core/profile.h b/core/profile.h index 42af6a845..988736f30 100644 --- a/core/profile.h +++ b/core/profile.h @@ -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 diff --git a/core/save-git.c b/core/save-git.c index 30e776e2f..9979aaf00 100644 --- a/core/save-git.c +++ b/core/save-git.c @@ -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 */ diff --git a/core/save-xml.c b/core/save-xml.c index f0583fb6b..151ebf0a3 100644 --- a/core/save-xml.c +++ b/core/save-xml.c @@ -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 */ diff --git a/core/statistics.c b/core/statistics.c index 18f247cb8..d86fe6324 100644 --- a/core/statistics.c +++ b/core/statistics.c @@ -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; } diff --git a/core/uemis.c b/core/uemis.c index 92b7cdfe9..eeb8a79c4 100644 --- a/core/uemis.c +++ b/core/uemis.c @@ -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; diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp index ee03e9e6e..096acd898 100644 --- a/profile-widget/diveprofileitem.cpp +++ b/profile-widget/diveprofileitem.cpp @@ -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]); } diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 90bf6dbb2..17f3544f3 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -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))); } } } diff --git a/profile-widget/tankitem.cpp b/profile-widget/tankitem.cpp index 307d3d397..89ddffed9 100644 --- a/profile-widget/tankitem.cpp +++ b/profile-widget/tankitem.cpp @@ -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; } diff --git a/qt-models/diveplotdatamodel.cpp b/qt-models/diveplotdatamodel.cpp index e5bb30ab0..b4e72b2df 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.cylinderindex; + return item.sensor[0]; case SENSOR_PRESSURE: return item.pressure[0][0]; case INTERPOLATED_PRESSURE: