From b245282a553e924e2bf0db656f5b3fe3ad6725bc Mon Sep 17 00:00:00 2001
From: "Robert C. Helling" <helling@atdotde.de>
Date: Sun, 9 Nov 2014 14:36:27 +0100
Subject: [PATCH 1/2] Some gas handling improvements

Add a time linear gas interpolation strategy. Some minor changes.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
---
 dive.c         |  4 ++--
 dive.h         |  2 +-
 file.c         |  4 ++--
 gaspressures.c | 52 ++++++++++++++++++++++++++++++++--------------------
 gaspressures.h |  1 +
 5 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/dive.c b/dive.c
index ccd071c..1cb8d7d 100644
--- a/dive.c
+++ b/dive.c
@@ -1054,8 +1054,8 @@ unsigned int dc_airtemp(struct divecomputer *dc)
 
 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_use(dive, oxygen);
-	dive->diluent_cylinder_index = get_cylinder_use(dive, diluent);
+	dive->oxygen_cylinder_index = get_cylinder_use(dive, OXYGEN);
+	dive->diluent_cylinder_index = get_cylinder_use(dive, DILUENT);
 }
 
 static void fixup_airtemp(struct dive *dive)
diff --git a/dive.h b/dive.h
index e3c4c74..a466d2d 100644
--- a/dive.h
+++ b/dive.h
@@ -48,7 +48,7 @@ extern "C" {
 #endif
 
 enum dive_comp_type {OC, CCR, PSCR};	// Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
-enum cylinderuse {oxygen, diluent, bailout}; // The different uses for cylinders in CCR dives
+enum cylinderuse {OC_GAS, DILUENT, OXYGEN}; // The different uses for cylinders
 
 struct gasmix {
 	fraction_t o2;
diff --git a/file.c b/file.c
index fa684dc..252f5de 100644
--- a/file.c
+++ b/file.c
@@ -475,14 +475,14 @@ int parse_txt_file(const char *filename, const char *csv)
 		dive->dc.dctype = CCR;
 		dive->dc.no_o2sensors = 2;
 
-		dive->cylinder[cur_cylinder_index].cylinder_use = oxygen;
+		dive->cylinder[cur_cylinder_index].cylinder_use = OXYGEN;
 		dive->cylinder[cur_cylinder_index].type.size.mliter = 3000;
 		dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000;
 		dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6");
 		dive->cylinder[cur_cylinder_index].gasmix.o2.permille = 1000;
 		cur_cylinder_index++;
 
-		dive->cylinder[cur_cylinder_index].cylinder_use = diluent;
+		dive->cylinder[cur_cylinder_index].cylinder_use = DILUENT;
 		dive->cylinder[cur_cylinder_index].type.size.mliter = 3000;
 		dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000;
 		dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6");
diff --git a/gaspressures.c b/gaspressures.c
index 3155a90..fbb52a1 100644
--- a/gaspressures.c
+++ b/gaspressures.c
@@ -97,7 +97,7 @@ static void dump_pr_track(pr_track_t **track_pr)
  * segments according to how big of a time_pressure area
  * they have.
  */
-static void fill_missing_segment_pressures(pr_track_t *list)
+static void fill_missing_segment_pressures(pr_track_t *list, enum interpolation_strategy strategy)
 {
 	while (list) {
 		int start = list->start, end;
@@ -128,17 +128,29 @@ static void fill_missing_segment_pressures(pr_track_t *list)
 		 */
 		list->start = start;
 		tmp->end = end;
-		for (;;) {
-			int pressure;
-			pt += list->pressure_time;
-			pressure = start;
-			if (pt_sum)
-				pressure -= (start - end) * (double)pt / pt_sum;
-			list->end = pressure;
-			if (list == tmp)
-				break;
-			list = list->next;
-			list->start = pressure;
+		switch (strategy) {
+		case SAC:
+			for (;;) {
+				int pressure;
+				pt += list->pressure_time;
+				pressure = start;
+				if (pt_sum)
+					pressure -= (start - end) * (double)pt / pt_sum;
+				list->end = pressure;
+				if (list == tmp)
+					break;
+				list = list->next;
+				list->start = pressure;
+			}
+			break;
+		case TIME:
+			if (list->t_end && (tmp->t_start - tmp->t_end))
+				list->end = start - (start - end) * (list->t_end - tmp->t_end) / (tmp->t_start - tmp->t_end);
+			else
+				list->end = start;
+			break;
+		case CONSTANT:
+			list->end = start;
 		}
 
 		/* Ok, we've done that set of segments */
@@ -155,12 +167,11 @@ void dump_pr_interpolate(int i, pr_interpolate_t interpolate_pr)
 #endif
 
 
-static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment, struct plot_info *pi, int cur, int diluent_flag)
+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
 	struct pr_interpolate_struct interpolate;
 	int i;
 	struct plot_data *entry;
-	int pressure;
 
 	interpolate.start = segment->start;
 	interpolate.end = segment->end;
@@ -169,10 +180,6 @@ static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment,
 
 	for (i = 0; i < pi->nr; i++) {
 		entry = pi->entry + i;
-		if (diluent_flag)
-			pressure = DILUENT_PRESSURE(entry);
-		else
-			pressure = SENSOR_PRESSURE(entry);
 
 		if (entry->sec < segment->t_start)
 			continue;
@@ -219,12 +226,17 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
 	int cur_pr[MAX_CYLINDERS]; // cur_pr[MAX_CYLINDERS] is the CCR diluent cylinder
 
 	for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
+		enum interpolation_strategy strategy;
 		if (!track_pr[cyl]) {
 			/* no segment where this cylinder is used */
 			cur_pr[cyl] = -1;
 			continue;
 		}
-		fill_missing_segment_pressures(track_pr[cyl]); // Interpolate the missing tank pressure values ..
+		if (dive->cylinder[cyl].cylinder_use == OC_GAS)
+			strategy = SAC;
+		else
+			strategy = TIME;
+		fill_missing_segment_pressures(track_pr[cyl], strategy); // Interpolate the missing tank pressure values ..
 		cur_pr[cyl] = track_pr[cyl]->start;	       // in the pr_track_t lists of structures
 	}						       // and keep the starting pressure for each cylinder.
 
@@ -279,7 +291,7 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
 			continue;			   // and skip to next point.
 		}
 		// If there is a valid segment but no tank pressure ..
-		interpolate = get_pr_interpolate_data(segment, pi, i, diluent_flag); // Set up an interpolation structure
+		interpolate = get_pr_interpolate_data(segment, pi, i, pressure); // Set up an interpolation structure
 
 		/* if this segment has pressure_time, then calculate a new interpolated pressure */
 		if (interpolate.pressure_time) {
diff --git a/gaspressures.h b/gaspressures.h
index 71fee34..420c117 100644
--- a/gaspressures.h
+++ b/gaspressures.h
@@ -27,6 +27,7 @@ struct pr_interpolate_struct {
 	int acc_pressure_time;
 };
 
+enum interpolation_strategy {SAC, TIME, CONSTANT};
 
 #ifdef __cplusplus
 }
-- 
1.8.5.2 (Apple Git-48)

