Display CCR setpoint values on the po2 graph

When a CCR dive is viewed and the toolbar button for PO2 is activated,
both the PO2 (green line) and the O2 setpoint (red line) are shown.
This allows evaluation of the PO2 in the CCR loop with respect to the
pre-configured O2 setpoint.

The setpoint graph can be disabled from the Preferences/Graphs tab
by checking the appropriate checkbox.

Signed-off-by: willem ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Willem Ferguson 2015-01-05 09:20:26 +02:00 committed by Dirk Hohndel
parent 27bfbee4e8
commit 0de3bc8452
12 changed files with 33 additions and 2 deletions

1
pref.h
View file

@ -43,6 +43,7 @@ struct preferences {
short gfhigh; short gfhigh;
int animation_speed; int animation_speed;
bool gf_low_at_maxdepth; bool gf_low_at_maxdepth;
bool show_ccr_setpoint;
short display_invalid_dives; short display_invalid_dives;
short unit_system; short unit_system;
struct units units; struct units units;

View file

@ -17,7 +17,6 @@
#include "libdivecomputer/version.h" #include "libdivecomputer/version.h"
#include "membuffer.h" #include "membuffer.h"
//#define DEBUG_GAS 1 //#define DEBUG_GAS 1
int selected_dive = -1; /* careful: 0 is a valid value */ int selected_dive = -1; /* careful: 0 is a valid value */
@ -609,7 +608,7 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
entry->in_deco = sample->in_deco; entry->in_deco = sample->in_deco;
entry->cns = sample->cns; entry->cns = sample->cns;
if (dc->dctype == CCR) { if (dc->dctype == CCR) {
entry->o2pressure.mbar = sample->setpoint.mbar; // for rebreathers entry->o2pressure.mbar = entry->o2setpoint.mbar = sample->setpoint.mbar; // for rebreathers
entry->o2sensor[0].mbar = sample->o2sensor[0].mbar; // for up to three rebreather O2 sensors entry->o2sensor[0].mbar = sample->o2sensor[0].mbar; // for up to three rebreather O2 sensors
entry->o2sensor[1].mbar = sample->o2sensor[1].mbar; entry->o2sensor[1].mbar = sample->o2sensor[1].mbar;
entry->o2sensor[2].mbar = sample->o2sensor[2].mbar; entry->o2sensor[2].mbar = sample->o2sensor[2].mbar;

View file

@ -43,6 +43,7 @@ struct plot_data {
struct gas_pressures pressures; struct gas_pressures pressures;
pressure_t o2pressure; // for rebreathers, this is consensus measured po2, or setpoint otherwise. 0 for OC. pressure_t o2pressure; // for rebreathers, this is consensus measured po2, or setpoint otherwise. 0 for OC.
pressure_t o2sensor[3]; //for rebreathers with up to 3 PO2 sensors pressure_t o2sensor[3]; //for rebreathers with up to 3 PO2 sensors
pressure_t o2setpoint;
double mod, ead, end, eadd; double mod, ead, end, eadd;
velocity_t velocity; velocity_t velocity;
int speed; int speed;

View file

@ -27,6 +27,7 @@ void fill_profile_color()
profile_color[PN2_ALERT] = COLOR(RED1, BLACK1_LOW_TRANS, RED1); profile_color[PN2_ALERT] = COLOR(RED1, BLACK1_LOW_TRANS, RED1);
profile_color[PHE] = COLOR(PEANUT, BLACK1_LOW_TRANS, PEANUT); profile_color[PHE] = COLOR(PEANUT, BLACK1_LOW_TRANS, PEANUT);
profile_color[PHE_ALERT] = COLOR(RED1, BLACK1_LOW_TRANS, RED1); profile_color[PHE_ALERT] = COLOR(RED1, BLACK1_LOW_TRANS, RED1);
profile_color[O2SETPOINT] = COLOR(RED1, BLACK1_LOW_TRANS, RED1);
profile_color[PP_LINES] = COLOR(BLACK1_HIGH_TRANS, BLACK1_LOW_TRANS, BLACK1_HIGH_TRANS); profile_color[PP_LINES] = COLOR(BLACK1_HIGH_TRANS, BLACK1_LOW_TRANS, BLACK1_HIGH_TRANS);
profile_color[TEXT_BACKGROUND] = COLOR(CONCRETE1_LOWER_TRANS, WHITE1, CONCRETE1_LOWER_TRANS); profile_color[TEXT_BACKGROUND] = COLOR(CONCRETE1_LOWER_TRANS, WHITE1, CONCRETE1_LOWER_TRANS);

View file

@ -37,6 +37,7 @@ typedef enum {
PN2_ALERT, PN2_ALERT,
PHE, PHE,
PHE_ALERT, PHE_ALERT,
O2SETPOINT,
PP_LINES, PP_LINES,
/* Other colors */ /* Other colors */

View file

@ -100,6 +100,7 @@ void PreferencesDialog::setUiFromPrefs()
ui.gflow->setValue(prefs.gflow); ui.gflow->setValue(prefs.gflow);
ui.gfhigh->setValue(prefs.gfhigh); ui.gfhigh->setValue(prefs.gfhigh);
ui.gf_low_at_maxdepth->setChecked(prefs.gf_low_at_maxdepth); ui.gf_low_at_maxdepth->setChecked(prefs.gf_low_at_maxdepth);
ui.show_ccr_setpoint->setChecked(prefs.show_ccr_setpoint);
// units // units
if (prefs.unit_system == METRIC) if (prefs.unit_system == METRIC)
@ -251,6 +252,7 @@ void PreferencesDialog::syncSettings()
SAVE_OR_REMOVE("gflow", default_prefs.gflow, ui.gflow->value()); SAVE_OR_REMOVE("gflow", default_prefs.gflow, ui.gflow->value());
SAVE_OR_REMOVE("gfhigh", default_prefs.gfhigh, ui.gfhigh->value()); SAVE_OR_REMOVE("gfhigh", default_prefs.gfhigh, ui.gfhigh->value());
SAVE_OR_REMOVE("gf_low_at_maxdepth", default_prefs.gf_low_at_maxdepth, ui.gf_low_at_maxdepth->isChecked()); SAVE_OR_REMOVE("gf_low_at_maxdepth", default_prefs.gf_low_at_maxdepth, ui.gf_low_at_maxdepth->isChecked());
SAVE_OR_REMOVE("show_ccr_setpoint", default_prefs.show_ccr_setpoint, ui.show_ccr_setpoint->isChecked());
SAVE_OR_REMOVE("display_unused_tanks", default_prefs.display_unused_tanks, ui.display_unused_tanks->isChecked()); SAVE_OR_REMOVE("display_unused_tanks", default_prefs.display_unused_tanks, ui.display_unused_tanks->isChecked());
SAVE_OR_REMOVE("show_average_depth", default_prefs.show_average_depth, ui.show_average_depth->isChecked()); SAVE_OR_REMOVE("show_average_depth", default_prefs.show_average_depth, ui.show_average_depth->isChecked());
s.endGroup(); s.endGroup();
@ -364,6 +366,7 @@ void PreferencesDialog::loadSettings()
GET_INT("gflow", gflow); GET_INT("gflow", gflow);
GET_INT("gfhigh", gfhigh); GET_INT("gfhigh", gfhigh);
GET_BOOL("gf_low_at_maxdepth", gf_low_at_maxdepth); GET_BOOL("gf_low_at_maxdepth", gf_low_at_maxdepth);
GET_BOOL("show_ccr_setpoint",show_ccr_setpoint);
GET_BOOL("zoomed_plot", zoomed_plot); GET_BOOL("zoomed_plot", zoomed_plot);
set_gf(prefs.gflow, prefs.gfhigh, prefs.gf_low_at_maxdepth); set_gf(prefs.gflow, prefs.gfhigh, prefs.gf_low_at_maxdepth);
GET_BOOL("show_sac", show_sac); GET_BOOL("show_sac", show_sac);

View file

@ -789,6 +789,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="show_ccr_setpoint">
<property name="text">
<string>CCR: Show setpoints when viewing pO₂</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

@ -52,6 +52,8 @@ QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
return item.pressures.he; return item.pressures.he;
case PO2: case PO2:
return item.pressures.o2; return item.pressures.o2;
case O2SETPOINT:
return item.o2setpoint.mbar / 1000.0;
case HEARTBEAT: case HEARTBEAT:
return item.heartbeat; return item.heartbeat;
case AMBPRESSURE: case AMBPRESSURE:
@ -127,6 +129,8 @@ QVariant DivePlotDataModel::headerData(int section, Qt::Orientation orientation,
return tr("pHe"); return tr("pHe");
case PO2: case PO2:
return tr("pO₂"); return tr("pO₂");
case O2SETPOINT:
return tr("Setpoint");
case AMBPRESSURE: case AMBPRESSURE:
return tr("Ambient pressure"); return tr("Ambient pressure");
case HEARTBEAT: case HEARTBEAT:

View file

@ -59,6 +59,7 @@ public:
PN2, PN2,
PHE, PHE,
PO2, PO2,
O2SETPOINT,
HEARTBEAT, HEARTBEAT,
AMBPRESSURE, AMBPRESSURE,
GFLINE, GFLINE,

View file

@ -93,6 +93,7 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent),
pn2GasItem(new PartialPressureGasItem()), pn2GasItem(new PartialPressureGasItem()),
pheGasItem(new PartialPressureGasItem()), pheGasItem(new PartialPressureGasItem()),
po2GasItem(new PartialPressureGasItem()), po2GasItem(new PartialPressureGasItem()),
o2SetpointGasItem(new PartialPressureGasItem()),
heartBeatAxis(new DiveCartesianAxis()), heartBeatAxis(new DiveCartesianAxis()),
heartBeatItem(new DiveHeartrateItem()), heartBeatItem(new DiveHeartrateItem()),
percentageAxis(new DiveCartesianAxis()), percentageAxis(new DiveCartesianAxis()),
@ -162,6 +163,7 @@ ProfileWidget2::~ProfileWidget2()
delete pn2GasItem; delete pn2GasItem;
delete pheGasItem; delete pheGasItem;
delete po2GasItem; delete po2GasItem;
delete o2SetpointGasItem;
delete heartBeatAxis; delete heartBeatAxis;
delete heartBeatItem; delete heartBeatItem;
delete percentageAxis; delete percentageAxis;
@ -201,6 +203,7 @@ void ProfileWidget2::addItemsToScene()
scene()->addItem(pn2GasItem); scene()->addItem(pn2GasItem);
scene()->addItem(pheGasItem); scene()->addItem(pheGasItem);
scene()->addItem(po2GasItem); scene()->addItem(po2GasItem);
scene()->addItem(o2SetpointGasItem);
scene()->addItem(percentageAxis); scene()->addItem(percentageAxis);
scene()->addItem(heartBeatAxis); scene()->addItem(heartBeatAxis);
scene()->addItem(heartBeatItem); scene()->addItem(heartBeatItem);
@ -313,6 +316,7 @@ void ProfileWidget2::setupItemOnScene()
CREATE_PP_GAS(pn2GasItem, PN2, PN2, PN2_ALERT, &prefs.pp_graphs.pn2_threshold, "pn2graph"); CREATE_PP_GAS(pn2GasItem, PN2, PN2, PN2_ALERT, &prefs.pp_graphs.pn2_threshold, "pn2graph");
CREATE_PP_GAS(pheGasItem, PHE, PHE, PHE_ALERT, &prefs.pp_graphs.phe_threshold, "phegraph"); CREATE_PP_GAS(pheGasItem, PHE, PHE, PHE_ALERT, &prefs.pp_graphs.phe_threshold, "phegraph");
CREATE_PP_GAS(po2GasItem, PO2, PO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph"); CREATE_PP_GAS(po2GasItem, PO2, PO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph");
CREATE_PP_GAS(o2SetpointGasItem, O2SETPOINT, PO2_ALERT, PO2_ALERT, &prefs.pp_graphs.po2_threshold, "po2graph");
#undef CREATE_PP_GAS #undef CREATE_PP_GAS
temperatureAxis->setTextVisible(false); temperatureAxis->setTextVisible(false);
@ -527,6 +531,11 @@ void ProfileWidget2::plotDive(struct dive *d, bool force)
currentdc = fake_dc(currentdc); currentdc = fake_dc(currentdc);
} }
if ((current_dc->dctype == CCR) && (prefs.show_ccr_setpoint))
o2SetpointGasItem->setVisible(true);
else
o2SetpointGasItem->setVisible(false);
/* This struct holds all the data that's about to be plotted. /* This struct holds all the data that's about to be plotted.
* I'm not sure this is the best approach ( but since we are * I'm not sure this is the best approach ( but since we are
* interpolating some points of the Dive, maybe it is... ) * interpolating some points of the Dive, maybe it is... )
@ -883,6 +892,7 @@ void ProfileWidget2::setEmptyState()
tankItem->setVisible(false); tankItem->setVisible(false);
pn2GasItem->setVisible(false); pn2GasItem->setVisible(false);
po2GasItem->setVisible(false); po2GasItem->setVisible(false);
o2SetpointGasItem->setVisible(false);
pheGasItem->setVisible(false); pheGasItem->setVisible(false);
ambPressureItem->setVisible(false); ambPressureItem->setVisible(false);
gflineItem->setVisible(false); gflineItem->setVisible(false);
@ -981,6 +991,7 @@ void ProfileWidget2::setProfileState()
} }
pn2GasItem->setVisible(prefs.pp_graphs.pn2); pn2GasItem->setVisible(prefs.pp_graphs.pn2);
po2GasItem->setVisible(prefs.pp_graphs.po2); po2GasItem->setVisible(prefs.pp_graphs.po2);
o2SetpointGasItem->setVisible(true);
pheGasItem->setVisible(prefs.pp_graphs.phe); pheGasItem->setVisible(prefs.pp_graphs.phe);
timeAxis->setPos(itemPos.time.pos.on); timeAxis->setPos(itemPos.time.pos.on);

View file

@ -174,6 +174,7 @@ private:
PartialPressureGasItem *pn2GasItem; PartialPressureGasItem *pn2GasItem;
PartialPressureGasItem *pheGasItem; PartialPressureGasItem *pheGasItem;
PartialPressureGasItem *po2GasItem; PartialPressureGasItem *po2GasItem;
PartialPressureGasItem *o2SetpointGasItem;
DiveCartesianAxis *heartBeatAxis; DiveCartesianAxis *heartBeatAxis;
DiveHeartrateItem *heartBeatItem; DiveHeartrateItem *heartBeatItem;
DiveCartesianAxis *percentageAxis; DiveCartesianAxis *percentageAxis;

View file

@ -29,6 +29,7 @@ struct preferences default_prefs = {
.gfhigh = 75, .gfhigh = 75,
.animation_speed = 500, .animation_speed = 500,
.gf_low_at_maxdepth = false, .gf_low_at_maxdepth = false,
.show_ccr_setpoint = false,
.font_size = -1, .font_size = -1,
.display_invalid_dives = false, .display_invalid_dives = false,
.show_sac = false, .show_sac = false,