diff options
author | Willem Ferguson <willemferguson@zoology.up.ac.za> | 2014-08-24 20:48:22 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2014-08-25 13:53:51 -0700 |
commit | 7575eb44df7541e4a2ad1f073c4f1b8e139c3cfd (patch) | |
tree | d1b9509e2fa63b9873d69d763feb661b82aa5685 /profile.c | |
parent | 214bd0ed6e16933560bbea9fba3d151ad9be8d0b (diff) | |
download | subsurface-7575eb44df7541e4a2ad1f073c4f1b8e139c3cfd.tar.gz |
CCR code: Split profile.c into two files, with gas caluclations separate.
This patch implements a separation of the code for gas pressure
calculations from the rest of the code in profile.c. The latter
file is now split into: profile.c and gaspressures.c. The
details of the transferred functions is given at the top of
gaspressures.c. The following chnages were made:
1) dive.h: The function types of calculate_depth_to_mbar
and depth_to_mbar were made non-static in order to make them
available within gaspressures.c.
2) profile.c: Prototypes for the functions in gaspressures.c
were inserted at the top of profile. Ten functions were
transferred from profile.c to gaspressures.c
3) gaspressures.c as well as a short header, gaspressures.h
were created.
For the gas pressure calculations for CCR dives, gaspressures.c
forms the immediate basis for further code development.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'profile.c')
-rw-r--r-- | profile.c | 347 |
1 files changed, 6 insertions, 341 deletions
@@ -10,6 +10,7 @@ #include "divelist.h" #include "profile.h" +#include "gaspressures.h" #include "deco.h" #include "libdivecomputer/parser.h" #include "libdivecomputer/version.h" @@ -18,9 +19,13 @@ int selected_dive = -1; /* careful: 0 is a valid value */ unsigned int dc_number = 0; - static struct plot_data *last_pi_entry_new = NULL; +void fill_missing_segment_pressures(pr_track_t*); +struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t*, struct plot_info*, int); +void fill_missing_tank_pressures(struct dive*, struct plot_info*, pr_track_t**); +void populate_pressure_information(struct dive*, struct divecomputer*, struct plot_info*); + #ifdef DEBUG_PI /* debugging tool - not normally used */ static void dump_pi(struct plot_info *pi) @@ -284,295 +289,6 @@ struct plot_info *analyze_plot_info(struct plot_info *pi) return pi; } -/* - * simple structure to track the beginning and end tank pressure as - * well as the integral of depth over time spent while we have no - * pressure reading from the tank */ -typedef struct pr_track_struct pr_track_t; -struct pr_track_struct { - int start; - int end; - int t_start; - int t_end; - int pressure_time; - pr_track_t *next; -}; - -static pr_track_t *pr_track_alloc(int start, int t_start) -{ - pr_track_t *pt = malloc(sizeof(pr_track_t)); - pt->start = start; - pt->end = 0; - pt->t_start = pt->t_end = t_start; - pt->pressure_time = 0; - pt->next = NULL; - return pt; -} - -/* poor man's linked list */ -static pr_track_t *list_last(pr_track_t *list) -{ - pr_track_t *tail = list; - if (!tail) - return NULL; - while (tail->next) { - tail = tail->next; - } - return tail; -} - -static pr_track_t *list_add(pr_track_t *list, pr_track_t *element) -{ - pr_track_t *tail = list_last(list); - if (!tail) - return element; - tail->next = element; - return list; -} - -static void list_free(pr_track_t *list) -{ - if (!list) - return; - list_free(list->next); - free(list); -} - -#ifdef DEBUG_PR_TRACK -static void dump_pr_track(pr_track_t **track_pr) -{ - int cyl; - pr_track_t *list; - - for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { - list = track_pr[cyl]; - while (list) { - printf("cyl%d: start %d end %d t_start %d t_end %d pt %d\n", cyl, - list->start, list->end, list->t_start, list->t_end, list->pressure_time); - list = list->next; - } - } -} -#endif - -typedef struct pr_interpolate_struct pr_interpolate_t; -struct pr_interpolate_struct { - int start; - int end; - int pressure_time; - int acc_pressure_time; -}; - -#ifdef DEBUG_PR_INTERPOLATE -static void dump_pr_interpolate(int i, pr_interpolate_t interpolate_pr) -{ - printf("Interpolate for entry %d: start %d - end %d - pt %d - acc_pt %d\n", i, - interpolate_pr.start, interpolate_pr.end, interpolate_pr.pressure_time, interpolate_pr.acc_pressure_time); -} -#endif - -/* - * This looks at the pressures for one cylinder, and - * calculates any missing beginning/end pressures for - * each segment by taking the over-all SAC-rate into - * account for that cylinder. - * - * NOTE! Many segments have full pressure information - * (both beginning and ending pressure). But if we have - * switched away from a cylinder, we will have the - * beginning pressure for the first segment with a - * missing end pressure. We may then have one or more - * segments without beginning or end pressures, until - * we finally have a segment with an end pressure. - * - * We want to spread out the pressure over these missing - * segments according to how big of a time_pressure area - * they have. - */ -static void fill_missing_segment_pressures(pr_track_t *list) -{ - while (list) { - int start = list->start, end; - pr_track_t *tmp = list; - int pt_sum = 0, pt = 0; - - for (;;) { - pt_sum += tmp->pressure_time; - end = tmp->end; - if (end) - break; - end = start; - if (!tmp->next) - break; - tmp = tmp->next; - } - - if (!start) - start = end; - - /* - * Now 'start' and 'end' contain the pressure values - * for the set of segments described by 'list'..'tmp'. - * pt_sum is the sum of all the pressure-times of the - * segments. - * - * Now dole out the pressures relative to pressure-time. - */ - 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; - } - - /* Ok, we've done that set of segments */ - list = list->next; - } -} - -/* - * What's the pressure-time between two plot data entries? - * We're calculating the integral of pressure over time by - * adding these up. - * - * The units won't matter as long as everybody agrees about - * them, since they'll cancel out - we use this to calculate - * a constant SAC-rate-equivalent, but we only use it to - * scale pressures, so it ends up being a unitless scaling - * factor. - */ -static inline int pressure_time(struct dive *dive, struct divecomputer *dc, struct plot_data *a, struct plot_data *b) -{ - int time = b->sec - a->sec; - int depth = (a->depth + b->depth) / 2; - - if (depth <= SURFACE_THRESHOLD) - return 0; - - return depth_to_mbar(depth, dive) * time; -} - -static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment, struct plot_info *pi, int cur) -{ - struct pr_interpolate_struct interpolate; - int i; - struct plot_data *entry; - - interpolate.start = segment->start; - interpolate.end = segment->end; - interpolate.acc_pressure_time = 0; - interpolate.pressure_time = 0; - - for (i = 0; i < pi->nr; i++) { - entry = pi->entry + i; - if (entry->sec < segment->t_start) - continue; - if (entry->sec >= segment->t_end) { - interpolate.pressure_time += entry->pressure_time; - break; - } - if (entry->sec == segment->t_start) { - interpolate.acc_pressure_time = 0; - interpolate.pressure_time = 0; - if (SENSOR_PRESSURE(entry)) - interpolate.start = SENSOR_PRESSURE(entry); - continue; - } - if (i < cur) { - if (SENSOR_PRESSURE(entry)) { - interpolate.start = SENSOR_PRESSURE(entry); - interpolate.acc_pressure_time = 0; - interpolate.pressure_time = 0; - } else { - interpolate.acc_pressure_time += entry->pressure_time; - interpolate.pressure_time += entry->pressure_time; - } - continue; - } - if (i == cur) { - interpolate.acc_pressure_time += entry->pressure_time; - interpolate.pressure_time += entry->pressure_time; - continue; - } - interpolate.pressure_time += entry->pressure_time; - if (SENSOR_PRESSURE(entry)) { - interpolate.end = SENSOR_PRESSURE(entry); - break; - } - } - return interpolate; -} - -static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr) -{ - int cyl, i; - struct plot_data *entry; - int cur_pr[MAX_CYLINDERS]; - -#ifdef DEBUG_PR_TRACK - /* another great debugging tool */ - dump_pr_track(track_pr); -#endif - for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { - if (!track_pr[cyl]) { - /* no segment where this cylinder is used */ - cur_pr[cyl] = -1; - continue; - } - fill_missing_segment_pressures(track_pr[cyl]); - cur_pr[cyl] = track_pr[cyl]->start; - } - - /* The first two are "fillers", but in case we don't have a sample - * at time 0 we need to process the second of them here */ - for (i = 1; i < pi->nr; i++) { - double magic; - pr_track_t *segment; - pr_interpolate_t interpolate; - - entry = pi->entry + i; - cyl = entry->cylinderindex; - - if (SENSOR_PRESSURE(entry)) { - cur_pr[cyl] = SENSOR_PRESSURE(entry); - continue; - } - - /* Find the right pressure segment for this entry.. */ - segment = track_pr[cyl]; - while (segment && segment->t_end < entry->sec) - segment = segment->next; - - /* No (or empty) segment? Just use our current pressure */ - if (!segment || !segment->pressure_time) { - SENSOR_PRESSURE(entry) = cur_pr[cyl]; - continue; - } - - interpolate = get_pr_interpolate_data(segment, pi, i); -#ifdef DEBUG_PR_INTERPOLATE - dump_pr_interpolate(i, interpolate); -#endif - /* if this segment has pressure time, calculate a new interpolated pressure */ - if (interpolate.pressure_time) { - /* Overall pressure change over total pressure-time for this segment*/ - magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time; - - /* Use that overall pressure change to update the current pressure */ - cur_pr[cyl] = rint(interpolate.start + magic * interpolate.acc_pressure_time); - } - INTERPOLATED_PRESSURE(entry) = cur_pr[cyl]; - } -} - int get_cylinder_index(struct dive *dive, struct event *ev) { int i; @@ -955,57 +671,6 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc } while ((secondary = secondary->next) != NULL); } -static void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi) -{ - int i, cylinderindex; - pr_track_t *track_pr[MAX_CYLINDERS] = { NULL, }; - pr_track_t *current; - bool missing_pr = false; - - cylinderindex = -1; - current = NULL; - for (i = 0; i < pi->nr; i++) { - struct plot_data *entry = pi->entry + i; - int pressure = SENSOR_PRESSURE(entry); - - /* discrete integration of pressure over time to get the SAC rate equivalent */ - if (current) { - entry->pressure_time = pressure_time(dive, dc, entry - 1, entry); - current->pressure_time += entry->pressure_time; - current->t_end = entry->sec; - } - - /* track the segments per cylinder and their pressure/time integral */ - if (entry->cylinderindex != cylinderindex) { - cylinderindex = entry->cylinderindex; - current = pr_track_alloc(pressure, entry->sec); - track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current); - continue; - } - - if (!pressure) { - missing_pr = 1; - continue; - } - - current->end = pressure; - - /* Was it continuous? */ - if (SENSOR_PRESSURE(entry - 1)) - continue; - - /* transmitter changed its working status */ - current = pr_track_alloc(pressure, entry->sec); - track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current); - } - - if (missing_pr) { - fill_missing_tank_pressures(dive, pi, track_pr); - } - for (i = 0; i < MAX_CYLINDERS; i++) - list_free(track_pr[i]); -} - /* calculate DECO STOP / TTS / NDL */ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry, struct dive *dive, double surface_pressure) { |