Mercurial > public > hwos_code
comparison src/p2_deco.c @ 631:185ba2f91f59
3.09 beta 1 release
author | heinrichsweikamp |
---|---|
date | Fri, 28 Feb 2020 15:45:07 +0100 |
parents | 237931377539 |
children | 4050675965ea |
comparison
equal
deleted
inserted
replaced
630:4cd81bdbf15c | 631:185ba2f91f59 |
---|---|
1 // *************************************************************************** | 1 // *************************************************************************** |
2 // p2_deco.c combined next generation V3.06.1 | 2 // p2_deco.c combined next generation V3.08.8 |
3 // | 3 // |
4 // Created on: 12.05.2009 | 4 // Created on: 12.05.2009 |
5 // Author: heinrichs weikamp, contributions by Ralph Lembcke and others | 5 // Author: heinrichs weikamp, contributions by Ralph Lembcke and others |
6 // | 6 // |
7 // *************************************************************************** | 7 // *************************************************************************** |
33 // 03/13/25 v101: CNS_fraction_real calculation | 33 // 03/13/25 v101: CNS_fraction_real calculation |
34 // 03/13/26 v101: optimization of tissue calc routines | 34 // 03/13/26 v101: optimization of tissue calc routines |
35 // 07/xx/2008 v102a: debug of bottom time routine | 35 // 07/xx/2008 v102a: debug of bottom time routine |
36 // 09/xx/2008 v102d: Gradient Factor Model implementation | 36 // 09/xx/2008 v102d: Gradient Factor Model implementation |
37 // 10/10/2008 v104: renamed to build v103 for v118 stable | 37 // 10/10/2008 v104: renamed to build v103 for v118 stable |
38 // 10/14/2008 v104: integration of char_I_depth_last_deco for Gradient Model | 38 // 10/14/2008 v104: integration of char_I_last_stop_depth for Gradient Model |
39 // 03/31/2009 v107: integration of FONT Incon24 | 39 // 03/31/2009 v107: integration of FONT Incon24 |
40 // 05/23/2010 v109: 5 gas changes & 1 min timer | 40 // 05/23/2010 v109: 5 gas changes & 1 min timer |
41 // 07/13/2010 v110: cns vault added | 41 // 07/13/2010 v110: cns vault added |
42 // 12/25/2010 v110: split in three files (deco.c, main.c, definitions.h) | 42 // 12/25/2010 v110: split in three files (deco.c, main.c, definitions.h) |
43 // 2011/01/20: [jDG] Create a common file included in ASM and C code. | 43 // 2011/01/20: [jDG] Create a common file included in ASM and C code. |
45 // 2011/01/25: [jDG] Fusion deco array for both models. | 45 // 2011/01/25: [jDG] Fusion deco array for both models. |
46 // 2011/01/25: [jDG] Use CF(54) to reverse deco order. | 46 // 2011/01/25: [jDG] Use CF(54) to reverse deco order. |
47 // 2011/02/11: [jDG] Reworked gradient-factor implementation. | 47 // 2011/02/11: [jDG] Reworked gradient-factor implementation. |
48 // 2011/02/15: [jDG] Fixed inconsistencies introduced by gas switch delays. | 48 // 2011/02/15: [jDG] Fixed inconsistencies introduced by gas switch delays. |
49 // 2011/03/21: [jDG] Added gas consumption (CF56 & CF57) evaluation for OCR mode. | 49 // 2011/03/21: [jDG] Added gas consumption (CF56 & CF57) evaluation for OCR mode. |
50 // 2011/04/15: [jDG] Store GF_low_depth in 32 bits (w/o rounding), for a better stability. | 50 // 2011/04/15: [jDG] Store GF_depth in 32 bits (w/o rounding), for a better stability. |
51 // 2011/04/25: [jDG] Added 1mn mode for CNS calculation, to allow it for deco planning. | 51 // 2011/04/25: [jDG] Added 1mn mode for CNS calculation, to allow it for deco planning. |
52 // 2011/04/27: [jDG] Fixed char_O_gradient_factor calculation when model uses gradient-factor. | 52 // 2011/04/27: [jDG] Fixed char_O_gradient_factor calculation when model uses gradient-factor. |
53 // 2011/05/02: [jDG] Added "Future TTS" function (CF58). | 53 // 2011/05/02: [jDG] Added "Future TTS" function (CF58). |
54 // 2011/05/17: [jDG] Various cleanups. | 54 // 2011/05/17: [jDG] Various cleanups. |
55 // 2011/08/08: [jDG] Computes CNS during deco planning ascent. | 55 // 2011/08/08: [jDG] Computes CNS during deco planning ascent. |
57 // 2011/12/17: [mH] Remove of the useless debug stuff | 57 // 2011/12/17: [mH] Remove of the useless debug stuff |
58 // 2012/02/24: [jDG] Remove missed stop bug. | 58 // 2012/02/24: [jDG] Remove missed stop bug. |
59 // 2012/02/25: [jDG] Looking for a more stable LOW grad factor reference. | 59 // 2012/02/25: [jDG] Looking for a more stable LOW grad factor reference. |
60 // 2012/09/10: [mH] Fill char_O_deco_time_for_log for logbook write | 60 // 2012/09/10: [mH] Fill char_O_deco_time_for_log for logbook write |
61 // 2012/10/05: [jDG] Better calc_gas_needs_ascent accuracy (average depth, switch between stop). | 61 // 2012/10/05: [jDG] Better calc_gas_needs_ascent accuracy (average depth, switch between stop). |
62 // 2013/03/05: [jDG] Should vault GF_low_depth too. | 62 // 2013/03/05: [jDG] Should vault GF_depth too. |
63 // 2013/03/05: [jDG] Wrobell remark: ascent_to_first_stop works better with finer steps (2sec). | 63 // 2013/03/05: [jDG] Wrobell remark: ascent_to_first_stop works better with finer steps (2sec). |
64 // 2013/05/08: [jDG] A. Salm remark: NOAA tables for CNS are in ATA, not bar. | 64 // 2013/05/08: [jDG] A. Salm remark: NOAA tables for CNS are in ATA, not bar. |
65 // 2013/12/21: [jDG] Fix CNS calculation in deco plan w/o marked gas switch | 65 // 2013/12/21: [jDG] Fix CNS calculation in deco plan w/o marked gas switch |
66 // 2014/06/16: [jDG] Fix Helium diluent. Fix volumes with many travel mix. | 66 // 2014/06/16: [jDG] Fix Helium diluent. Fix volumes with many travel mix. |
67 // 2014/06/29: [mH] Compute int_O_ceiling | 67 // 2014/06/29: [mH] Compute int_O_ceiling |
121 // 0.735 bar is a typical cabin pressure for nowadays commercial jet aircrafts | 121 // 0.735 bar is a typical cabin pressure for nowadays commercial jet aircrafts |
122 // ----- | 122 // ----- |
123 // 0.135 bar safety margin | 123 // 0.135 bar safety margin |
124 | 124 |
125 // constants and factors | 125 // constants and factors |
126 #define ppWater 0.06270 // water vapor partial pressure in the lungs | 126 #define ppWater 0.06270 // water vapor partial pressure in the lungs |
127 #define METER_TO_BAR 0.09985 // conversion factor | 127 #define METER_TO_BAR 0.09807 // conversion factor (1 m water column = 0.09807 bar) |
128 #define BAR_TO_METER 10.0150 // conversion factor (1.0/METER_TO_BAR) | 128 #define BAR_TO_METER 10.19716 // conversion factor (1 bar = 10.19716 m ) |
129 #define SURFACE_DESAT_FACTOR 0.70420 // surface desaturation safety factor | 129 #define SURFACE_DESAT_FACTOR 0.70420 // surface desaturation safety factor |
130 #define HYST 1.0E-06 // threshold for tissue graphics on-gassing / off-gassing visualization | 130 #define HYST 1.0E-06 // threshold for tissue graphics on-gassing / off-gassing visualization |
131 | 131 |
132 // thresholds | 132 // thresholds |
133 #define CNS_LIMIT_WARNING 100 // threshold for CNS warning | 133 #define CNS_LIMIT_WARNING 100 // threshold for CNS warning |
134 #define CNS_LIMIT_ATTENTION 70 // threshold for CNS attention | 134 #define CNS_LIMIT_ATTENTION 70 // threshold for CNS attention |
135 #define PRESSURE_LIMIT_WARNING 200 // threshold for pressure reading warning : 20.0 bar | 135 #define PRESSURE_LIMIT_WARNING 200 // threshold for pressure reading warning : 20.0 bar |
136 #define PRESSURE_LIMIT_ATTENTION 500 // threshold for pressure reading attention: 50.0 bar | 136 #define PRESSURE_LIMIT_ATTENTION 500 // threshold for pressure reading attention: 50.0 bar |
137 #define GAS_NEEDS_LIMIT_ATTENTION 0.70 // threshold for gas needs attention [1.00 = 100%] | 137 #define GAS_NEEDS_ATTENTION 0.7 // threshold for gas needs attention [1 = 100%] |
138 #define O2_CONSUMPTION_LIMIT_ATTENTION 20 // threshold for O2 "SAC" attention: 2.0 l/min | 138 #define O2_CONSUMPTION_LIMIT_ATTENTION 20 // threshold for O2 "SAC" attention: 2.0 l/min |
139 #define ppO2_GAP_TO_SETPOINT 10 // gap between setpoint and max. ppO2 of the pure diluent [cbar] | 139 #define ppO2_GAP_TO_SETPOINT 10 // gap between setpoint and max. ppO2 of the pure diluent [cbar] |
140 #define ppO2_MARGIN_ON_MAX 3 // [cbar] margin on ppO2 max to compensate for surface pressures > 1.000 mbar | 140 #define ppO2_MARGIN_ON_MAX 3 // [cbar] margin on ppO2 max to compensate for surface pressures > 1.000 mbar |
141 #define STOP_CHAINING_LIMIT 5 // max. number of chained stop table entries before deco calculation is aborted | 141 #define STOP_CHAINING_LIMIT 3 // max. number of chained stop table entries before deco calculation is aborted |
142 | 142 |
143 | 143 |
144 // deco engine states and modes - (char_O_)main_status: controls current tissue and deco status calculation (as-is situation) | 144 // deco engine states and modes - (char_O_)main_status: controls current tissue and deco status calculation (as-is situation) |
145 #define CALC_VOLUME 0x01 // =1: calculate gas needs | 145 #define CALC_VOLUME 0x01 // =1: calculate gas needs |
146 #define CALCULATE_BOTTOM 0x02 // =1: calculate gas needs in deco calculator mode, =0: in dive mode | 146 #define CALCULATE_BOTTOM 0x02 // =1: calculate gas needs in deco calculator mode, =0: in dive mode |
147 #define CAVE_MODE 0x04 // =1: calculate ascent and gas needs using backtracking data | 147 #define CAVE_MODE 0x04 // =1: calculate return path and gas needs using backtracking data |
148 #define USE_Z_FACTOR 0x08 // =1: calculate with Z factor when converting gas volumes <-> pressures | 148 #define GAS_CONTINGENCY 0x08 // =1: use a second best gas if best gas is all used up |
149 | |
150 #define TR_FUNCTIONS 0x10 // =1: calculate TR functions (pressure reading) processing | 149 #define TR_FUNCTIONS 0x10 // =1: calculate TR functions (pressure reading) processing |
151 #define EXTENDED_STOPS 0x20 // =1: allow placement of gas switches below the depth of the 1st stop | 150 #define EXTENDED_STOPS 0x20 // =1: allow placement of gas switches below the depth of the 1st stop |
152 | 151 |
153 #define MODE_MASK 0xC0 // mask for real tissues mode selection | 152 #define MODE_MASK 0xC0 // mask for real tissues mode selection |
154 #define MODE_LOOP 0x40 // =1: CCR (MODE_PSCR needs to be cleared) or pSCR mode | 153 #define MODE_LOOP 0x40 // =1: CCR (MODE_PSCR needs to be cleared) or pSCR mode |
164 #define COMPLETED_NORM 0x01 // output: calculation of a normal deco plan has completed | 163 #define COMPLETED_NORM 0x01 // output: calculation of a normal deco plan has completed |
165 #define START_ALT 0x02 // input: start calculation of an alternative deco plan | 164 #define START_ALT 0x02 // input: start calculation of an alternative deco plan |
166 #define CALC_ALT 0x02 // internal: calculating an alternative deco plan | 165 #define CALC_ALT 0x02 // internal: calculating an alternative deco plan |
167 #define COMPLETED_ALT 0x02 // output: calculation of an alternative deco plan has completed | 166 #define COMPLETED_ALT 0x02 // output: calculation of an alternative deco plan has completed |
168 #define INITIALIZE 0x04 // input: initialize deco engine | 167 #define INITIALIZE 0x04 // input: initialize deco engine |
169 #define INITIALIZE_START_NORM 0x05 // input: initialize deco engine and start calculation of a normal deco plan | 168 #define INITIALIZE_START_NORM 0x05 // input: initialize deco engine and start calculation of a normal deco plan |
170 #define INITIALIZE_START_ALT 0x06 // input: initialize deco engine and start calculation of an alternative deco plan | 169 #define INITIALIZE_START_ALT 0x06 // input: initialize deco engine and start calculation of an alternative deco plan |
171 #define DECO_CALCULATOR_MODE 0x08 // input: deco engine is run from deco calculator | 170 #define DECO_CALCULATOR_MODE 0x08 // input: deco engine is run from deco calculator |
172 | 171 |
173 #define BAILOUT_MODE 0x10 // =1: allow gas switches before first deco stop | 172 #define BAILOUT_MODE 0x10 // =1: allow gas switches before first deco stop |
174 #define DELAYED_ASCENT 0x20 // =1: figure in a delayed ascent (fTTS) | 173 #define DELAYED_ASCENT 0x20 // =1: figure in a delayed ascent / delayed turn of the dive (fTTS) |
175 | 174 |
176 // MODE_MASK 0xC0 // mask for simulated tissues mode selection | 175 // MODE_MASK 0xC0 // mask for simulated tissues mode selection |
177 // MODE_LOOP 0x40 // =1: CCR (MODE_PSCR needs to be cleared) or pSCR mode | 176 // MODE_LOOP 0x40 // =1: CCR (MODE_PSCR needs to be cleared) or pSCR mode |
178 // MODE_CCR 0x40 // to be used with == operator in combination with MODE_MASK only! | 177 // MODE_CCR 0x40 // to be used with == operator in combination with MODE_MASK only! |
179 // MODE_PSCR 0x80 // =1: pSCR mode (MODE_LOOP needs to be set, too) | 178 // MODE_PSCR 0x80 // =1: pSCR mode (MODE_LOOP needs to be set, too) |
185 #define DECO_WARNING_MBUBBLES 0x04 // micro bubbles likely to develop now | 184 #define DECO_WARNING_MBUBBLES 0x04 // micro bubbles likely to develop now |
186 #define DECO_WARNING_MBUBBLES_lock 0x08 // ditto, but sometime during the dive | 185 #define DECO_WARNING_MBUBBLES_lock 0x08 // ditto, but sometime during the dive |
187 #define DECO_WARNING_OUTSIDE 0x10 // tissue pressures outside the Buhlmann model now | 186 #define DECO_WARNING_OUTSIDE 0x10 // tissue pressures outside the Buhlmann model now |
188 #define DECO_WARNING_OUTSIDE_lock 0x20 // tissue pressures outside the model sometime during the dive | 187 #define DECO_WARNING_OUTSIDE_lock 0x20 // tissue pressures outside the model sometime during the dive |
189 #define DECO_ATTENTION_OUTSIDE 0x40 // tissue pressures are very close to the Buhlmann limit | 188 #define DECO_ATTENTION_OUTSIDE 0x40 // tissue pressures are very close to the Buhlmann limit |
190 #define DECO_WARNING_INCOMPLETE 0x80 // internal error: deco calculation incomplete | 189 #define DECO_WARNING_INCOMPLETE 0x80 // deco calculation incomplete due to too long compute time |
191 | 190 |
192 // deco engine status (char_O_)deco_info | 191 // deco engine status (char_O_)deco_info |
193 #define DECO_MODE 0x01 // =1: deco ppO2 levels are permitted | 192 #define DECO_MODE 0x01 // =1: deco ppO2 levels are permitted |
194 #define IND_DOUBLE_SWITCH_FLAG 0x02 // =1: switch to other tank advice active | 193 #define IND_DOUBLE_SWITCH_FLAG 0x02 // =1: switch to other tank advice active |
195 // 0x04 // --- unused | 194 #define GAS_NEEDS_fTTS 0x04 // =1: gas needs are calculated in fTTS mode |
196 #define DECO_ZONE 0x08 // =1: fTTS < TTS (not updated when in bailout mode) | 195 #define DECO_ZONE 0x08 // =1: fTTS < TTS (not updated when in bailout mode) |
197 #define DECO_CEILING 0x10 // =1: ceiling depth > 0 | 196 #define DECO_CEILING 0x10 // =1: deco obligation (ceiling > 0) |
198 #define DECO_STOPS 0x20 // =1: deco stops found | 197 #define DECO_STOPS_NORM 0x20 // =1: deco stops found in normal plan |
199 #define GAS_NEEDS_CAVE 0x40 // =1: indicated gas needs are calculated in cave mode | 198 #define DECO_STOPS_ALT 0x40 // =1: deco stops found in alternative plan |
200 // 0x80 // --- unused | 199 #define GAS_NEEDS_CAVE 0x80 // =1: indicated gas needs are calculated in cave mode |
201 | 200 |
202 | 201 |
203 // deco engine control - tissue_increment | 202 // deco engine control - tissue_increment |
204 #define TIME_MASK 0x7F // =0: time increment is 2 seconds, 1..127: time increments is 1..127 minutes | 203 #define TIME_MASK 0x7F // =0: time increment is 2 or 6 seconds, 1..127: time increments is 1..127 minutes |
205 #define TISSUE_SELECTOR 0x80 // =1: calculate on real tissues, =0: calculate on simulated tissues | 204 #define TISSUE_SELECTOR 0x80 // =0: calculate on simulated tissues, 1 : calculate on real tissues |
206 | 205 |
207 | 206 |
208 // deco engine control - next_planning_phase | 207 // deco engine control - next_planning_phase |
209 #define PHASE_00_DONE 0x00 // calculation cycle finished | 208 #define PHASE_00_DONE 0x00 // calculation cycle finished |
210 #define PHASE_10_DIVE_INIT 0x10 // once-per-dive initialization of the deco engine | 209 #define PHASE_10_DIVE_INIT 0x10 // once-per-dive initialization of the deco engine |
211 #define PHASE_20_CYCLIC_INIT 0x20 // once-every-cycle initialization of the deco engine | 210 #define PHASE_20_CYCLIC_INIT 0x20 // once-every-cycle initialization of the deco engine |
212 #define PHASE_30_EXTENDED_BOTTOM_TIME 0x30 // calculate extended bottom time | 211 #define PHASE_30_EXTENDED_BOTTOM_TIME 0x30 // calculate extended bottom time |
213 #define PHASE_40_BOTTOM_GAS_NEED 0x40 // calculate gas needs for bottom segment | 212 #define PHASE_40_BOTTOM_GAS_NEED 0x40 // calculate gas needs for bottom segment |
214 #define PHASE_50_NDL_TIME 0x50 // calculate NDL time | 213 #define PHASE_50_NDL_TIME 0x50 // calculate NDL time |
215 #define PHASE_60_CAVE_RETURN 0x60 // calculate cave mode return | 214 #define PHASE_70_ASCENT_OR_RETURN 0x70 // calculate open water ascent or cave return |
216 #define PHASE_70_OPEN_WATER_ASCENT 0x70 // calculate open water ascent | |
217 #define PHASE_80_RESULTS 0x80 // results - initialization | 215 #define PHASE_80_RESULTS 0x80 // results - initialization |
218 #define PHASE_81_RESULTS_STOPS_TABLE 0x81 // results - publish stops table | 216 #define PHASE_81_RESULTS_STOPS_TABLE 0x81 // results - publish stops table |
219 #define PHASE_82_RESULTS_NDL 0x82 // results - publish data / within NDL | 217 #define PHASE_82_RESULTS_NDL 0x82 // results - publish data / within NDL |
220 #define PHASE_83_RESULTS_DECO 0x83 // results - publish data / in deco | 218 #define PHASE_83_RESULTS_DECO 0x83 // results - publish data / in deco |
221 #define PHASE_84_GAS_NEEDS_PRESSURES 0x84 // results - convert gas needs from volumes to pressures | 219 #define PHASE_84_GAS_NEEDS_PRESSURES 0x84 // results - convert gas needs from volumes to pressures |
220 #define PHASE_85_GAS_NEEDS_CAVE 0x85 // results - tag gas needs as calculated in cave or open water mode | |
222 #define PHASE_90_FINISH 0x90 // finish calculation cycle | 221 #define PHASE_90_FINISH 0x90 // finish calculation cycle |
222 | |
223 | |
224 // gas & diluent - type and availability state | |
225 // 0x01 // | 0: disabled, 1: first, 2: normal/work, 3: deco | |
226 // 0x02 // | | |
227 #define GAS_TYPE_MASK 0x03 // bit mask covering the type enumerator | |
228 #define GAS_AVAIL_LOST 0x04 // =1: gas/diluent lost flag (permanently unavailable) | |
229 #define GAS_AVAIL_STAGED 0x08 // =1: gas/diluent staged flag (temporary unavailable) | |
230 #define GAS_AVAIL_MASK 0x0C // bit mask covering the availability flags | |
231 #define GAS_NEED_ATTENTION 0x10 // =1: gas need >= attention threshold | |
232 #define GAS_NEED_WARNING 0x20 // =1: gas need >= warning threshold | |
233 #define GAS_NEED_MASK 0x30 // bit mask covering the need flags | |
234 #define GAS_NEARLY_USED_UP 0x40 // =1: the gas is nearly used up (= at attention threshold) | |
235 #define GAS_FULLY_USED_UP 0x80 // =1: the gas is fully used up (= at warning threshold) | |
223 | 236 |
224 | 237 |
225 // flags used with integer numbers | 238 // flags used with integer numbers |
226 #define INT_FLAG_INVALID 0x0400 // =1: value not valid | 239 #define INT_FLAG_INVALID 0x0400 // =1: value not valid |
227 #define INT_FLAG_NOT_COMPUTED_YET 0x0800 // =1: value not computed yet | 240 #define INT_FLAG_NOT_COMPUTED_YET 0x0800 // =1: value not computed yet |
262 // needs either calc_hauptroutine_data_input() be called beforehand or | 275 // needs either calc_hauptroutine_data_input() be called beforehand or |
263 // gas_take_current() or gas_find_best()/gas_take_best() and gas_set_ratios(). | 276 // gas_take_current() or gas_find_best()/gas_take_best() and gas_set_ratios(). |
264 static void calc_tissues(void); // Updates the tissues dependent on the partial pressures of N2 and He. | 277 static void calc_tissues(void); // Updates the tissues dependent on the partial pressures of N2 and He. |
265 static void calc_CNS(void); // Updates the CNS value dependent on the partial pressure of the O2. | 278 static void calc_CNS(void); // Updates the CNS value dependent on the partial pressure of the O2. |
266 static void calc_limit(PARAMETER float GF_current); | 279 static void calc_limit(PARAMETER float GF_current); |
267 // Calculates ceiling, current GF (supersaturation) and some more data. | 280 // Calculates ceiling, current supersaturation factor and some more data. |
268 | 281 |
269 // Functions for TR | 282 // Functions for TR |
270 #ifdef _rx_functions | 283 #ifdef _rx_functions |
271 static void calc_TR_functions(void); // Calculates SAC etc. | 284 static void calc_TR_functions(void); // Calculates SAC etc. |
272 #endif | 285 #endif |
273 | 286 |
287 // Functions for Cave Mode | |
288 #ifdef _cave_mode | |
289 static void read_backtrack_data(void); // Gets the data of the next backtracking data set | |
290 #endif | |
291 | |
274 // Functions dedicated to Deco Calculations | 292 // Functions dedicated to Deco Calculations |
275 static void clear_deco_table(void); // Clears the deco stops table, invoked at the start of each calculation cycle. | 293 static void clear_deco_table(void); // Clears the deco stops table, invoked at the start of each calculation cycle. |
276 static void gas_take_current(void); // Sets the first gas used for deco calculation, invoked at start of cycle, too. | 294 static void gas_take_current(void); // Take the actual currently used gas for ascent & deco calculation |
277 static unsigned char gas_find_best(void); // Searches for the best gas available. | 295 static unsigned char gas_find_best(void); // Searches for the best gas available. |
278 static void gas_take_best(void); // Switches to the best gas that has been found found before by gas_find_best(). | 296 static void gas_take_best(void); // Switches to the best gas that has been found found before by gas_find_best(). |
279 static void gas_set_ratios(void); // Sets the gas ratios for use in deco calculation (simulated tissues), | 297 static void gas_set_ratios(void); // Sets the gas ratios for use in deco calculation (simulated tissues), |
280 // needs to be called after each gas change (gas_take_current/_better). | 298 // needs to be called after each gas change (gas_take_current/_better). |
281 static void calc_NDL_time_tissue(void); // Calculates the remaining NDL time for a given tissue. | 299 static void calc_NDL_time_tissue(void); // Calculates the remaining NDL time for a given tissue. |
282 static unsigned char find_next_stop(void); // Finds the next stop when in a deco ascent. | 300 static unsigned char find_next_stop(void); // Finds the next stop when in a deco ascent. |
283 static unsigned char update_deco_table(PARAMETER unsigned char time_increment); | 301 static void update_deco_table(PARAMETER unsigned char time_increment); |
284 // Enters a new stop or extends an existing stop in the deco stops table. | 302 // Enters a new stop or extends an existing stop in the deco stops table. |
285 static void calc_due_by_depth_time_sac(void); // Calculates gas volume required for a given depth, time and usage (SAC rate). | 303 static void calc_required_volume(void); // Calculates gas volume required for a given depth, time and usage (SAC rate). |
286 static void convert_gas_needs_to_press(void); // Converts gas volumes into pressures and sets respective flags. | 304 static void convert_volume_to_pressure(void); // Converts gas volumes into pressures and sets respective flags. |
287 | 305 |
288 // Functions for Results Reporting | 306 // Functions for Results Reporting |
289 static void publish_deco_table(void); // Copies the internal deco stops table to the export interface. | 307 static void publish_deco_table(void); // Copies the internal deco stops table to the export interface. |
290 static void convert_cur_CNS_for_display(void); // Converts the current CNS value from float to integer. | 308 static void convert_cur_CNS_for_display(void); // Converts the current CNS value from float to integer. |
291 static void convert_sim_CNS_for_display(void); // Converts the end-of-dive CNS value from float to integer. | 309 static void convert_sim_CNS_for_display(void); // Converts the end-of-dive CNS value from float to integer. |
303 // Reads pre-computed tissue increment factors from a ROM table. | 321 // Reads pre-computed tissue increment factors from a ROM table. |
304 static void read_Buhlmann_ht(void); // Reads the half-times from a ROM table. | 322 static void read_Buhlmann_ht(void); // Reads the half-times from a ROM table. |
305 static void adopt_Buhlmann_coefficients(void); // Computes average a and b coefficient by the N2/He tissue ratio. | 323 static void adopt_Buhlmann_coefficients(void); // Computes average a and b coefficient by the N2/He tissue ratio. |
306 static void push_tissues_to_vault(void); // Stores the state of the real tissues during simulator runs. | 324 static void push_tissues_to_vault(void); // Stores the state of the real tissues during simulator runs. |
307 static void pull_tissues_from_vault(void); // Restores the state of the real tissues after a simulator run. | 325 static void pull_tissues_from_vault(void); // Restores the state of the real tissues after a simulator run. |
308 static void calc_sim_pres_respiration(void); // Calculate sim_pres_respiration from char_depth_sim. | |
309 static void calc_N2_equilibrium(void); // Calculate partial pressure of N2 in respired air at surface pressure. | 326 static void calc_N2_equilibrium(void); // Calculate partial pressure of N2 in respired air at surface pressure. |
310 static void get_saturation_factors(void); // Get, safeguard and convert the saturation and desaturation factors. | 327 static void get_saturation_factors(void); // Get, safeguard and convert the saturation and desaturation factors. |
311 static void apply_saturation_factors(void); // Applies saturation and desaturation factors. | 328 static void apply_saturation_factors(void); // Applies saturation and desaturation factors. |
312 | 329 |
313 | 330 |
320 //---- Bank 5 parameters ----------------------------------------------------- | 337 //---- Bank 5 parameters ----------------------------------------------------- |
321 #ifndef UNIX | 338 #ifndef UNIX |
322 # pragma udata bank5=0x500 | 339 # pragma udata bank5=0x500 |
323 #endif | 340 #endif |
324 | 341 |
325 // Environmental and Gas Data (52 byte) | 342 // Data that go into the deco data vault (4 byte) |
343 | |
344 static float CNS_fraction_real; // || current real CNS (1.00 = 100%) | |
345 | |
346 | |
347 // Environmental and Gas Data (51 byte) | |
326 | 348 |
327 static float pres_surface; // absolute pressure at the surface | 349 static float pres_surface; // absolute pressure at the surface |
328 | 350 |
329 static float float_depth_real; // current real depth in meters, float | 351 static float float_depth_real; // current real depth in meters, float |
330 static unsigned char char_depth_real; // current real depth in meters, integer | 352 static unsigned char char_depth_real; // current real depth in meters, integer |
331 static unsigned char char_depth_sim_start; // start value of simulated depth in meters, integer | 353 static unsigned char char_depth_start; // start value of simulated depth in meters, integer |
332 static unsigned char char_depth_sim; // current value of simulated depth in meters, integer | 354 static unsigned char char_depth_sim; // current value of simulated depth in meters, integer |
333 static unsigned char char_depth_last; // last value of simulated depth in meters, integer | |
334 | 355 |
335 static float real_pres_respiration; // current real depth in absolute pressure | 356 static float real_pres_respiration; // current real depth in absolute pressure |
336 static float real_O2_ratio; // real breathed gas oxygen ratio | 357 static float real_O2_ratio; // real breathed gas oxygen ratio |
337 static float real_N2_ratio; // real breathed gas nitrogen ratio | 358 static float real_N2_ratio; // real breathed gas nitrogen ratio |
338 static float real_He_ratio; // real breathed gas helium ratio | 359 static float real_He_ratio; // real breathed gas helium ratio |
343 static float sim_N2_ratio; // simulated breathed gas nitrogen ratio | 364 static float sim_N2_ratio; // simulated breathed gas nitrogen ratio |
344 static float sim_He_ratio; // simulated breathed gas helium ratio | 365 static float sim_He_ratio; // simulated breathed gas helium ratio |
345 static float sim_pSCR_drop; // simulated ppO2 drop in pSCR loop | 366 static float sim_pSCR_drop; // simulated ppO2 drop in pSCR loop |
346 | 367 |
347 | 368 |
348 // general Deco Parameters (57 byte) | 369 // general Deco Parameters (64 byte) |
349 | 370 |
350 static float GF_low; // gradient factor to determine 1st stop | 371 static float GF_low; // gradient factor to determine 1st stop |
351 static float GF_high; // gradient factor to determine surfacing | 372 static float GF_high; // gradient factor to determine surfacing |
352 | 373 |
353 static unsigned char GF_low_last; // last GF low, used to detect changes | 374 static unsigned char GF_low_last; // last GF low, used to detect a GF change |
354 static unsigned char GF_high_last; // last GF high, used to detect changes | 375 static unsigned char GF_high_last; // last GF high, used to detect a GF change |
355 | 376 |
356 static unsigned char GF_low_depth; // GF low reference depth in current calculation cycle | 377 static unsigned char GF_depth; // GF low reference depth in current calculation cycle |
357 static unsigned char GF_low_depth_norm; // GF low reference depth in normal plan | 378 static unsigned char GF_depth_norm; // GF low reference depth in normal plan |
358 static unsigned char GF_low_depth_alt; // GF low reference depth in alternative plan | 379 static unsigned char GF_depth_alt; // GF low reference depth in alternative plan |
359 | 380 |
360 static float GF_slope; // (GF_high - GF_low) / GF_low_depth in current calculation cycle | 381 static float GF_slope; // (GF_high - GF_low) / GF_depth in current calculation cycle |
361 static float GF_slope_norm; // (GF_high - GF_low) / GF_low_depth_norm in normal plan | 382 static float GF_slope_norm; // (GF_high - GF_low) / GF_depth_norm in normal plan |
362 static float GF_slope_alt; // (GF_high - GF_low) / GF_low_depth_alt in alternative plan | 383 static float GF_slope_alt; // (GF_high - GF_low) / GF_depth_alt in alternative plan |
363 | 384 |
364 static float float_ascent_speed; // ascent speed from options_table (5.0 .. 10.0 m/min) | |
365 static float float_deco_distance; // additional depth below stop depth - not used any more | |
366 static float float_saturation_multiplier; // safety factor for on-gassing rates | 385 static float float_saturation_multiplier; // safety factor for on-gassing rates |
367 static float float_desaturation_multiplier; // safety factor for off-gassing rates | 386 static float float_desaturation_multiplier; // safety factor for off-gassing rates |
368 | 387 |
369 static unsigned char split_N2_He[NUM_COMP]; // used for calculating the desaturation time | 388 static unsigned char split_N2_He[NUM_COMP]; // used for calculating the desaturation time |
370 | 389 static unsigned char deco_gas_type[NUM_GAS]; // type and state of the deco gases |
371 | 390 static unsigned char peer_tank[NUM_GAS]; // bit flag vector indicating peer tanks holding same gas |
372 // real Context: what we are doing now (16 byte) | 391 |
373 | 392 |
374 static float CNS_fraction_real; // current real CNS (1.00 = 100%) | 393 // real Context: what we are doing now (12 byte) |
394 | |
375 static unsigned short IBCD_tissue_vector; // 16 bit vector to memorize all tissues that experience IBCD | 395 static unsigned short IBCD_tissue_vector; // 16 bit vector to memorize all tissues that experience IBCD |
376 | 396 |
377 static float pres_respiration_sac; // used in SAC calculation: current depth in absolute pressure | 397 static float pres_respiration_sac; // used in SAC calculation: current depth in absolute pressure |
378 static float float_sac; // used in SAC calculation: SAC value in float | 398 static float float_sac; // used in SAC calculation: SAC value in float |
379 static unsigned short max_sac_rate; // used in SAC calculation: threshold for SAC rate attention | 399 static unsigned short max_sac_rate; // used in SAC calculation: threshold for SAC rate attention |
392 | 412 |
393 // Result Values from Calculation Functions (9 byte) | 413 // Result Values from Calculation Functions (9 byte) |
394 | 414 |
395 static float ceiling; // minimum tolerated relative pressure (i.e. without surface pressure) | 415 static float ceiling; // minimum tolerated relative pressure (i.e. without surface pressure) |
396 static float lead_supersat; // supersaturation of the leading tissue, 1.0 = 100% | 416 static float lead_supersat; // supersaturation of the leading tissue, 1.0 = 100% |
397 static unsigned char lead_tissue; // number of the leading tissue | 417 static unsigned char lead_tissue; // number of the leading tissue (0-15) |
398 | 418 |
399 | 419 |
400 // Transfer Variables between calc_desaturation_time() and calc_desaturation_time_helper() (18 byte) | 420 // Transfer Variables between calc_desaturation_time() and calc_desaturation_time_helper() (18 byte) |
401 | 421 |
402 static float desat_factor; // used to cache a pre-computed factor | 422 static float desat_factor; // used to cache a pre-computed factor |
403 static float var_ht; // buffer for a half-time factor | 423 static float var_ht; // half-time factor for the compartment |
404 static float pres_target; // target pressure for a compartment | 424 static float pres_target; // target pressure for the compartment |
405 static float pres_actual; // current pressure of the compartment | 425 static float pres_actual; // current pressure of the compartment |
406 static unsigned short int_time; // time it takes for the compartment to reach the target pressure | 426 static unsigned short int_time; // time it takes for the compartment to reach the target pressure |
407 | 427 |
408 | 428 |
409 // Gas in Use and Gas Needs (26 byte) | 429 // Gas in Use and Gas Needs (67 byte) |
430 | |
431 static unsigned char start_gas_num; // number of the gas/dil to start with | |
410 | 432 |
411 static unsigned char sim_gas_last_num; // number of the last used gas | 433 static unsigned char sim_gas_last_num; // number of the last used gas |
412 static unsigned char sim_gas_current_num; // number of the currently used gas | 434 static unsigned char sim_gas_current_num; // number of the currently used gas |
413 static unsigned char sim_gas_current_depth; // change depth of the currently used gas | 435 static unsigned char sim_gas_current_depth; // change depth of the currently used gas |
414 | 436 |
415 static unsigned char sim_gas_best_num; // number of the better gas | 437 static unsigned char sim_gas_best_num; // number of the best gas available |
416 static unsigned char sim_gas_best_depth; // change depth of the better gas | 438 static unsigned char sim_gas_best_depth; // change depth of the best gas available |
417 | 439 |
418 static unsigned char gas_needs_gas_index; // index to the gas and tank data arrays | 440 static unsigned char gas_needs_gas_index; // index to the gas and tank data arrays |
419 static float gas_volume_need[NUM_GAS]; // gas volumes required for return/ascent in liters | 441 static float gas_volume_need[NUM_GAS]; // gas volumes required for ascent / cave return in liters |
420 static float gas_volume_avail[NUM_GAS]; // gas volumes available for return/ascent in liters | 442 static float gas_volume_avail[NUM_GAS]; // gas volumes available for ascent / cave return in liters |
421 | 443 static float gas_volume_atten[NUM_GAS]; // attention threshold for gas volumes available |
422 | 444 |
423 // Transfer Variables for calc_due_by_depth_time_sac() (7 byte) | 445 |
446 // Transfer Variables for calc_required_volume() (7 byte) | |
424 | 447 |
425 static unsigned char gas_needs_depth; // depth of the stop or half-way point | 448 static unsigned char gas_needs_depth; // depth of the stop or half-way point |
426 static unsigned char gas_needs_time; // duration of the stop or ascent phase | 449 static unsigned char gas_needs_time; // duration of the stop, ascent or travel phase |
427 static unsigned char gas_needs_usage_rate; // gas usage in l/min | 450 static unsigned char gas_needs_usage_rate; // gas usage in l/min |
428 static float gas_needs_volume_due; // computed due of gas volume required | 451 static float gas_needs_volume_due; // computed amount of required gas volume |
429 | 452 |
430 | 453 |
431 // Auxiliary Variables for Data Buffering (28 byte) | 454 // 243 byte used, 13 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) |
432 | |
433 static float N2_equilibrium; // used for N2 tissue graphics scaling | |
434 static float temp_tissue; // auxiliary variable to buffer tissue pressures | |
435 static float float_pSCR_factor; // pre-computed factor for pSCR ppO2 drop calculation | |
436 static float calc_pres_tissue_N2; // auxiliary variable to buffer tissue N2 pressure | |
437 static float calc_pres_tissue_He; // auxiliary variable to buffer tissue He pressure | |
438 static float pres_tissue; // auxiliary variable to buffer total tissue pressure | |
439 static float old_pres_respiration; // auxiliary variable to buffer sim_pres_respiration | |
440 | |
441 | |
442 // 244 byte used, 12 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) | |
443 | 455 |
444 | 456 |
445 //---- Bank 6 parameters ----------------------------------------------------- | 457 //---- Bank 6 parameters ----------------------------------------------------- |
446 #ifndef UNIX | 458 #ifndef UNIX |
447 # pragma udata bank6=0x600 | 459 # pragma udata bank6=0x600 |
448 #endif | 460 #endif |
449 | 461 |
450 // Timer5 Interface (3 byte) - Attention: keep order and keep at beginning of bank 6, i.e. at address 0x600 ! | 462 // Timer5 Interface (3 byte) - Attention: keep order and keep at beginning of bank 6, i.e. at address 0x600 ! |
451 | 463 |
452 static volatile unsigned short tmr5_value; // timer 5 value buffer MUST be at address 0x600 | 464 static volatile unsigned short tmr5_value; // | timer 5 value buffer MUST be at address 0x600 |
453 static volatile unsigned char tmr5_overflow; // timer 5 overflow flag MUST be at address 0x602 | 465 static volatile unsigned char tmr5_overflow; // | timer 5 overflow flag MUST be at address 0x602 |
454 | 466 |
455 | 467 |
456 // Modes, Sequencing and Indexing (12 byte) | 468 // Modes, Sequencing and Indexing (14 byte) |
457 | 469 |
458 static unsigned char main_status; // shadow register for char_O_main_status | 470 static unsigned char main_status; // shadow register for char_O_main_status |
459 static unsigned char deco_status; // shadow register for char_O_deco_status | 471 static unsigned char deco_status; // shadow register for char_O_deco_status |
460 static unsigned char deco_info; // shadow register for char_O_deco_info | 472 static unsigned char deco_info; // shadow register for char_O_deco_info |
461 static unsigned char deco_warnings; // shadow register for char_O_deco_warnings | 473 static unsigned char deco_warnings; // shadow register for char_O_deco_warnings |
463 static unsigned char tissue_increment; // selector for real/simulated tissues and time increment | 475 static unsigned char tissue_increment; // selector for real/simulated tissues and time increment |
464 static unsigned char sequence_timer; // timer to sequence deco engine tasks | 476 static unsigned char sequence_timer; // timer to sequence deco engine tasks |
465 static unsigned char ci; // index to the Buhlmann tables (compartment index) | 477 static unsigned char ci; // index to the Buhlmann tables (compartment index) |
466 static unsigned char cns_i; // index to the CNS tables (ppO2 range index) | 478 static unsigned char cns_i; // index to the CNS tables (ppO2 range index) |
467 static unsigned char i; // general purpose loop counter and index | 479 static unsigned char i; // general purpose loop counter and index |
468 static unsigned char fast; // selects 1 minute or 2 second ascent steps | 480 static unsigned char j; // general purpose loop counter and index |
469 static unsigned char stop_index; // current stop table position | 481 static unsigned char stop_index; // current stop table position |
470 static unsigned char chained_stops; // counter for chained stop entries | 482 static unsigned char chained_stops; // counter for chained stop entries |
483 static unsigned char backtrack_index; // index into the depth backtracking array char_I_backtrack_storage | |
484 static unsigned char backtrack_target_depth; // current backtracking target depth | |
485 static unsigned char backtrack_step_counter; // counter for number of 1/10 minute steps done | |
471 | 486 |
472 | 487 |
473 // Result Values from Calculation Functions (28 byte) | 488 // Result Values from Calculation Functions (28 byte) |
474 | 489 |
475 static float O2_ppO2; // ppO2 - calculated for pure oxygen at current depth | 490 static float ppO2_O2; // ppO2 calculated for breathing pure oxygen in OC mode |
476 static float OC_ppO2; // ppO2 - calculated for breathing in OC mode | 491 static float ppO2_OC; // ppO2 calculated for breathing current gas in OC mode |
477 static float pSCR_ppO2; // ppO2 - calculated for breathing in pSCR mode | 492 static float ppO2_pSCR; // ppO2 calculated for breathing current gas in pSCR mode |
478 | 493 |
479 static float ppO2; // partial pressure of breathed oxygen | 494 static float ppO2; // partial pressure of breathed oxygen |
480 static float ppN2; // partial pressure of breathed nitrogen | 495 static float ppN2; // partial pressure of breathed nitrogen |
481 static float ppHe; // partial pressure of breathed helium | 496 static float ppHe; // partial pressure of breathed helium |
482 | 497 |
483 static unsigned char char_ppO2; // partial pressure of breathed oxygen, as integer 100 = 1.00 bar | 498 static unsigned char char_ppO2; // partial pressure of breathed oxygen, 100 = 1.00 bar |
484 static unsigned char NDL_time; // time in minutes until reaching NDL | 499 static unsigned char NDL_time; // time in full minutes until reaching no-deco limit (NDL) |
485 static unsigned short ascent_time; // time in minutes needed for the ascent | 500 static unsigned short TTS_time; // time in 1/10 minutes until finishing ascent / cave return |
501 static unsigned short TST_time; // time in full minutes of all stops in ascent / cave return | |
486 | 502 |
487 | 503 |
488 // Buhlmann Model Parameters (40 byte) | 504 // Buhlmann Model Parameters (40 byte) |
489 | 505 |
490 static float var_N2_a; // Buhlmann a, for current N2 tissue | 506 static float var_N2_a; // Buhlmann a for current N2 tissue |
491 static float var_N2_b; // Buhlmann b, for current N2 tissue | 507 static float var_N2_b; // Buhlmann b for current N2 tissue |
492 static float var_He_a; // Buhlmann a, for current He tissue | 508 static float var_He_a; // Buhlmann a for current He tissue |
493 static float var_He_b; // Buhlmann b, for current He tissue | 509 static float var_He_b; // Buhlmann b for current He tissue |
494 static float var_a; // Buhlmann a, adopted to current N2/He ratio | 510 static float var_a; // Buhlmann a adopted to current N2/He ratio |
495 static float var_b; // Buhlmann b, adopted to current N2/He ratio | 511 static float var_b; // Buhlmann b adopted to current N2/He ratio |
496 static float var_N2_e; // exposition, for current N2 tissue | 512 static float var_N2_e; // exposition for current N2 tissue |
497 static float var_He_e; // exposition, for current He tissue | 513 static float var_He_e; // exposition for current He tissue |
498 static float var_N2_ht; // half-time, for current N2 tissue | 514 static float var_N2_ht; // half-time for current N2 tissue |
499 static float var_He_ht; // half-time, for current He tissue | 515 static float var_He_ht; // half-time for current He tissue |
500 | 516 |
501 | 517 |
502 // CNS Coefficients (10 byte) | 518 // CNS Coefficients (10 byte) |
503 | 519 |
504 static float var_cns_a; // two coefficients approximation, gain | 520 static float var_cns_gain; // two coefficients approximation, gain |
505 static float var_cns_b; // two coefficients approximation, offset | 521 static float var_cns_offset; // two coefficients approximation, offset |
506 static unsigned short var_cns_c; // one coefficient approximation, value | 522 static unsigned short var_cns_value; // one coefficient approximation, value |
507 | 523 |
508 | 524 |
509 // Vault to back-up & restore Tissue related Data (134 byte) | 525 // Auxiliary Variables for Data Buffering (28 byte) |
510 | 526 |
511 static float vault_pres_tissue_N2[NUM_COMP]; // stores the nitrogen tissue pressures | 527 static float N2_equilibrium; // used for N2 tissue graphics scaling |
512 static float vault_pres_tissue_He[NUM_COMP]; // stores the helium tissue pressures | 528 static float temp_tissue; // auxiliary variable to buffer tissue pressures |
513 static float vault_CNS_fraction_real; // stores current CNS (float representation) | 529 static float float_pSCR_factor; // pre-computed factor for pSCR ppO2 drop calculation |
514 static unsigned char vault_deco_warnings; // stores warnings status | 530 static float calc_pres_tissue_N2; // auxiliary variable to buffer tissue N2 pressure |
515 static unsigned char vault_deco_info; // stores info status | 531 static float calc_pres_tissue_He; // auxiliary variable to buffer tissue He pressure |
516 | 532 static float pres_tissue; // auxiliary variable to buffer total tissue pressure |
517 | 533 static float old_pres_respiration; // auxiliary variable to buffer sim_pres_respiration |
518 // Transfer values for convert_float_int and convert_float_to_char() (7 byte) | 534 |
535 | |
536 // Transfer Values for convert_float_to_int() (6 byte) | |
519 | 537 |
520 static float float_value; // input value, float | 538 static float float_value; // input value, float |
521 static unsigned short int_value; // output value, 16 bit | 539 static unsigned short int_value; // output value, 16 bit |
522 static unsigned char char_value; // output value, 8 bit | |
523 | 540 |
524 | 541 |
525 // Performance Profiling (4 byte) | 542 // Performance Profiling (4 byte) |
526 | 543 |
527 static unsigned short profiling_runtime; // performance measurement: runtime of current invocation | 544 static unsigned short profiling_runtime; // performance measurement: runtime of current invocation |
530 | 547 |
531 | 548 |
532 // 7 byte occupied by compiler-placed vars | 549 // 7 byte occupied by compiler-placed vars |
533 | 550 |
534 | 551 |
535 // 245 byte used, 11 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) | 552 // 139 byte used, 117 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) |
536 | 553 |
537 | 554 |
538 | 555 |
539 //---- Bank 12 parameters ----------------------------------------------------- | 556 //---- Bank 12 parameters ----------------------------------------------------- |
540 #ifndef UNIX | 557 #ifndef UNIX |
546 static unsigned char internal_deco_depth[NUM_STOPS]; // depths of the stops in meters | 563 static unsigned char internal_deco_depth[NUM_STOPS]; // depths of the stops in meters |
547 static unsigned char internal_deco_time[NUM_STOPS]; // durations of the stops in minutes | 564 static unsigned char internal_deco_time[NUM_STOPS]; // durations of the stops in minutes |
548 static unsigned char internal_deco_gas[NUM_STOPS]; // gases used on the stops (0 / 1-5) | 565 static unsigned char internal_deco_gas[NUM_STOPS]; // gases used on the stops (0 / 1-5) |
549 | 566 |
550 | 567 |
551 // 96 byte used, 160 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) | 568 // Vault to back-up & restore Tissue related Data (134 byte) |
569 | |
570 static float vault_pres_tissue_N2[NUM_COMP]; // stores the nitrogen tissue pressures | |
571 static float vault_pres_tissue_He[NUM_COMP]; // stores the helium tissue pressures | |
572 static float vault_CNS_fraction_real; // stores CNS percentage (1.0 = 100%) | |
573 static unsigned char vault_deco_warnings; // stores warnings status | |
574 static unsigned char vault_deco_info; // stores info status | |
575 | |
576 // 230 byte used, 26 byte left in this bank (4 bytes per float, 2 bytes per short, 1 byte per char) | |
552 | 577 |
553 | 578 |
554 //---- Bank 7 parameters ----------------------------------------------------- | 579 //---- Bank 7 parameters ----------------------------------------------------- |
555 #ifndef UNIX | 580 #ifndef UNIX |
556 # pragma udata bank7=0x700 | 581 # pragma udata bank7=0x700 |
589 // L O O K - U P T A B L E S | 614 // L O O K - U P T A B L E S |
590 // | 615 // |
591 // ********************************************************************************************************************************* | 616 // ********************************************************************************************************************************* |
592 | 617 |
593 #ifndef UNIX | 618 #ifndef UNIX |
619 # pragma romdata Buhlmann_ht = 0x1DC00 // needs to be in the UPPER bank | |
620 #endif | |
621 | |
622 rom const float Buhlmann_ht[2*16] = { | |
623 // Compartment half-times, in minutes | |
624 //--- N2 ---- He ---------------------- | |
625 4.0, 1.51, | |
626 8.0, 3.02, | |
627 12.5, 4.72, | |
628 18.5, 6.99, | |
629 27.0, 10.21, | |
630 38.3, 14.48, | |
631 54.3, 20.53, | |
632 77.0, 29.11, | |
633 109.0, 41.20, | |
634 146.0, 55.19, | |
635 187.0, 70.69, | |
636 239.0, 90.34, | |
637 305.0, 115.29, | |
638 390.0, 147.42, | |
639 498.0, 188.24, | |
640 635.0, 240.03 | |
641 }; | |
642 | |
643 | |
644 #ifndef UNIX | |
594 # pragma romdata CNS_tables = 0x1DC80 // needs to be in the UPPER bank | 645 # pragma romdata CNS_tables = 0x1DC80 // needs to be in the UPPER bank |
595 #endif | 646 #endif |
596 | 647 |
597 rom const float CNS_ab[2*11] = { | 648 rom const float CNS_2_approx[2*11] = { |
598 // CNS increment per 2 sec = 1 / (a*ppO2 + b) with ppO2 in [cbar] | 649 // 2 coefficient approximation for ppO2 = 51 ... 160 cbar |
599 // a b for ppO2 cbar range | 650 // CNS increment per 2 sec = 1 / (gain*ppO2 + offset) with ppO2 in [cbar] |
651 // gain offset for ppO2 cbar range | |
600 -533.07, 54000, // 51 - 60 (index 0) | 652 -533.07, 54000, // 51 - 60 (index 0) |
601 -444.22, 48600, // 61 - 70 (index 1) | 653 -444.22, 48600, // 61 - 70 (index 1) |
602 -355.38, 42300, // 71 - 80 (index 2) | 654 -355.38, 42300, // 71 - 80 (index 2) |
603 -266.53, 35100, // 81 - 90 (index 3) | 655 -266.53, 35100, // 81 - 90 (index 3) |
604 -177.69, 27000, // 91 - 100 (index 4) | 656 -177.69, 27000, // 91 - 100 (index 4) |
608 -88.84, 17100, // 131 - 140 (index 8) | 660 -88.84, 17100, // 131 - 140 (index 8) |
609 -88.84, 17100, // 141 - 150 (index 9) | 661 -88.84, 17100, // 141 - 150 (index 9) |
610 -222.11, 37350 // 151 - 160 (index 10) | 662 -222.11, 37350 // 151 - 160 (index 10) |
611 }; | 663 }; |
612 | 664 |
613 rom const unsigned short CNS_c[1*18] = { | 665 rom const unsigned short CNS_1_approx[1*18] = { |
614 // CNS increment per 2 sec = c / 100000.0 | 666 // 1 coefficient approximation for ppO2 = 161 ... 250 cbar |
615 // c in [1/100000] for ppO2 cbar range | 667 // CNS increment per 2 sec = c / 100000.0 |
668 // value in [1/100000] for ppO2 cbar range | |
616 75, // 161 - 165 (index 0) | 669 75, // 161 - 165 (index 0) |
617 102, // 166 - 170 (index 1) | 670 102, // 166 - 170 (index 1) |
618 136, // 171 - 175 (index 2) | 671 136, // 171 - 175 (index 2) |
619 180, // 176 - 180 (index 3) | 672 180, // 176 - 180 (index 3) |
620 237, // 181 - 185 (index 4) | 673 237, // 181 - 185 (index 4) |
633 4820 // 246 - 250 (index 17) | 686 4820 // 246 - 250 (index 17) |
634 }; | 687 }; |
635 | 688 |
636 | 689 |
637 #ifndef UNIX | 690 #ifndef UNIX |
638 # pragma romdata Buhlmann_tables = 0x1DD00 // needs to be in the UPPER bank | 691 # pragma romdata Buhlmann_ab = 0x1DD00 // needs to be in the UPPER bank |
639 #endif | 692 #endif |
640 | 693 |
641 rom const float Buhlmann_ab[4*16] = { | 694 rom const float Buhlmann_ab[4*16] = { |
695 // Compartment a and b factors | |
642 // Data ZH-L16C, from Bühlmann Tauchmedizin 2002, option 1a (4mn) | 696 // Data ZH-L16C, from Bühlmann Tauchmedizin 2002, option 1a (4mn) |
643 // a for N2 b for N2 a of He b for He | 697 // a for N2 b for N2 a for He b for He |
644 1.2599, 0.5050, 1.7424, 0.4245, | 698 1.2599, 0.5050, 1.7424, 0.4245, |
645 1.0000, 0.6514, 1.3830, 0.5747, | 699 1.0000, 0.6514, 1.3830, 0.5747, |
646 0.8618, 0.7222, 1.1919, 0.6527, | 700 0.8618, 0.7222, 1.1919, 0.6527, |
647 0.7562, 0.7825, 1.0458, 0.7223, | 701 0.7562, 0.7825, 1.0458, 0.7223, |
648 0.6200, 0.8126, 0.9220, 0.7582, | 702 0.6200, 0.8126, 0.9220, 0.7582, |
657 0.2610, 0.9544, 0.5176, 0.9171, | 711 0.2610, 0.9544, 0.5176, 0.9171, |
658 0.2480, 0.9602, 0.5172, 0.9217, | 712 0.2480, 0.9602, 0.5172, 0.9217, |
659 0.2327, 0.9653, 0.5119, 0.9267 | 713 0.2327, 0.9653, 0.5119, 0.9267 |
660 }; | 714 }; |
661 | 715 |
662 rom const float Buhlmann_ht[2*16] = { | 716 |
663 // Compartment half-life, in minutes | 717 #ifndef UNIX |
664 //--- N2 ---- He ---------------------- | 718 # pragma romdata e_tables = 0x1DE00 // needs to be in the UPPER bank |
665 4.0, 1.51, | 719 #endif |
666 8.0, 3.02, | 720 |
667 12.5, 4.72, | 721 rom const float e2sec[2*16] = { |
668 18.5, 6.99, | 722 // Integration constants for 2 seconds, |
669 27.0, 10.21, | 723 // result of 1 - 2^(-(2sec/60sec / HT)) |
670 38.3, 14.48, | |
671 54.3, 20.53, | |
672 77.0, 29.11, | |
673 109.0, 41.20, | |
674 146.0, 55.19, | |
675 187.0, 70.69, | |
676 239.0, 90.34, | |
677 305.0, 115.29, | |
678 390.0, 147.42, | |
679 498.0, 188.24, | |
680 635.0, 240.03 | |
681 }; | |
682 | |
683 rom const float e2secs[2*16] = { | |
684 // Integration constant for 2 seconds, | |
685 // result of 1 - 2^(-1/(2sec/60sec * HT)) | |
686 //---- N2 ------------- He ------------ | 724 //---- N2 ------------- He ------------ |
687 5.75958E-03, 1.51848E-02, | 725 5.75958E-03, 1.51848E-02, |
688 2.88395E-03, 7.62144E-03, | 726 2.88395E-03, 7.62144E-03, |
689 1.84669E-03, 4.88315E-03, | 727 1.84669E-03, 4.88315E-03, |
690 1.24813E-03, 3.29997E-03, | 728 1.24813E-03, 3.29997E-03, |
701 4.63943E-05, 1.22734E-04, | 739 4.63943E-05, 1.22734E-04, |
702 3.63850E-05, 9.62538E-05 | 740 3.63850E-05, 9.62538E-05 |
703 //------------------------------------- | 741 //------------------------------------- |
704 }; | 742 }; |
705 | 743 |
744 rom const float e6sec[2*16] = { | |
745 // Integration constants for 6 seconds, | |
746 // result of 1 - 2^(-(6sec/60sec / HT)) | |
747 //---- N2 ------------- He ------------ | |
748 1.71794E-02, 4.48661E-02, | |
749 8.62691E-03, 2.26905E-02, | |
750 5.52983E-03, 1.45780E-02, | |
751 3.73973E-03, 9.86726E-03, | |
752 2.56392E-03, 6.76591E-03, | |
753 1.80815E-03, 4.77549E-03, | |
754 1.27570E-03, 3.37057E-03, | |
755 8.99786E-04, 2.37830E-03, | |
756 6.35713E-04, 1.68098E-03, | |
757 4.74646E-04, 1.25514E-03, | |
758 3.70598E-04, 9.80064E-04, | |
759 2.89978E-04, 7.66971E-04, | |
760 2.27236E-04, 6.01040E-04, | |
761 1.77714E-04, 4.70075E-04, | |
762 1.39176E-04, 3.68157E-04, | |
763 1.09151E-04, 2.88734E-04 | |
764 //------------------------------------- | |
765 }; | |
766 | |
706 rom const float e1min[2*16] = { | 767 rom const float e1min[2*16] = { |
707 // Integration constant for 1 minute, | 768 // Integration constants for 1 minute, |
708 // result of 1 - 2^(-1/HT) | 769 // result of 1 - 2^(-(1min / HT)) |
709 //----- N2 --------- e 1min He -------- | 770 //----- N2 --------- e 1min He -------- |
710 1.59104E-01, 3.68109E-01, | 771 1.59104E-01, 3.68109E-01, |
711 8.29960E-02, 2.05084E-01, | 772 8.29960E-02, 2.05084E-01, |
712 5.39424E-02, 1.36579E-01, | 773 5.39424E-02, 1.36579E-01, |
713 3.67742E-02, 9.44046E-02, | 774 3.67742E-02, 9.44046E-02, |
725 1.09097E-03, 2.88359E-03 | 786 1.09097E-03, 2.88359E-03 |
726 //------------------------------------- | 787 //------------------------------------- |
727 }; | 788 }; |
728 | 789 |
729 rom const float e10min[2*16] = { | 790 rom const float e10min[2*16] = { |
730 // Integration constant for 10 minutes, | 791 // Integration constants for 10 minutes, |
731 // result of 1 - 2^(-10/ht) | 792 // result of 1 - 2^(-(10min / HT)) |
732 //---- N2 -------------- He ----------- | 793 //---- N2 -------------- He ----------- |
733 8.23223E-01, 9.89851E-01, | 794 8.23223E-01, 9.89851E-01, |
734 5.79552E-01, 8.99258E-01, | 795 5.79552E-01, 8.99258E-01, |
735 4.25651E-01, 7.69737E-01, | 796 4.25651E-01, 7.69737E-01, |
736 3.12487E-01, 6.29027E-01, | 797 3.12487E-01, 6.29027E-01, |
851 #endif | 912 #endif |
852 } | 913 } |
853 | 914 |
854 | 915 |
855 ////////////////////////////////////////////////////////////////////////////// | 916 ////////////////////////////////////////////////////////////////////////////// |
856 // Read CNS coefficients a and b | 917 // Read CNS coefficients gain and offset |
857 // | 918 // |
858 static void read_CNS_ab_coefficient(void) | 919 static void read_CNS_ab_coefficient(void) |
859 { | 920 { |
860 #ifndef CROSS_COMPILE | 921 #ifndef CROSS_COMPILE |
861 // Note: We don't use far ROM pointer, because handling | 922 // Note: We don't use far ROM pointer, because handling |
867 movwf TBLPTRU,0 | 928 movwf TBLPTRU,0 |
868 _endasm | 929 _endasm |
869 #endif | 930 #endif |
870 | 931 |
871 { | 932 { |
872 overlay rom const float* ptr = &CNS_ab[2*cns_i]; | 933 overlay rom const float* ptr = &CNS_2_approx[2*cns_i]; |
873 var_cns_a = *ptr++; | 934 var_cns_gain = *ptr++; |
874 var_cns_b = *ptr++; | 935 var_cns_offset = *ptr++; |
875 } | 936 } |
876 } | 937 } |
877 | 938 |
878 | 939 |
879 ////////////////////////////////////////////////////////////////////////////// | 940 ////////////////////////////////////////////////////////////////////////////// |
891 movwf TBLPTRU,0 | 952 movwf TBLPTRU,0 |
892 _endasm | 953 _endasm |
893 #endif | 954 #endif |
894 | 955 |
895 { | 956 { |
896 overlay rom const unsigned short* ptr = &CNS_c[cns_i]; | 957 overlay rom const unsigned short* ptr = &CNS_1_approx[cns_i]; |
897 var_cns_c = *ptr++; | 958 var_cns_value = *ptr++; |
898 } | 959 } |
899 } | 960 } |
900 | 961 |
901 ////////////////////////////////////////////////////////////////////////////// | 962 ////////////////////////////////////////////////////////////////////////////// |
902 // Read Buhlmann coefficients a and b for compartment ci | 963 // Read Buhlmann coefficients a and b for compartment ci |
935 static void read_Buhlmann_times(PARAMETER char period) | 996 static void read_Buhlmann_times(PARAMETER char period) |
936 { | 997 { |
937 #ifndef CROSS_COMPILE | 998 #ifndef CROSS_COMPILE |
938 // Note: We don't use far ROM pointer, because handling | 999 // Note: We don't use far ROM pointer, because handling |
939 // 24 bit is to complex, hence we have to set the | 1000 // 24 bit is to complex, hence we have to set the |
940 // UPPER page ourself... | 1001 // UPPER page by hand... |
941 // -> set to zero if tables are moved to lower pages! | 1002 // -> set to zero if tables are moved to lower pages! |
942 _asm | 1003 _asm |
943 movlw 1 | 1004 movlw 1 |
944 movwf TBLPTRU,0 | 1005 movwf TBLPTRU,0 |
945 _endasm | 1006 _endasm |
948 assert( ci < NUM_COMP ); | 1009 assert( ci < NUM_COMP ); |
949 | 1010 |
950 // Integration Intervals | 1011 // Integration Intervals |
951 switch(period) | 1012 switch(period) |
952 { | 1013 { |
953 case 0: //---- 2 sec ----------------------------------------------------- | 1014 case 0: //---- 2 or 6 seconds -------------------------------------------- |
954 { | 1015 { |
955 overlay rom const float* ptr = &e2secs[2*ci]; | 1016 // check which tissues are selected |
956 var_N2_e = *ptr++; | 1017 if(tissue_increment & TISSUE_SELECTOR) |
957 var_He_e = *ptr++; | 1018 { |
1019 // real tissues - 2 seconds | |
1020 overlay rom const float* ptr = &e2sec[2*ci]; | |
1021 var_N2_e = *ptr++; | |
1022 var_He_e = *ptr++; | |
1023 } | |
1024 else | |
1025 { | |
1026 // simulated tissues - 6 seconds | |
1027 overlay rom const float* ptr = &e6sec[2*ci]; | |
1028 var_N2_e = *ptr++; | |
1029 var_He_e = *ptr++; | |
1030 } | |
958 } | 1031 } |
959 break; | 1032 break; |
960 | 1033 |
961 case 1: //---- 1 min ----------------------------------------------------- | 1034 case 1: //---- 1 minutes ------------------------------------------------- |
962 { | 1035 { |
963 overlay rom const float* ptr = &e1min[2*ci]; | 1036 overlay rom const float* ptr = &e1min[2*ci]; |
964 var_N2_e = *ptr++; | 1037 var_N2_e = *ptr++; |
965 var_He_e = *ptr++; | 1038 var_He_e = *ptr++; |
966 } | 1039 } |
967 break; | 1040 break; |
968 | 1041 |
969 case 2: //---- 10 min ---------------------------------------------------- | 1042 case 2: //---- 10 minutes ------------------------------------------------ |
970 { | 1043 { |
971 overlay rom const float* ptr = &e10min[2*ci]; | 1044 overlay rom const float* ptr = &e10min[2*ci]; |
972 var_N2_e = *ptr++; | 1045 var_N2_e = *ptr++; |
973 var_He_e = *ptr++; | 1046 var_He_e = *ptr++; |
974 } | 1047 } |
1038 | 1111 |
1039 } | 1112 } |
1040 | 1113 |
1041 | 1114 |
1042 ////////////////////////////////////////////////////////////////////////////// | 1115 ////////////////////////////////////////////////////////////////////////////// |
1043 // Calculate sim_pres_respiration from char_depth_sim | |
1044 // | |
1045 // Input: char_depth_sim simulated depth in meters | |
1046 // pres_surface surface pressure | |
1047 // | |
1048 // Output: sim_pres_respiration simulated depth in absolute pressure | |
1049 // | |
1050 static void calc_sim_pres_respiration(void) | |
1051 { | |
1052 sim_pres_respiration = (float)char_depth_sim * METER_TO_BAR + pres_surface; | |
1053 } | |
1054 | |
1055 | |
1056 ////////////////////////////////////////////////////////////////////////////// | |
1057 // Calculate partial pressure of N2 in respired air at surface pressure | 1116 // Calculate partial pressure of N2 in respired air at surface pressure |
1058 // | 1117 // |
1059 // Input: pres_surface surface pressure | 1118 // Input: pres_surface surface pressure |
1060 // | 1119 // |
1061 // Output: N2_equilibrium partial pressure of N2 in surface air | 1120 // Output: N2_equilibrium partial pressure of N2 in surface air |
1118 else if ( float_value >= 9.985 ) int_value = 999; | 1177 else if ( float_value >= 9.985 ) int_value = 999; |
1119 else int_value = (unsigned short)(100 * float_value + 0.5); | 1178 else int_value = (unsigned short)(100 * float_value + 0.5); |
1120 } | 1179 } |
1121 | 1180 |
1122 | 1181 |
1123 ////////////////////////////////////////////////////////////////////////////// | |
1124 // convert_float_to_char | |
1125 // | |
1126 // Converts a float within range 0.0 - 255 into 8 bit integer | |
1127 // | |
1128 static void convert_float_to_char(void) | |
1129 { | |
1130 if (float_value < 0.0) char_value = 0; | |
1131 else if (float_value >= 254.5) char_value = 255; | |
1132 else char_value = (unsigned char)(float_value + 0.5); | |
1133 } | |
1134 | |
1135 | 1182 |
1136 // ********************************************************************************************************************************* | 1183 // ********************************************************************************************************************************* |
1137 // | 1184 // |
1138 // J U M P I N F U N C T I O N S | 1185 // J U M P I N F U N C T I O N S |
1139 // | 1186 // |
1297 ////////////////////////////////////////////////////////////////////////////// | 1344 ////////////////////////////////////////////////////////////////////////////// |
1298 // Calculate the next deco stop | 1345 // Calculate the next deco stop |
1299 // | 1346 // |
1300 // INPUT, fixed during dive: | 1347 // INPUT, fixed during dive: |
1301 // pres_surface : surface pressure (as absolute pressure) | 1348 // pres_surface : surface pressure (as absolute pressure) |
1302 // char_I_depth_last_deco : depth of the last deco stop | 1349 // char_I_last_stop_depth : depth of the last deco stop |
1303 // | 1350 // |
1304 // INPUT, may change during dive: | 1351 // INPUT, may change during dive: |
1305 // GF_high : GF high factor | 1352 // GF_high : GF high factor |
1306 // GF_low : GF low factor | 1353 // GF_low : GF low factor |
1307 // | 1354 // GF_depth : GF low reference depth |
1308 // INPUT & OUTPUT | 1355 // GF_slope : GF slope |
1356 // | |
1357 // MODIFIED | |
1309 // char_depth_sim : simulated depth in meters | 1358 // char_depth_sim : simulated depth in meters |
1310 // GF_low_depth : GF low depth in current calculation cycle | |
1311 // GF_slope : GF slope in current calculation cycle | |
1312 // GF_low_depth_norm/_alt : frozen GF low depth reference | |
1313 // GF_slope_norm/_alt : frozen GF slope | |
1314 // | 1359 // |
1315 // OUTPUT | 1360 // OUTPUT |
1316 // char_depth_last : depth we came from | 1361 // GF_depth_norm/_alt : updated GF low depth reference |
1317 // sim_pres_respiration : simulated depth in absolute pressure | 1362 // GF_slope_norm/_alt : updated GF slope |
1318 // | 1363 // |
1319 // RETURN | 1364 // RETURN |
1320 // TRUE: a stop is needed, FALSE: no stop needed | 1365 // TRUE: a deco stop is required, FALSE: no deco stop required |
1321 // | 1366 // |
1322 static unsigned char find_next_stop(void) | 1367 static unsigned char find_next_stop(void) |
1323 { | 1368 { |
1324 overlay unsigned char depth_1min; | 1369 overlay unsigned char depth_1min; |
1325 overlay unsigned char depth_limit; | 1370 overlay unsigned char depth_limit; |
1326 overlay unsigned char stop_depth; | 1371 overlay unsigned char stop_depth; |
1327 overlay unsigned char next_stop; | 1372 overlay unsigned char next_stop; |
1328 overlay unsigned char need_stop; | 1373 |
1329 | 1374 |
1330 | 1375 // calculate the current deco ceiling (minimum relative pressure) |
1331 // memorize the depth we came from | 1376 if( char_I_model == 0 ) calc_limit(1.0); // straight Buhlmann |
1332 char_depth_last = char_depth_sim; | 1377 else if( NDL_time ) calc_limit(GF_high); // with GF: not in deco |
1333 | 1378 else if( char_depth_sim >= GF_depth ) calc_limit(GF_low); // in deco, below or at low depth reference |
1334 // calculate the ceiling (minimum relative pressure) for the current depth | 1379 else calc_limit(GF_high - GF_slope * (float)char_depth_sim); // in deco, above low depth reference |
1335 if( char_I_deco_model == 0 ) calc_limit(1.0); // deco or not - straight Buhlmann | 1380 |
1336 else if( NDL_time ) calc_limit(GF_high); // not in deco | 1381 // convert the deco ceiling from relative pressure to meters, |
1337 else if( char_depth_sim >= GF_low_depth ) calc_limit(GF_low); // in deco with GF, below or at low depth reference | 1382 // rounded up (i.e. made deeper) to the next full meter |
1338 else calc_limit(GF_high - GF_slope * (float)char_depth_sim); // in deco with GF, above low depth reference | 1383 depth_limit = (unsigned char)(ceiling * BAR_TO_METER + 0.99); |
1339 | 1384 |
1340 // convert the ceiling from relative pressure to meters, | 1385 |
1341 // rounded up (i.e. made deeper) to next full meter, | 1386 #ifdef _cave_mode |
1342 // limiting at surface. | 1387 // in cave or open water mode? |
1343 depth_limit = (ceiling > 0.0) ? (unsigned char)(ceiling * BAR_TO_METER + 0.99) : 0; | 1388 if( main_status & CAVE_MODE ) |
1344 | 1389 { |
1345 // calculate the stop depth, i.e. round up (make deeper) to | 1390 // cave mode |
1346 // the next multiple of 3 meters using integer arithmetics | 1391 |
1347 stop_depth = 3 * ( (depth_limit + 2) / 3 ); | 1392 // does backtracking require descent or keeping depth? |
1348 | 1393 if( backtrack_target_depth >= char_depth_sim ) |
1349 // apply correction for the shallowest stop | 1394 { |
1350 if( stop_depth == 3 ) stop_depth = char_I_depth_last_deco; | 1395 // YES - decent to target depth or stay at current depth |
1351 | 1396 char_depth_sim = backtrack_target_depth; |
1352 // compute depth in meters that will be reached in 1 minute of ascent | 1397 |
1353 // at a speed of char_I_ascent_speed (5..10 m/min) | 1398 // - done, no stop required |
1354 if( char_depth_sim > char_I_ascent_speed ) | 1399 return(0); |
1355 { | 1400 } |
1356 depth_1min = char_depth_sim - char_I_ascent_speed; | 1401 else |
1402 { | |
1403 // NO | |
1404 | |
1405 // target depth requires an ascent - determine ascent limit due to deco obligation | |
1406 stop_depth = depth_limit; | |
1407 | |
1408 // apply correction for the shallowest stop | |
1409 if( stop_depth && (stop_depth < char_I_last_stop_depth) ) stop_depth = char_I_last_stop_depth; | |
1410 } | |
1357 } | 1411 } |
1358 else | 1412 else |
1359 { | 1413 #endif |
1360 depth_1min = 0; | 1414 { |
1361 } | 1415 // open water vertical ascent mode - determine the stop depth |
1362 | 1416 |
1363 // is the stop depth shallower than the depth that can be reached within 1 minute, | 1417 // stop depth is depth limit rounded up (made deeper) to the next multiple of 3 meters |
1364 // or are we allowed to surface AND can we reach the surface within 1 minute? | 1418 stop_depth = 3 * ( (depth_limit + 2) / 3 ); |
1365 if( ( ( stop_depth < depth_1min ) ) | 1419 |
1366 || ( ( stop_depth == 0 ) && ( depth_1min == 0 ) ) | 1420 // apply correction for the shallowest stop |
1367 ) | 1421 if( stop_depth == 3 ) stop_depth = char_I_last_stop_depth; |
1368 { | 1422 } |
1369 // YES - report the depth that will be reached within 1 minute of ascent | 1423 |
1370 char_depth_sim = depth_1min; | 1424 // is the stop depth shallower than the current depth (can we ascent)? |
1371 | 1425 if( stop_depth < char_depth_sim ) |
1372 // - no stop needed | 1426 { |
1373 need_stop = 0; | 1427 // YES - ascent by 1 meter |
1374 | 1428 char_depth_sim--; |
1375 // - done | 1429 |
1376 goto done; | 1430 // done, no stop needed |
1431 return(0); | |
1377 } | 1432 } |
1378 | 1433 |
1379 // ----------------------------------------------------------------------- | 1434 // ----------------------------------------------------------------------- |
1380 // we need to make a stop now, or need to stay at the current stop depth | 1435 // we need to make a stop because we are not allowed to ascent any further |
1381 // ----------------------------------------------------------------------- | 1436 // ----------------------------------------------------------------------- |
1382 | 1437 |
1383 // set stop data | 1438 // set depth to stop depth |
1384 need_stop = 1; | |
1385 char_depth_sim = stop_depth; | 1439 char_depth_sim = stop_depth; |
1386 | 1440 |
1387 // Apply correction in case the stop is to be placed deeper than a | 1441 // Apply correction in case the stop is to be placed deeper than a |
1388 // previously recorded stop for a gas change. This may happen because | 1442 // previously recorded stop for a gas change. This may happen because |
1389 // the deco stops are placed at the next deeper multiple of 3 meters | 1443 // the deco stops are placed at the next deeper multiple of 3 meters |
1391 // deco stop to the depth of the last gas change. The resulting combined | 1445 // deco stop to the depth of the last gas change. The resulting combined |
1392 // stop's duration will be the sum of the configured gas change time plus | 1446 // stop's duration will be the sum of the configured gas change time plus |
1393 // the duration of the deco stop itself. | 1447 // the duration of the deco stop itself. |
1394 if( 0 < internal_deco_depth[stop_index] ) | 1448 if( 0 < internal_deco_depth[stop_index] ) |
1395 if( char_depth_sim > internal_deco_depth[stop_index] ) | 1449 if( char_depth_sim > internal_deco_depth[stop_index] ) |
1396 char_depth_sim = internal_deco_depth[stop_index]; | 1450 char_depth_sim = internal_deco_depth[stop_index]; |
1397 | 1451 |
1398 // done so far if using straight Buhlmann | 1452 // if using straight Buhlmann: done, stop needed |
1399 if( char_I_deco_model == 0 ) goto done; | 1453 if( char_I_model == 0 ) return(1); |
1400 | 1454 |
1401 // ----------------------------------------------------------------------- | 1455 // ----------------------------------------------------------------------- |
1402 // we need to make or hold a stop and we are using the GF extension | 1456 // we need to make or hold a stop and we are using the GF extension |
1403 // ----------------------------------------------------------------------- | 1457 // ----------------------------------------------------------------------- |
1404 | 1458 |
1405 // is the stop depth deeper than the GF low depth reference used up to now? | 1459 // is the stop_depth deeper than the GF low depth reference used up to now? |
1406 if( stop_depth > GF_low_depth ) | 1460 if( stop_depth > GF_depth ) |
1407 { | 1461 { |
1408 // YES - update the reference | 1462 // YES - update the GF low depth reference |
1409 GF_low_depth = stop_depth; | 1463 GF_depth = stop_depth; |
1410 GF_slope = (GF_high - GF_low) / (float)GF_low_depth; | 1464 GF_slope = (GF_high - GF_low) / (float)GF_depth; |
1411 | 1465 |
1412 // store for use in next cycles | 1466 // store for use in next cycles |
1413 if( deco_status & CALC_NORM ) | 1467 if( deco_status & CALC_NORM ) |
1414 { | 1468 { |
1415 GF_low_depth_norm = GF_low_depth; | 1469 GF_depth_norm = GF_depth; |
1416 GF_slope_norm = GF_slope; | 1470 GF_slope_norm = GF_slope; |
1417 } | 1471 } |
1418 else | 1472 else |
1419 { | 1473 { |
1420 GF_low_depth_alt = GF_low_depth; | 1474 GF_depth_alt = GF_depth; |
1421 GF_slope_alt = GF_slope; | 1475 GF_slope_alt = GF_slope; |
1422 } | 1476 } |
1423 } | 1477 } |
1424 | 1478 |
1425 // We have a (first) stop. But with a steep GF slope, the stop(s) after this | 1479 #ifdef _cave_mode |
1426 // first stop may be allowed to ascent to, too. This is because the gradient | 1480 // if in cave mode: done, stop needed |
1481 if( main_status & CAVE_MODE ) return(1); | |
1482 #endif | |
1483 | |
1484 // We have a stop depth candidate. But with a steep GF slope, the stop(s) after | |
1485 // this first stop may be allowed to ascent to, too. This is because the gradient | |
1427 // factor that will be used at the next depth(s) will allow more tissue super- | 1486 // factor that will be used at the next depth(s) will allow more tissue super- |
1428 // saturation, maybe so much more that the next stop(s) will be allowed to | 1487 // saturation, maybe so much more that the next stop(s) will be allowed to ascent |
1429 // ascent to. So we have to probe the next stops that are within the reach of | 1488 // to. So we have to probe the next stops that are within the reach of 1 minute |
1430 // 1 minute of ascent as well. | 1489 // of ascent as well. |
1490 | |
1491 // compute depth in meters that is reachable within 1 minute of ascent at 10 m/min | |
1492 depth_1min = ( char_depth_sim > 10 ) ? char_depth_sim - 10 : 0; | |
1431 | 1493 |
1432 // probe all stop depths that are in reach of 1 minute of ascent | 1494 // probe all stop depths that are in reach of 1 minute of ascent |
1433 next_stop = stop_depth; | 1495 next_stop = stop_depth; |
1434 | 1496 |
1435 while(next_stop > 0) | 1497 while(next_stop > 0) |
1436 { | 1498 { |
1437 // compute the depth of the next stop ... | 1499 // compute the depth of the next stop to probe |
1438 if ( next_stop <= char_I_depth_last_deco ) next_stop = 0; | 1500 if ( next_stop <= char_I_last_stop_depth ) next_stop = 0; |
1439 else if ( next_stop == 6 ) next_stop = char_I_depth_last_deco; | 1501 else if ( next_stop == 6 ) next_stop = char_I_last_stop_depth; |
1440 else next_stop -= 3; | 1502 else next_stop -= 3; |
1441 | 1503 |
1442 // would the next stop be beyond the 1 minute limit? | 1504 // done if the next stop would be above the 1 minute limit |
1443 if( next_stop < depth_1min ) | 1505 if( next_stop < depth_1min ) return(1); |
1444 { | 1506 |
1445 // YES - signal that probing is done | 1507 // compute the ceiling for the next stop depth |
1446 next_stop = 0; | 1508 calc_limit(GF_high - GF_slope * (float)next_stop); |
1447 } | 1509 |
1448 else | 1510 // done if the next stop would be above the ceiling |
1449 { | 1511 if( next_stop < (unsigned char)(ceiling * BAR_TO_METER + 0.99) ) return(1); |
1450 // NO - compute the ceiling at the next stop depth | 1512 |
1451 calc_limit(GF_high - GF_slope * (float)next_stop); | 1513 // the next stop depth is allowed, ascent to it and redo trying further stop |
1452 | 1514 char_depth_sim = next_stop; |
1453 // - limit ceiling to positive values, i.e. the surface | 1515 } |
1454 if( ceiling < 0.0 ) ceiling = 0.0; | 1516 |
1455 | 1517 // reached the surface, done with no further stop |
1456 // - check if this stop depth would be allowed | 1518 return(0); |
1457 if( next_stop >= (unsigned char)(ceiling * BAR_TO_METER + 0.99) ) | |
1458 { | |
1459 // YES - this stop depth is allowed | |
1460 char_depth_sim = next_stop; | |
1461 | |
1462 // - no stop needed if stop depth actually is the surface | |
1463 if( next_stop == 0 ) need_stop = 0; | |
1464 } | |
1465 } | |
1466 } | |
1467 | |
1468 | |
1469 // ----------------------------------------------------------------------- | |
1470 // common end for straight Buhlmann and Buhlmann with GF extension | |
1471 // ----------------------------------------------------------------------- | |
1472 | |
1473 done: | |
1474 | |
1475 // calculate absolute pressure at the depth found | |
1476 calc_sim_pres_respiration(); | |
1477 | |
1478 return need_stop; | |
1479 } | 1519 } |
1480 | 1520 |
1481 | 1521 |
1482 ////////////////////////////////////////////////////////////////////////////// | 1522 ////////////////////////////////////////////////////////////////////////////// |
1483 // Find current gas in the list and get its change depth | 1523 // Take the actual currently used gas for ascent & deco calculation |
1484 // | 1524 // |
1485 // Input: char_I_current_gas_num number of current gas (1..5 or 6) | 1525 // Input: start_gas_num number of the gas/dil to start with (1..5 or 6) |
1486 // | 1526 // |
1487 // Output: sim_gas_current_num 1..6 or 0 for the manually configured gas/dil | 1527 // Output: sim_gas_current_num 1..6 or 0 for the manually configured gas/dil |
1488 // sim_gas_current_depth change depth (MOD) of the gas/dil in meters | 1528 // sim_gas_current_depth change depth (MOD) of the gas/dil in meters |
1489 // | 1529 // |
1490 static void gas_take_current(void) | 1530 static void gas_take_current(void) |
1491 { | 1531 { |
1492 assert( 1 <= char_I_current_gas_num && char_I_current_gas_num <= 6 ); | 1532 assert( 1 <= start_gas_num && start_gas_num <= 6 ); |
1493 | 1533 |
1494 if( char_I_current_gas_num <= NUM_GAS ) // gas/diluent 1-5 | 1534 |
1495 { | 1535 // check origin of the gas/diluent to start with |
1496 sim_gas_current_num = char_I_current_gas_num; | 1536 if( start_gas_num <= NUM_GAS ) |
1497 sim_gas_current_depth = char_I_deco_gas_change[sim_gas_current_num-1]; | 1537 { |
1538 // pre-configured gas/diluent | |
1539 | |
1540 // set gas number | |
1541 sim_gas_current_num = sim_gas_last_num = start_gas_num; | |
1542 | |
1543 // set change depth | |
1544 sim_gas_current_depth = char_I_deco_gas_change[start_gas_num-1]; | |
1498 | 1545 |
1499 // capture case of non-configured change depth | 1546 // capture case of non-configured change depth |
1500 if( sim_gas_current_depth == 0 ) sim_gas_current_depth = 255; | 1547 if( sim_gas_current_depth == 0 ) sim_gas_current_depth = 255; |
1501 } | 1548 } |
1502 else | 1549 else |
1503 { | 1550 { |
1504 sim_gas_current_num = 0; | 1551 // on-the-fly configured gas/diluent ("gas 6") |
1552 | |
1553 // set gas number | |
1554 sim_gas_current_num = sim_gas_last_num = 0; | |
1555 | |
1556 // set change depth | |
1505 sim_gas_current_depth = char_I_gas6_depth; | 1557 sim_gas_current_depth = char_I_gas6_depth; |
1506 } | 1558 } |
1507 } | 1559 } |
1508 | 1560 |
1509 | 1561 |
1510 ////////////////////////////////////////////////////////////////////////////// | 1562 ////////////////////////////////////////////////////////////////////////////// |
1511 // Find the gas with the shallowest change depth below or at the current depth | 1563 // Find the gas with the shallowest change depth below or at the current depth |
1512 // | 1564 // |
1513 // Input: char_depth_sim simulated depth in meters | 1565 // Input: char_depth_sim simulated depth in meters |
1514 // sim_gas_current_num number of the currently used gas/dil | 1566 // sim_gas_current_num number of the currently used gas/dil |
1515 // char_I_deco_gas_type[] types of the gases/dils | 1567 // deco_gas_type[] types and state of the gases/dils |
1516 // char_I_deco_gas_change[] change depths of the gases/dils | 1568 // char_I_deco_gas_change[] change depths of the gases/dils |
1517 // | 1569 // |
1518 // Modified: sim_gas_best_num index of the gas (1..5) - only if return value is true | 1570 // Modified: sim_gas_best_num index of the gas (1..5) - only if return value is true |
1519 // sim_gas_best_depth switch depth - only if return value is true | 1571 // sim_gas_best_depth switch depth - only if return value is true |
1520 // | 1572 // |
1521 // Return value is TRUE if a better gas is available | 1573 // Return value is TRUE if a better gas is available |
1522 // | 1574 // |
1523 static unsigned char gas_find_best(void) | 1575 static unsigned char gas_find_best(void) |
1524 { | 1576 { |
1525 overlay unsigned char switch_depth = 255; | 1577 overlay unsigned char switch_depth = 255; |
1526 overlay unsigned char switch_gas = 0; | 1578 overlay unsigned char switch_gas = 0; |
1527 overlay unsigned char j; | 1579 |
1528 | 1580 |
1529 // loop over all gases to find the shallowest one below or at current depth | 1581 // loop over all gases to find the shallowest one below or at current depth |
1530 for( j = 0; j < NUM_GAS; ++j ) | 1582 for( j = 0; j < NUM_GAS; ++j ) |
1531 { | 1583 { |
1532 // Is this gas available? | 1584 // is this gas available? |
1533 if( char_I_deco_gas_type[j] > 0 ) | 1585 if( ( deco_gas_type[j] & GAS_TYPE_MASK ) // gas enabled (type > 0) ? |
1534 | 1586 && !( deco_gas_type[j] & GAS_AVAIL_MASK ) // neither lost nor staged ? |
1535 // Is the change depth of the this gas deeper than or | 1587 ) |
1588 | |
1589 // is it not a deco gas unless: | |
1590 // extended stops are activated | |
1591 // OR we are on a deco stop | |
1592 // OR we are in bailout but not in cave mode | |
1593 if( ( ( deco_gas_type[j] & GAS_TYPE_MASK ) < 3 ) | |
1594 || ( ( main_status & EXTENDED_STOPS ) ) | |
1595 || ( ( deco_status & CALC_NORM ) && ( deco_info & DECO_STOPS_NORM ) ) | |
1596 || ( ( deco_status & CALC_ALT ) && ( deco_info & DECO_STOPS_ALT ) ) | |
1597 || ( ( deco_status & BAILOUT_MODE ) && !( main_status & CAVE_MODE ) ) | |
1598 ) | |
1599 | |
1600 // is the change depth of the this gas deeper than or | |
1536 // at least equal to the current depth? | 1601 // at least equal to the current depth? |
1537 if( char_I_deco_gas_change[j] >= char_depth_sim ) | 1602 if( char_I_deco_gas_change[j] >= char_depth_sim ) |
1538 | 1603 |
1539 // Is the change depth of this gas shallower than or | 1604 // is the change depth of this gas shallower than |
1540 // at least equal to the change depth of the best gas | 1605 // the change depth of the best gas found so far, |
1541 // found so far, or is it the first better gas found? | 1606 // or is it the first better gas found? |
1542 if( char_I_deco_gas_change[j] <= switch_depth ) | 1607 if( char_I_deco_gas_change[j] < switch_depth ) |
1543 | 1608 |
1544 #ifdef _gas_contingency | 1609 #ifdef _gas_contingency |
1545 // Is there still enough of this gas or doesn't it matter? | 1610 // is there still enough of this gas or shall we don't care? |
1546 if( ( gas_volume_need[j] < gas_volume_avail[j] ) || ( !char_I_gas_contingency ) ) | 1611 if( !(deco_gas_type[j] & GAS_FULLY_USED_UP ) |
1547 #endif | 1612 || !( main_status & GAS_CONTINGENCY ) |
1548 | 1613 || !( main_status & CALC_VOLUME ) |
1549 // If there is a yes to all these questions, we have a better gas! | 1614 ) |
1615 #endif | |
1616 | |
1617 // if there is a yes to all these questions, we have a better gas! | |
1550 { | 1618 { |
1551 // memorize this gas (1..5) and its change depth | 1619 // memorize this gas (1..5) and its change depth |
1552 switch_gas = j+1; | 1620 switch_gas = j+1; |
1553 switch_depth = char_I_deco_gas_change[j]; | 1621 switch_depth = char_I_deco_gas_change[j]; |
1554 } | 1622 } |
1623 | |
1555 } // continue looping through all gases to eventually find an even better gas | 1624 } // continue looping through all gases to eventually find an even better gas |
1556 | 1625 |
1557 // has a best gas been found? | 1626 // has a best gas been found? |
1558 if( switch_gas ) | 1627 if( switch_gas ) |
1559 { | 1628 { |
1583 // Modified: sim_gas_current_num index of the new gas (1..5) | 1652 // Modified: sim_gas_current_num index of the new gas (1..5) |
1584 // sim_gas_current_depth switch depth of the new gas | 1653 // sim_gas_current_depth switch depth of the new gas |
1585 // | 1654 // |
1586 static void gas_take_best(void) | 1655 static void gas_take_best(void) |
1587 { | 1656 { |
1657 // memorize current gas as last gas used | |
1658 sim_gas_last_num = sim_gas_current_num; | |
1659 | |
1588 // set new gas | 1660 // set new gas |
1589 sim_gas_current_num = sim_gas_best_num; | 1661 sim_gas_current_num = sim_gas_best_num; |
1590 sim_gas_current_depth = sim_gas_best_depth; | 1662 sim_gas_current_depth = sim_gas_best_depth; |
1591 } | 1663 } |
1592 | 1664 |
1653 | 1725 |
1654 | 1726 |
1655 ////////////////////////////////////////////////////////////////////////////// | 1727 ////////////////////////////////////////////////////////////////////////////// |
1656 // Compute respired ppO2, ppN2 and ppHe | 1728 // Compute respired ppO2, ppN2 and ppHe |
1657 // | 1729 // |
1658 // Input: tissue_increment : selector for targeting simulated or real tissues | 1730 // Input: tissue_increment : selector for simulated/real tissues and gases |
1659 // main_status : breathing mode for real tissues | 1731 // main_status : breathing mode for real tissues |
1660 // deco_status : breathing mode for simulated tissues | 1732 // deco_status : breathing mode for simulated tissues |
1661 // sim_/real_O2_ratio : (simulated) O2 ratio breathed | 1733 // sim_/real_O2_ratio : (simulated) O2 ratio breathed |
1662 // sim_/real_N2_ratio : (simulated) N2 ratio breathed | 1734 // sim_/real_N2_ratio : (simulated) N2 ratio breathed |
1663 // sim_/real_He_ratio : (simulated) He ratio breathed | 1735 // sim_/real_He_ratio : (simulated) He ratio breathed |
1664 // sim_/real_pres_respiration : (simulated) respiration pressure [bar] | 1736 // sim_/real_pres_respiration : (simulated) respiration pressure [bar] |
1665 // sim_/real_pSCR_drop : (simulated) pSCR O2 drop | 1737 // sim_/real_pSCR_drop : (simulated) pSCR O2 drop |
1666 // pres_surface : surface pressure [bar] | 1738 // pres_surface : surface pressure [bar] |
1667 // char_I_const_ppO2 : ppO2 reported from sensors or setpoint [cbar] | 1739 // char_I_const_ppO2 : ppO2 reported from sensors or setpoint [cbar] |
1668 // float_deco_distance : safety factor, additional depth below stop depth [bar] - not used any more | |
1669 // ppWater : water-vapor pressure inside respiratory tract [bar] | 1740 // ppWater : water-vapor pressure inside respiratory tract [bar] |
1670 // | 1741 // |
1671 // Output: ppN2 : respired N2 partial pressure | 1742 // Output: ppN2 : respired N2 partial pressure |
1672 // ppHe : respired He partial pressure | 1743 // ppHe : respired He partial pressure |
1673 // char_ppO2 : breathed ppO2 in %, used for CNS calculation | 1744 // char_ppO2 : breathed ppO2 in %, used for CNS calculation |
1741 } | 1812 } |
1742 | 1813 |
1743 //---- OC, CCR and Bailout Mode Gas Calculations ----------------------------------- | 1814 //---- OC, CCR and Bailout Mode Gas Calculations ----------------------------------- |
1744 | 1815 |
1745 // calculate ppO2 of pure oxygen | 1816 // calculate ppO2 of pure oxygen |
1746 O2_ppO2 = calc_pres_respiration - ppWater; | 1817 ppO2_O2 = calc_pres_respiration - ppWater; |
1747 | 1818 |
1748 // capture failure condition in case real_pres_respiration is < ppWater (should never happen...) | 1819 // capture failure condition in case real_pres_respiration is < ppWater (should never happen...) |
1749 if( O2_ppO2 < 0.0 ) O2_ppO2 = 0.0; | 1820 if( ppO2_O2 < 0.0 ) ppO2_O2 = 0.0; |
1750 | 1821 |
1751 // calculate ppO2 of the pure gas (OC, diluent) | 1822 // calculate ppO2 of the pure gas (OC, diluent) |
1752 OC_ppO2 = O2_ppO2 * calc_O2_ratio; | 1823 ppO2_OC = ppO2_O2 * calc_O2_ratio; |
1753 | 1824 |
1754 #ifdef _ccr_pscr | 1825 #ifdef _ccr_pscr |
1755 | 1826 |
1756 // calculate pSCR ppO2 | 1827 // calculate pSCR ppO2 |
1757 pSCR_ppO2 = OC_ppO2 - calc_pSCR_drop; | 1828 ppO2_pSCR = ppO2_OC - calc_pSCR_drop; |
1758 | 1829 |
1759 // capture failure condition in case pSCR_ppO2 becomes negative | 1830 // capture failure condition in case ppO2_pSCR becomes negative |
1760 if( pSCR_ppO2 < 0.0 ) pSCR_ppO2 = 0.0; | 1831 if( ppO2_pSCR < 0.0 ) ppO2_pSCR = 0.0; |
1761 | 1832 |
1762 | 1833 |
1763 //---- Loop modes : adjust ppN2 and ppHe for change in ppO2 due to setpoint (CCR) or drop (pSCR) --- | 1834 //---- Loop modes : adjust ppN2 and ppHe for change in ppO2 due to setpoint (CCR) or drop (pSCR) --- |
1764 if( status & MODE_LOOP ) | 1835 if( status & MODE_LOOP ) |
1765 { | 1836 { |
1781 // check which kind of loop we are on | 1852 // check which kind of loop we are on |
1782 if( status & MODE_PSCR ) | 1853 if( status & MODE_PSCR ) |
1783 { | 1854 { |
1784 //---- pSCR Mode -------------------------------------------------------------------------- | 1855 //---- pSCR Mode -------------------------------------------------------------------------- |
1785 | 1856 |
1786 // Use the sensor value if available, but only in real tissue context! | 1857 // Use the sensor value if available and in real tissue context, else use calculated ppO2. |
1787 // In all other cases use calculated ppO2. | 1858 ppO2 = ( char_I_const_ppO2 && (tissue_increment & TISSUE_SELECTOR)) ? const_ppO2 : ppO2_pSCR; |
1788 if ( char_I_const_ppO2 && (tissue_increment & TISSUE_SELECTOR)) ppO2 = const_ppO2; | |
1789 else ppO2 = pSCR_ppO2; | |
1790 } | 1859 } |
1791 else | 1860 else |
1792 { | 1861 { |
1793 //---- CCR Mode --------------------------------------------------------------------------- | 1862 //---- CCR Mode --------------------------------------------------------------------------- |
1794 | 1863 |
1819 #endif // _ccr_pscr | 1888 #endif // _ccr_pscr |
1820 { | 1889 { |
1821 //---- OC mode --------------------------------------------------------------------------------- | 1890 //---- OC mode --------------------------------------------------------------------------------- |
1822 | 1891 |
1823 // breathed ppO2 is ppO2 of pure gas | 1892 // breathed ppO2 is ppO2 of pure gas |
1824 ppO2 = OC_ppO2; | 1893 ppO2 = ppO2_OC; |
1825 } | 1894 } |
1826 | 1895 |
1827 | 1896 |
1828 //---- derive char_ppO2 in [cbar], used for calculating CNS% --------------------------------------- | 1897 //---- derive char_ppO2 in [cbar], used for calculating CNS% --------------------------------------- |
1829 | 1898 |
1831 else if ( ppO2 >= 2.545 ) char_ppO2 = 255; | 1900 else if ( ppO2 >= 2.545 ) char_ppO2 = 255; |
1832 else char_ppO2 = (unsigned char)(100 * ppO2 + 0.5); | 1901 else char_ppO2 = (unsigned char)(100 * ppO2 + 0.5); |
1833 | 1902 |
1834 | 1903 |
1835 //---- calculate ppN2 and ppHe --------------------------------------------------------------------- | 1904 //---- calculate ppN2 and ppHe --------------------------------------------------------------------- |
1836 | |
1837 // add deco safety distance when working on simulated tissues - not used any more | |
1838 // if( !(tissue_increment & TISSUE_SELECTOR) ) calc_pres_respiration += float_deco_distance; | |
1839 | 1905 |
1840 // compute ppN2 and ppHe, capture potential failure conditions first: | 1906 // compute ppN2 and ppHe, capture potential failure conditions first: |
1841 if( calc_pres_respiration > ppWater ) | 1907 if( calc_pres_respiration > ppWater ) |
1842 { | 1908 { |
1843 // subtract water vapor pressure | 1909 // subtract water vapor pressure |
1910 // initialize CNS values | 1976 // initialize CNS values |
1911 int_O_CNS_norm = 0 + INT_FLAG_INVALID; | 1977 int_O_CNS_norm = 0 + INT_FLAG_INVALID; |
1912 int_O_CNS_alt = 0 + INT_FLAG_INVALID; | 1978 int_O_CNS_alt = 0 + INT_FLAG_INVALID; |
1913 | 1979 |
1914 // initialize NDL times | 1980 // initialize NDL times |
1915 char_O_NDL_norm = 240; | 1981 int_O_NDL_norm = 240; |
1916 char_O_NDL_alt = 240; | 1982 int_O_NDL_alt = 240; |
1917 | 1983 |
1918 // initialize ascent times | 1984 // initialize stop times |
1985 int_O_TST_norm = 0; | |
1986 int_O_TST_alt = 0 + INT_FLAG_INVALID + INT_FLAG_NOT_COMPUTED_YET + INT_FLAG_ZERO; | |
1987 | |
1988 | |
1989 // initialize ascent / return times | |
1919 int_O_TTS_norm = 0; | 1990 int_O_TTS_norm = 0; |
1920 int_O_TTS_alt = 0 + INT_FLAG_INVALID + INT_FLAG_NOT_COMPUTED_YET; | 1991 int_O_TTS_alt = 0 + INT_FLAG_INVALID + INT_FLAG_NOT_COMPUTED_YET; |
1921 | 1992 |
1922 #ifdef _rx_functions | 1993 #ifdef _rx_functions |
1923 // clear TR values | 1994 // clear TR values |
1949 // CNS_fraction_real internal CNS value | 2020 // CNS_fraction_real internal CNS value |
1950 // int_O_CNS_current current CNS value | 2021 // int_O_CNS_current current CNS value |
1951 // int_O_CNS_norm CNS value at end of normal dive plan | 2022 // int_O_CNS_norm CNS value at end of normal dive plan |
1952 // int_O_CNS_alt CNS value at end of alternative dive plan | 2023 // int_O_CNS_alt CNS value at end of alternative dive plan |
1953 // char_O_deco_warnings deco warnings vector | 2024 // char_O_deco_warnings deco warnings vector |
1954 // char_O_NDL_norm remaining NDL time in normal dive plan | 2025 // int_O_NDL_norm remaining NDL time in normal dive plan |
1955 // char_O_NDL_alt remaining NDL time in alternative dive plan | 2026 // int_O_NDL_alt remaining NDL time in alternative dive plan |
1956 // int_O_TTS_norm ascent time (TTS) in normal dive plan | 2027 // int_O_TTS_norm ascent time (TTS) in normal dive plan |
1957 // int_O_TTS_alt ascent time (TTS) in alternative dive plan | 2028 // int_O_TTS_alt ascent time (TTS) in alternative dive plan |
1958 // int_O_lead_supersat supersaturation of the leading tissue | 2029 // int_O_lead_supersat supersaturation of the leading tissue |
1959 // | 2030 // |
1960 static void clear_tissue(void) | 2031 static void clear_tissue(void) |
1972 // reset tissue pressures | 2043 // reset tissue pressures |
1973 real_pres_tissue_He[ci] = 0.0; // He | 2044 real_pres_tissue_He[ci] = 0.0; // He |
1974 real_pres_tissue_N2[ci] = N2_equilibrium; // N2 | 2045 real_pres_tissue_N2[ci] = N2_equilibrium; // N2 |
1975 | 2046 |
1976 // reset tissue pressures for scaled tissue graphics | 2047 // reset tissue pressures for scaled tissue graphics |
1977 char_O_tissue_pres_He[ci] = 0; // He | 2048 char_O_tissue_pres_He[ci] = 0; // He |
1978 char_O_tissue_pres_N2[ci] = 10; // N2 | 2049 char_O_tissue_pres_N2[ci] = 10; // N2 |
1979 char_O_tissue_pressure[ci] = 10; // combined | 2050 char_O_tissue_pressure[ci] = 10; // combined |
1980 } | 2051 } |
1981 | 2052 |
1982 // reset CNS values | 2053 // reset CNS values |
1983 CNS_fraction_real = 0.0; | 2054 CNS_fraction_real = 0.0; |
1984 int_O_CNS_current = int_O_CNS_norm = int_O_CNS_alt = 0; | 2055 int_O_CNS_current = int_O_CNS_norm = int_O_CNS_alt = 0; |
1985 | 2056 |
1986 // reset some more vars to their defaults | 2057 // reset some more vars to their defaults |
1987 char_O_NDL_norm = 240; | 2058 int_O_NDL_norm = 240; |
1988 char_O_NDL_alt = 240; | 2059 int_O_NDL_alt = 240; |
1989 int_O_TTS_norm = 0; | 2060 int_O_TST_norm = 0; |
1990 int_O_TTS_alt = 0; | 2061 int_O_TST_alt = 0 + INT_FLAG_ZERO; |
1991 int_O_lead_supersat = 0; | 2062 int_O_TTS_norm = 0; |
2063 int_O_TTS_alt = 0; | |
2064 int_O_lead_supersat = 0; | |
1992 | 2065 |
1993 // reset all warning and info flags | 2066 // reset all warning and info flags |
1994 char_O_deco_warnings = 0; | 2067 char_O_deco_warnings = 0; |
1995 char_O_deco_info = 0; | 2068 char_O_deco_info = 0; |
1996 } | 2069 } |
1997 | 2070 |
1998 | 2071 |
1999 ////////////////////////////////////////////////////////////////////////////// | 2072 ////////////////////////////////////////////////////////////////////////////// |
2000 // Deco engine main code | 2073 // Deco engine main code |
2007 // char_I_sim_advance_time mailbox for bottom time incrementing | 2080 // char_I_sim_advance_time mailbox for bottom time incrementing |
2008 // | 2081 // |
2009 // char_I_SAC_work gas usage rate during working phase in l/min | 2082 // char_I_SAC_work gas usage rate during working phase in l/min |
2010 // char_I_SAC_deco gas usage rate during deco stops phase in l/min | 2083 // char_I_SAC_deco gas usage rate during deco stops phase in l/min |
2011 // | 2084 // |
2012 // char_I_deco_model selector for GF extension | 2085 // char_I_model selector for GF extension |
2013 // char_I_ascent_speed ascent speed | |
2014 // char_I_saturation_multiplier safety factor for tissue saturation | 2086 // char_I_saturation_multiplier safety factor for tissue saturation |
2015 // char_I_desaturation_multiplier safety factor for tissue desaturation | 2087 // char_I_desaturation_multiplier safety factor for tissue desaturation |
2016 // | 2088 // |
2017 // char_I_pressure_gas[] amount of gas available for ascent in bar | 2089 // char_I_pressure_gas[] amount of gas available for ascent / cave return in bar |
2018 // int_I_pressure_drop[] pressure drop used to calculate SAC rate | 2090 // int_I_pressure_drop[] pressure drop used to calculate SAC rate |
2019 // char_I_gas_avail_size[] size of the tanks in liters | 2091 // char_I_gas_avail_size[] size of the tanks in liters |
2020 // | 2092 // |
2021 // Output: int_O_O2_ppO2 partial pressure of pure O2 at current depth | 2093 // Output: int_O_O2_ppO2 partial pressure of pure O2 at current depth |
2022 // int_O_pure_ppO2 partial pressure of O2 in gas at current depth | 2094 // int_O_pure_ppO2 partial pressure of O2 in gas at current depth |
2025 // | 2097 // |
2026 // char_O_deco_status deco engine computations status | 2098 // char_O_deco_status deco engine computations status |
2027 // char_O_deco_info deco engine information vector | 2099 // char_O_deco_info deco engine information vector |
2028 // char_O_deco_warnings deco engine warnings vector | 2100 // char_O_deco_warnings deco engine warnings vector |
2029 // | 2101 // |
2030 // char_O_NDL_norm remaining NDL time in normal dive plan | 2102 // int_O_NDL_norm remaining NDL time in normal dive plan |
2031 // char_O_NDL_alt remaining NDL time in alternative dive plan | 2103 // int_O_NDL_alt remaining NDL time in alternative dive plan |
2032 // int_O_TTS_norm ascent time (TTS) in normal dive plan | 2104 // int_O_TTS_norm ascent time (TTS) in normal dive plan |
2033 // int_O_TTS_alt ascent time (TTS) in alternative dive plan | 2105 // int_O_TTS_alt ascent time (TTS) in alternative dive plan |
2034 // int_O_CNS_norm CNS value at end of normal dive plan | 2106 // int_O_CNS_norm CNS value at end of normal dive plan |
2035 // int_O_CNS_alt CNS value at end of alternative dive plan | 2107 // int_O_CNS_alt CNS value at end of alternative dive plan |
2036 // | 2108 // |
2037 // int_O_gas_need_vol calculated gas volumes needed for ascent | 2109 // int_O_gas_need_vol[] calculated gas volumes needed for ascent / cave return |
2038 // int_O_gas_need_pres calculated gas pressures needed for ascent | 2110 // int_O_gas_need_pres[] calculated gas pressures needed for ascent / cave return |
2039 // | 2111 // |
2040 // int_O_SAC_measured measured surface air consumption (SAC) rate in l/min | 2112 // int_O_SAC_measured measured surface air consumption (SAC) rate in l/min |
2041 // | 2113 // |
2042 // Modified: int_IO_pressure_value[] warning flags added to pressure reading 1 & 2 | 2114 // Modified: int_IO_pressure_value[] warning flags added to pressure reading 1 & 2 |
2043 // int_IO_pressure_need[] pressure needs to pressure reading 1 & 2 | 2115 // int_IO_pressure_need[] pressure needs to pressure reading 1 & 2 |
2046 { | 2118 { |
2047 overlay unsigned short int_ppO2_min; | 2119 overlay unsigned short int_ppO2_min; |
2048 overlay unsigned short int_ppO2_max_warn; | 2120 overlay unsigned short int_ppO2_max_warn; |
2049 overlay unsigned short int_ppO2_max_att; | 2121 overlay unsigned short int_ppO2_max_att; |
2050 overlay unsigned short int_ppO2_max_dil; | 2122 overlay unsigned short int_ppO2_max_dil; |
2051 overlay float EAD; | 2123 overlay float EAD_pres; |
2052 overlay float END; | 2124 overlay float END_pres; |
2053 | 2125 |
2054 //============================================================================================= | 2126 //============================================================================================= |
2055 | 2127 |
2056 // | 2128 // |
2057 //--- Setup Part --------------------------------------------------------------------------------- | 2129 //--- Setup Part --------------------------------------------------------------------------------- |
2177 | 2249 |
2178 // update the CNS value for the real tissues | 2250 // update the CNS value for the real tissues |
2179 calc_CNS(); | 2251 calc_CNS(); |
2180 | 2252 |
2181 // calculate ceiling (at GF_high or 100%) and leading tissue supersaturation | 2253 // calculate ceiling (at GF_high or 100%) and leading tissue supersaturation |
2182 if ( char_I_deco_model ) calc_limit(GF_high); // GF factors enabled | 2254 if ( char_I_model ) calc_limit(GF_high); // GF factors enabled |
2183 else calc_limit( 1.0 ); // classic Buhlmann | 2255 else calc_limit( 1.0 ); // classic Buhlmann |
2184 | 2256 |
2185 // convert the ceiling value to integer | 2257 // convert the ceiling value to integer |
2186 convert_ceiling_for_display(); | 2258 convert_ceiling_for_display(); |
2187 | 2259 |
2188 // convert the saturation value of the leading tissue to integer | 2260 // convert the saturation value of the leading tissue to integer |
2201 ) | 2273 ) |
2202 #endif | 2274 #endif |
2203 { | 2275 { |
2204 //---- Calculate and Export EAD and END ------------------------------------------------------ | 2276 //---- Calculate and Export EAD and END ------------------------------------------------------ |
2205 | 2277 |
2206 // calculate EAD (Equivalent Air Depth): equivalent depth for the same N2 level with plain air | 2278 // calculate EAD (Equivalent Air Depth) as pressure in [bar]: |
2207 EAD = (ppN2 / 0.7902 + ppWater - pres_surface) * BAR_TO_METER; | 2279 // equivalent depth for the same N2 level with plain air |
2208 | 2280 EAD_pres = ppN2 / 0.7902 + ppWater - pres_surface; |
2209 // calculate END (Equivalent Narcotic Depth): here O2 is treated as narcotic, too | 2281 |
2210 // Source cited: The Physiology and Medicine of Diving by Peter Bennett and David Elliott, | 2282 // calculate END (Equivalent Narcotic Depth) as pressure in [bar]: |
2211 // 4th edition, 1993, W.B.Saunders Company Ltd, London. | 2283 // as before, but with O2 treated as narcotic, too |
2212 END = (real_pres_respiration - ppHe - pres_surface) * BAR_TO_METER; | 2284 // Source: The Physiology and Medicine of Diving by Peter Bennett and David Elliott, |
2213 | 2285 // 4th edition, 1993, W.B.Saunders Company Ltd, London. |
2214 // export EAD | 2286 END_pres = real_pres_respiration - ppHe - pres_surface; |
2215 float_value = EAD; convert_float_to_char(); char_O_EAD = char_value; | 2287 |
2216 | 2288 |
2217 // export END | 2289 // export EAD, factor 10 is because conversion delivers in [cbar] but we need [mbar] |
2218 float_value = END; convert_float_to_char(); char_O_END = char_value; | 2290 float_value = EAD_pres; convert_float_to_int(); int_O_EAD_pres = int_value * 10; |
2291 | |
2292 // export END, factor 10 is because conversion delivers in [cbar] but we need [mbar] | |
2293 float_value = END_pres; convert_float_to_int(); int_O_END_pres = int_value * 10; | |
2219 | 2294 |
2220 | 2295 |
2221 //---- Compute ppO2 Values in [cbar] --------------------------------------------------------- | 2296 //---- Compute ppO2 Values in [cbar] --------------------------------------------------------- |
2222 | 2297 |
2223 float_value = ppO2; convert_float_to_int(); int_O_breathed_ppO2 = int_value; // breathed gas | 2298 float_value = ppO2; convert_float_to_int(); int_O_breathed_ppO2 = int_value; // breathed gas |
2224 #ifdef _ccr_pscr | 2299 #ifdef _ccr_pscr |
2225 float_value = O2_ppO2; convert_float_to_int(); int_O_O2_ppO2 = int_value; // pure oxygen | 2300 float_value = ppO2_O2; convert_float_to_int(); int_O_O2_ppO2 = int_value; // pure oxygen |
2226 float_value = OC_ppO2; convert_float_to_int(); int_O_pure_ppO2 = int_value; // pure gas | 2301 float_value = ppO2_OC; convert_float_to_int(); int_O_pure_ppO2 = int_value; // pure gas |
2227 float_value = pSCR_ppO2; convert_float_to_int(); int_O_pSCR_ppO2 = int_value; // pSCR calculated | 2302 float_value = ppO2_pSCR; convert_float_to_int(); int_O_pSCR_ppO2 = int_value; // pSCR calculated |
2228 #endif | 2303 #endif |
2229 | 2304 |
2230 | 2305 |
2231 //---- Set/Clear Deco Mode ------------------------------------------------------------------ | 2306 //---- Set/Clear Deco Mode ------------------------------------------------------------------ |
2232 | 2307 |
2234 // deco mode is set | 2309 // deco mode is set |
2235 // AND we are deeper than 7 meters below the deepest deco stop | 2310 // AND we are deeper than 7 meters below the deepest deco stop |
2236 // (7 meters chosen as to be 2 stop depth intervals plus 1 additional meter below) | 2311 // (7 meters chosen as to be 2 stop depth intervals plus 1 additional meter below) |
2237 if ( ( deco_info & DECO_MODE ) > 0 ) | 2312 if ( ( deco_info & DECO_MODE ) > 0 ) |
2238 if ( ( char_depth_real ) > char_O_deco_depth[0] + 7 ) | 2313 if ( ( char_depth_real ) > char_O_deco_depth[0] + 7 ) |
2239 deco_info &= ~DECO_MODE; | 2314 deco_info &= ~DECO_MODE; |
2240 | 2315 |
2241 // Set the deco mode flag if: | 2316 // Set the deco mode flag if: |
2242 // deco mode is not set | 2317 // deco mode is not set |
2243 // AND breathing an OC deco gas (gas type 3) | 2318 // AND breathing an OC deco gas (gas type 3) |
2244 // OR breathing a gas or diluent that officially is disabled (type 0) | 2319 // OR breathing a gas or diluent that officially is disabled (type 0) |
2245 // OR there is a deco stop | 2320 // OR there is a deco stop |
2321 // | |
2322 // Remark: when breathing a gas, its lost & staged flags are cleared | |
2323 // | |
2246 if ( ( deco_info & DECO_MODE ) == 0 ) | 2324 if ( ( deco_info & DECO_MODE ) == 0 ) |
2247 if ( ( char_I_current_gas_type == 3 ) | 2325 if ( ( char_I_current_gas_type == 3 ) |
2248 || ( char_I_current_gas_type == 0 ) | 2326 || ( char_I_current_gas_type == 0 ) |
2249 || ( char_O_deco_depth[0] > 0 ) | 2327 || ( char_O_deco_depth[0] > 0 ) |
2250 ) | 2328 ) |
2251 deco_info |= DECO_MODE; | 2329 deco_info |= DECO_MODE; |
2252 | 2330 |
2253 | 2331 |
2254 //---- Compute ppO2 Warnings ------------------------------------------------------------------ | 2332 //---- Compute ppO2 Warnings ------------------------------------------------------------------ |
2255 | 2333 |
2256 // compute conditional min value | 2334 // compute conditional min value |
2275 #ifdef _ccr_pscr | 2353 #ifdef _ccr_pscr |
2276 // default value for the upper diluent ppO2 warning threshold is the upper warning threshold | 2354 // default value for the upper diluent ppO2 warning threshold is the upper warning threshold |
2277 int_ppO2_max_dil = int_ppO2_max_warn; | 2355 int_ppO2_max_dil = int_ppO2_max_warn; |
2278 | 2356 |
2279 // when enabled and in CCR mode, the upper diluent warning threshold gets adjust according to the current setpoint | 2357 // when enabled and in CCR mode, the upper diluent warning threshold gets adjust according to the current setpoint |
2280 if( char_I_dil_ppO2_check ) | 2358 if( char_I_dil_check ) |
2281 if( (main_status & MODE_MASK) == MODE_CCR ) | 2359 if( (main_status & MODE_MASK) == MODE_CCR ) |
2282 { | 2360 { |
2283 overlay unsigned short max_dil; | 2361 overlay unsigned short max_dil; |
2284 | 2362 |
2285 // The upper diluent ppO2 threshold is ppO2_GAP_TO_SETPOINT below the setpoint... | 2363 // The upper diluent ppO2 threshold is ppO2_GAP_TO_SETPOINT below the setpoint... |
2363 case PHASE_10_DIVE_INIT: | 2441 case PHASE_10_DIVE_INIT: |
2364 | 2442 |
2365 // initialize all output variables to defaults | 2443 // initialize all output variables to defaults |
2366 init_output_vars(); | 2444 init_output_vars(); |
2367 | 2445 |
2368 // safeguard input parameters that are constant during the course of the dive | |
2369 if( char_I_ascent_speed < 5 ) char_I_ascent_speed = 5; | |
2370 if( char_I_ascent_speed > 10 ) char_I_ascent_speed = 10; | |
2371 | |
2372 // convert input parameters to float numbers | |
2373 float_ascent_speed = 1.00 * char_I_ascent_speed; | |
2374 | |
2375 | |
2376 // initialize values that will be recalculated later on periodically | 2446 // initialize values that will be recalculated later on periodically |
2377 deco_warnings = 0; // reset all deco warnings | 2447 deco_warnings = 0; // reset all deco warnings |
2378 deco_info = 0; // reset all deco infos | 2448 deco_info = 0; // reset all deco infos |
2379 IBCD_tissue_vector = 0; // reset tissue IBCD vector | 2449 IBCD_tissue_vector = 0; // reset tissue IBCD vector |
2380 NDL_tissue_start_norm = 0; // initialize the tissue to start with when calculating normal NDL time | 2450 NDL_tissue_start_norm = 0; // initialize the tissue to start with when calculating normal NDL time |
2381 NDL_tissue_start_alt = 0; // initialize the tissue to start with when calculating alternative NDL time | 2451 NDL_tissue_start_alt = 0; // initialize the tissue to start with when calculating alternative NDL time |
2382 | 2452 |
2383 // enforce initialization of GF data on first cyclic initialization | 2453 // enforce initialization of GF data on first cyclic initialization |
2384 GF_high_last = 255; | 2454 GF_high_last = 255; |
2385 GF_low_last = 255; | 2455 GF_low_last = 255; |
2386 | 2456 |
2387 #ifdef _gas_contingency | 2457 |
2388 // shall check for gas pan out? | 2458 // calculate volumes available for each gas |
2389 if( char_I_gas_contingency ) | 2459 for( i = 0; i < NUM_GAS; i++ ) |
2390 { | 2460 { |
2391 overlay float reduction = 0.5 * (float)char_I_SAC_deco * (1.0 + (float)char_I_depth_last_deco / 10.0); | 2461 // total available volume = tank size * fill press, char_I_gas_avail_pres is in multiples of 10 bar |
2392 | 2462 gas_volume_avail[i] = (float)char_I_gas_avail_size[i] * (float)char_I_gas_avail_pres[i] * 10.0; |
2393 // YES - calculate volumes available for each gas | 2463 |
2394 for( i = 0; i < NUM_GAS; i++ ) | 2464 // attention threshold |
2395 { | 2465 gas_volume_atten[i] = gas_volume_avail[i] * GAS_NEEDS_ATTENTION; |
2396 // total available volume = tank size * fill press, char_I_gas_avail_pres is in multiples of 10 bar | 2466 } |
2397 gas_volume_avail[i] = (float)char_I_gas_avail_size[i] * (float)char_I_gas_avail_pres[i] * 10.0; | 2467 |
2398 | |
2399 // reduce total available volumes by due for 1/2 minute on last stop | |
2400 gas_volume_avail[i] -= reduction; | |
2401 } | |
2402 } | |
2403 #endif | |
2404 | |
2405 #ifdef _cave_mode | |
2406 char_I_backtrack_time = 0; //clear backtracking time (index to char_I_backtrack_depth) | |
2407 char_I_backtrack_depth = 0; //prime first entry with a depth of 0 meter | |
2408 #endif | |
2409 | 2468 |
2410 #ifdef _profiling | 2469 #ifdef _profiling |
2411 int_O_profiling_overrun_max = 0; | 2470 int_O_profiling_overrun_max = 0; |
2412 char_O_profiling_runs_norm = 0; | 2471 char_O_profiling_runs_norm = 0; |
2413 char_O_profiling_runs_alt = 0; | 2472 char_O_profiling_runs_alt = 0; |
2431 tissue_increment = 0; | 2490 tissue_increment = 0; |
2432 | 2491 |
2433 // clear the internal stops table | 2492 // clear the internal stops table |
2434 clear_deco_table(); | 2493 clear_deco_table(); |
2435 | 2494 |
2495 // clear deco stops info | |
2496 if( deco_status & CALC_NORM ) deco_info &= ~DECO_STOPS_NORM; | |
2497 else deco_info &= ~DECO_STOPS_ALT; | |
2498 | |
2436 // initialize the simulated tissues with the current state of the real tissues | 2499 // initialize the simulated tissues with the current state of the real tissues |
2437 for( i = 0; i < NUM_COMP; i++ ) | 2500 for( i = 0; i < NUM_COMP; i++ ) |
2438 { | 2501 { |
2439 sim_pres_tissue_N2[i] = real_pres_tissue_N2[i]; | 2502 sim_pres_tissue_N2[i] = real_pres_tissue_N2[i]; |
2440 sim_pres_tissue_He[i] = real_pres_tissue_He[i]; | 2503 sim_pres_tissue_He[i] = real_pres_tissue_He[i]; |
2441 } | 2504 } |
2442 | 2505 |
2506 // initialize the gas types | |
2507 for( i = 0; i < NUM_GAS; i++ ) | |
2508 { | |
2509 deco_gas_type[i] = char_I_deco_gas_type[i]; | |
2510 } | |
2511 | |
2512 #ifdef _gas_contingency | |
2513 // if in gas contingency mode, | |
2514 // check if there are multiple tanks with the same gas | |
2515 // (or at least with the same change depth...) | |
2516 if( main_status & GAS_CONTINGENCY ) | |
2517 { | |
2518 for( i = 0; i < NUM_GAS; i++ ) | |
2519 { | |
2520 // default to no peer tanks existing | |
2521 peer_tank[i] = 0; | |
2522 | |
2523 // tank enabled? | |
2524 if( char_I_deco_gas_type[i] ) | |
2525 { | |
2526 // YES - check for peer tanks | |
2527 for( j = 0; j < NUM_GAS; j++ ) | |
2528 { | |
2529 // do not check a tank against itself | |
2530 if( i == j ) continue; | |
2531 | |
2532 // is the other tank also enabled and does it have the same change depth? | |
2533 if( char_I_deco_gas_type[j] & GAS_TYPE_MASK ) | |
2534 if( char_I_deco_gas_change[i] == char_I_deco_gas_change[j] ) | |
2535 { | |
2536 // YES - memorize it as a peer tank | |
2537 peer_tank[i] |= (1 << j); | |
2538 } | |
2539 } | |
2540 } | |
2541 } | |
2542 } | |
2543 #endif | |
2544 | |
2443 // initialize GF parameters if using GF model | 2545 // initialize GF parameters if using GF model |
2444 if( char_I_deco_model != 0 ) | 2546 if( char_I_model != 0 ) |
2445 { | 2547 { |
2446 // update GF parameters (GFs may have been switched between GF and aGF) | 2548 // update GF parameters (GFs may have been switched between GF and aGF) |
2447 if( (char_I_GF_Low_percentage != GF_low_last) || (char_I_GF_High_percentage != GF_high_last) ) | 2549 if( (char_I_GF_Low_percentage != GF_low_last) || (char_I_GF_High_percentage != GF_high_last) ) |
2448 { | 2550 { |
2449 // store new values in integer format | 2551 // store new values in integer format |
2454 GF_low = ( GF_low_last > 10 ) ? 0.01 * GF_low_last : 0.10 ; | 2556 GF_low = ( GF_low_last > 10 ) ? 0.01 * GF_low_last : 0.10 ; |
2455 GF_high = ( GF_high_last > GF_low_last ) ? 0.01 * GF_high_last : GF_low; | 2557 GF_high = ( GF_high_last > GF_low_last ) ? 0.01 * GF_high_last : GF_low; |
2456 | 2558 |
2457 | 2559 |
2458 // reset low depth references and slopes | 2560 // reset low depth references and slopes |
2459 GF_low_depth_norm = 0; | 2561 GF_depth_norm = 0; |
2460 GF_low_depth_alt = 0; | 2562 GF_depth_alt = 0; |
2461 GF_slope_norm = 0.0; | 2563 GF_slope_norm = 0.0; |
2462 GF_slope_alt = 0.0; | 2564 GF_slope_alt = 0.0; |
2463 } | 2565 } |
2464 | 2566 |
2465 // retrieve GF parameters for current calculation cycle | 2567 // retrieve GF parameters for current calculation cycle |
2466 if( deco_status & CALC_NORM ) | 2568 if( deco_status & CALC_NORM ) |
2467 { | 2569 { |
2468 GF_low_depth = GF_low_depth_norm; | 2570 GF_depth = GF_depth_norm; |
2469 GF_slope = GF_slope_norm; | 2571 GF_slope = GF_slope_norm; |
2470 } | 2572 } |
2471 else | 2573 else |
2472 { | 2574 { |
2473 GF_low_depth = GF_low_depth_alt; | 2575 GF_depth = GF_depth_alt; |
2474 GF_slope = GF_slope_alt; | 2576 GF_slope = GF_slope_alt; |
2475 } | 2577 } |
2476 } | 2578 } |
2477 | 2579 |
2478 // initialize the simulated CNS value with the current CNS value of the real tissues | 2580 // initialize the simulated CNS value with the current CNS value of the real tissues |
2479 CNS_fraction_sim = CNS_fraction_real; | 2581 CNS_fraction_sim = CNS_fraction_real; |
2480 | 2582 |
2481 // initialize the simulated depth with the current depth, | 2583 // initialize the simulated pressure with the current real pressure |
2482 // memorize current depth as start depth of the simulation | |
2483 sim_pres_respiration = real_pres_respiration; | 2584 sim_pres_respiration = real_pres_respiration; |
2484 char_depth_sim = char_depth_real; | 2585 |
2485 char_depth_sim_start = char_depth_real; | 2586 // initialize the simulated depth with the current real depth |
2587 char_depth_sim = char_depth_start = char_depth_real; | |
2588 | |
2589 // cache the gas/dil to start calculations with | |
2590 start_gas_num = char_I_current_gas_num; | |
2591 | |
2486 | 2592 |
2487 // Lookup the gas that is currently breathed with the real tissues and set it as | 2593 // Lookup the gas that is currently breathed with the real tissues and set it as |
2488 // the gas to be used with the simulated tissues, too. This gas will be used until | 2594 // the gas to be used with the simulated tissues, too. This gas will be used until |
2489 // gas_find_best()/gas_take_best() is invoked and switches to a better gas. | 2595 // gas_find_best()/gas_take_best() is invoked and switches to a better gas. |
2490 gas_take_current(); | 2596 gas_take_current(); |
2499 calc_alveolar_pressures(); | 2605 calc_alveolar_pressures(); |
2500 | 2606 |
2501 // initialize the no decompression limit (NDL) time to 240 minutes | 2607 // initialize the no decompression limit (NDL) time to 240 minutes |
2502 NDL_time = 240; | 2608 NDL_time = 240; |
2503 | 2609 |
2504 // initialize the total ascent time to 0 minutes | 2610 // clear the Total Time to Surface (TTS) and the Total Stops Time (TST) |
2505 ascent_time = 0; | 2611 TTS_time = 0; |
2612 TST_time = 0; | |
2506 | 2613 |
2507 // retrieve the tissue that had the shortest NDL time during last calculation | 2614 // retrieve the tissue that had the shortest NDL time during last calculation |
2508 NDL_tissue_start = ( deco_status & CALC_NORM ) ? NDL_tissue_start_norm : NDL_tissue_start_alt; | 2615 NDL_tissue_start = ( deco_status & CALC_NORM ) ? NDL_tissue_start_norm : NDL_tissue_start_alt; |
2509 | 2616 |
2510 // start calculating NDL time with the tissue that had the shortest NDL last time | 2617 // start calculating NDL time with the tissue that had the shortest NDL last time |
2511 NDL_tissue = NDL_tissue_start; | 2618 NDL_tissue = NDL_tissue_start; |
2512 NDL_tissue_lead = NDL_tissue_start; | 2619 NDL_tissue_lead = NDL_tissue_start; |
2513 | 2620 |
2514 // initialization for calculating the initial ascent | 2621 // initialization for convert_volume_to_pressure() |
2515 // start with 1 minute ascent steps when calculating the initial ascent | 2622 gas_needs_gas_index = 0; |
2516 fast = 1; | 2623 |
2517 | 2624 // tag gas needs as not calculated in fTTS mode by default |
2518 // initialization for convert_gas_needs_to_press() | 2625 deco_info &= ~GAS_NEEDS_fTTS; |
2519 gas_needs_gas_index = 0; | |
2520 | 2626 |
2521 // shall calculate gas needs? | 2627 // shall calculate gas needs? |
2522 if( main_status & CALC_VOLUME ) | 2628 if( main_status & CALC_VOLUME ) |
2523 { | 2629 { |
2524 // set the usage rate (SAC rate), starting with working part of the dive | 2630 // set the usage rate (SAC rate), starting with working part of the dive |
2536 int_O_pressure_need[1] = 0 + INT_FLAG_NOT_AVAIL; | 2642 int_O_pressure_need[1] = 0 + INT_FLAG_NOT_AVAIL; |
2537 } | 2643 } |
2538 #endif | 2644 #endif |
2539 } | 2645 } |
2540 | 2646 |
2647 | |
2648 #ifdef _cave_mode | |
2649 if( main_status & CAVE_MODE ) | |
2650 { | |
2651 // get the position of the first data set to start the backtracking from | |
2652 backtrack_index = char_I_backtrack_index; | |
2653 | |
2654 // get the first backtracking data set | |
2655 read_backtrack_data(); | |
2656 } | |
2657 #endif | |
2658 | |
2659 | |
2541 #ifdef _profiling | 2660 #ifdef _profiling |
2542 profiling_runs = 0; | 2661 profiling_runs = 0; |
2543 #endif | 2662 #endif |
2544 | 2663 |
2545 // The next calculation phase will | 2664 // The next calculation phase will |
2556 // | 2675 // |
2557 //---- extended Bottom Time --------------------------------------------------------------- | 2676 //---- extended Bottom Time --------------------------------------------------------------- |
2558 // | 2677 // |
2559 case PHASE_30_EXTENDED_BOTTOM_TIME: | 2678 case PHASE_30_EXTENDED_BOTTOM_TIME: |
2560 | 2679 |
2680 // tag gas needs as calculated in fTTS mode | |
2681 deco_info |= GAS_NEEDS_fTTS; | |
2682 | |
2561 // program interval on simulated tissues (flag bit 7 = 0) | 2683 // program interval on simulated tissues (flag bit 7 = 0) |
2562 tissue_increment = char_I_extra_time; | 2684 tissue_increment = char_I_extra_time; |
2563 | 2685 |
2564 // update the simulated tissues for tissue_increment (char_I_extra_time) minutes at depth, | 2686 // update the simulated tissues for tissue_increment (char_I_extra_time) minutes at depth, |
2565 // calc_alveolar_pressures() has already been called in cyclic initialization | 2687 // calc_alveolar_pressures() has already been called in cyclic initialization |
2583 case PHASE_40_BOTTOM_GAS_NEED: | 2705 case PHASE_40_BOTTOM_GAS_NEED: |
2584 | 2706 |
2585 // on gas 1-5 ? | 2707 // on gas 1-5 ? |
2586 if( sim_gas_current_num ) | 2708 if( sim_gas_current_num ) |
2587 { | 2709 { |
2588 // YES - set the bottom depth | 2710 // YES - take either the whole bottom time or just the fTTS/bailout extra time |
2589 gas_needs_depth = char_depth_sim_start; | |
2590 | |
2591 // take either the whole bottom time or just the fTTS/bailout extra time | |
2592 gas_needs_time = ( main_status & CALCULATE_BOTTOM ) ? char_I_bottom_time : char_I_extra_time; | 2711 gas_needs_time = ( main_status & CALCULATE_BOTTOM ) ? char_I_bottom_time : char_I_extra_time; |
2593 | 2712 |
2594 // calculate gas demand | 2713 // any time to do? |
2595 calc_due_by_depth_time_sac(); | 2714 if( gas_needs_time ) |
2596 | 2715 { |
2597 // take the result | 2716 // YES - set the bottom depth |
2598 gas_volume_need[sim_gas_current_num-1] = gas_needs_volume_due; | 2717 gas_needs_depth = char_depth_start; |
2718 | |
2719 // calculate required gas volume | |
2720 calc_required_volume(); | |
2721 | |
2722 // take the result | |
2723 gas_volume_need[sim_gas_current_num-1] = gas_needs_volume_due; | |
2724 } | |
2599 } | 2725 } |
2600 | 2726 |
2601 | 2727 |
2602 // the next calculation phase will calculate the NDL time | 2728 // the next calculation phase will calculate the NDL time |
2603 next_planning_phase = PHASE_50_NDL_TIME; | 2729 next_planning_phase = PHASE_50_NDL_TIME; |
2631 // set the tissue with the shortest NDL time found as | 2757 // set the tissue with the shortest NDL time found as |
2632 // the one to start with in the next calculation cycle | 2758 // the one to start with in the next calculation cycle |
2633 if( deco_status & CALC_NORM ) NDL_tissue_start_norm = NDL_tissue_lead; | 2759 if( deco_status & CALC_NORM ) NDL_tissue_start_norm = NDL_tissue_lead; |
2634 else NDL_tissue_start_alt = NDL_tissue_lead; | 2760 else NDL_tissue_start_alt = NDL_tissue_lead; |
2635 | 2761 |
2636 // done with calculating NDL time, set next calculation phase: | 2762 // done with calculating NDL time, next phase will calculate the ascent / cave return |
2637 // - calculate return and ascent in cave mode if configured, else | 2763 next_planning_phase = PHASE_70_ASCENT_OR_RETURN; |
2638 // - proceed with no-stop ascent if within NDL time, or | 2764 } |
2639 // - proceed with deco ascent if beyond NDL time. | 2765 |
2766 break; | |
2767 | |
2768 | |
2769 // | |
2770 //---- Ascent or Return (cave mode) ------------------------------------------------------- | |
2771 // | |
2772 case PHASE_70_ASCENT_OR_RETURN: | |
2773 | |
2774 { | |
2775 overlay unsigned char doing_deco_stop = 0; | |
2776 overlay unsigned char doing_gas_change = 0; | |
2777 | |
2778 | |
2779 // target simulated tissues, default is 1 minute interval | |
2780 tissue_increment = 1; | |
2781 | |
2782 // check if a deco stop is required: | |
2783 // - stays at the current depth if a stop is required, | |
2784 // - ascents to the next stop if possible, else | |
2785 // - ascents by 1 meter | |
2786 if( find_next_stop() ) | |
2787 { | |
2788 //---- stop required -------------------- | |
2789 | |
2790 // memorize doing a deco stop | |
2791 doing_deco_stop = 1; | |
2792 | |
2793 // set flag for deco stops found | |
2794 if( deco_status & CALC_NORM ) deco_info |= DECO_STOPS_NORM; | |
2795 else deco_info |= DECO_STOPS_ALT; | |
2796 | |
2797 // encountered a deco stop, so switch to deco usage rate (SAC deco) | |
2798 gas_needs_usage_rate = char_I_SAC_deco; | |
2799 | |
2800 // check if there is a better gas to switch to | |
2801 if( gas_find_best() ) | |
2802 { | |
2803 // YES - memorize doing a gas change | |
2804 doing_gas_change = 1; | |
2805 | |
2806 // take the gas | |
2807 gas_take_best(); | |
2808 | |
2809 // set the new calculation ratios for N2, He and O2 | |
2810 gas_set_ratios(); | |
2811 | |
2812 // add the gas change time to the stop time | |
2813 tissue_increment += char_I_gas_change_time; | |
2814 } | |
2815 | |
2816 // add the stop to an existing stop or add a new stop | |
2817 update_deco_table(tissue_increment); | |
2818 } | |
2819 else | |
2820 { | |
2821 //---- no stop required ----------------- | |
2822 | |
2823 // switch to 1/10 minute interval | |
2824 tissue_increment = 0; | |
2825 | |
2826 // memorize not doing a deco stop | |
2827 doing_deco_stop = 0; | |
2828 | |
2829 // check if there is a better gas to switch to, but only: | |
2830 // | |
2831 // if extended stops are activated OR if cave mode is enabled OR if in bailout | |
2832 // AND if the actual depth (char_depth_start) is deeper or at the change | |
2833 // depth of the better gas (change depth has not been passed yet) *) | |
2834 // AND if the depth of the last stop is above (shallower) or at the change | |
2835 // depth of the better gas (do not switch on final ascent) *) | |
2836 // | |
2837 // *) skipped when calculating in cave mode | |
2838 // | |
2839 // Attention: do not use a && formula over all 'if' terms, the | |
2840 // conditions need to be evaluated in the given order! | |
2841 // | |
2842 if( ( main_status & EXTENDED_STOPS ) | |
2843 || ( main_status & CAVE_MODE ) | |
2844 || ( deco_status & BAILOUT_MODE ) | |
2845 ) | |
2846 if( gas_find_best() ) | |
2640 #ifdef _cave_mode | 2847 #ifdef _cave_mode |
2641 if ( main_status & CAVE_MODE ) next_planning_phase = PHASE_60_CAVE_RETURN; | 2848 if( ( char_depth_start >= sim_gas_best_depth ) || ( main_status & CAVE_MODE ) ) |
2642 else | 2849 if( ( char_I_last_stop_depth <= sim_gas_best_depth ) || ( main_status & CAVE_MODE ) ) |
2643 #endif | 2850 #else |
2644 next_planning_phase = PHASE_70_OPEN_WATER_ASCENT; | 2851 if( ( char_depth_start >= sim_gas_best_depth ) ) |
2645 } | 2852 if( ( char_I_last_stop_depth <= sim_gas_best_depth ) ) |
2646 | 2853 #endif |
2647 break; | 2854 { |
2855 // YES - memorize doing a gas change | |
2856 doing_gas_change = 1; | |
2857 | |
2858 // take the gas | |
2859 gas_take_best(); | |
2860 | |
2861 // set the new calculation values for N2, He and O2 | |
2862 gas_set_ratios(); | |
2863 | |
2864 // create a stop lasting the gas change time | |
2865 tissue_increment = char_I_gas_change_time; | |
2866 | |
2867 // if in deco and run from the deco calculator: | |
2868 // create a stop for the gas change in the stops table | |
2869 if( !NDL_time && (deco_status & DECO_CALCULATOR_MODE) ) | |
2870 update_deco_table(tissue_increment); | |
2871 } | |
2872 | |
2873 } // stop / no stop | |
2648 | 2874 |
2649 | 2875 |
2650 #ifdef _cave_mode | 2876 #ifdef _cave_mode |
2651 // | 2877 // cave mode actions |
2652 //---- Cave Mode Return ------------------------------------------------------------------- | 2878 if( main_status & CAVE_MODE ) |
2653 // | |
2654 case PHASE_60_CAVE_RETURN: | |
2655 | |
2656 // TODO | |
2657 | |
2658 // the next calculation phase will gather all results | |
2659 next_planning_phase = PHASE_80_RESULTS; | |
2660 | |
2661 break; | |
2662 #endif | |
2663 | |
2664 | |
2665 // | |
2666 //---- Open Water Ascent ------------------------------------------------------------------ | |
2667 // | |
2668 case PHASE_70_OPEN_WATER_ASCENT: | |
2669 | |
2670 // program 1 minute interval on simulated tissues | |
2671 tissue_increment = 1; | |
2672 | |
2673 // memorize current gas in case there will be a gas change | |
2674 sim_gas_last_num = sim_gas_current_num; | |
2675 | |
2676 // find_next_stop(): | |
2677 // stays at the current stop depth, ascents to the next stop depth, or | |
2678 // ascents to the depth that is reachable within one minute of ascent | |
2679 // without needing to stop. | |
2680 // | |
2681 // return value : 1/true if a stop is required, else 0/false | |
2682 // char_depth_sim : current depth (depth achieved) | |
2683 // char_depth_last : last depth (depth we came from) | |
2684 // | |
2685 if( find_next_stop() ) | |
2686 { | |
2687 overlay unsigned char silent_stop = 0; | |
2688 overlay unsigned char gas_change = 0; | |
2689 | |
2690 //---- stop required -------------------- | |
2691 | |
2692 // check if there is a better gas to switch to | |
2693 if( gas_find_best() ) | |
2694 { | 2879 { |
2695 // YES - memorize it | 2880 // doing a deco stop? |
2696 gas_change = 1; | 2881 if( doing_deco_stop ) |
2697 | |
2698 // take the gas | |
2699 gas_take_best(); | |
2700 | |
2701 // set the new calculation ratios for N2, He and O2 | |
2702 gas_set_ratios(); | |
2703 | |
2704 // add the gas change time to the stop time | |
2705 tissue_increment += char_I_gas_change_time; | |
2706 | |
2707 // extended stops option enabled and | |
2708 // gas change depth deeper than the current depth ? | |
2709 if( main_status & EXTENDED_STOPS ) | |
2710 if( sim_gas_current_depth > char_depth_sim ) | |
2711 { | 2882 { |
2712 // YES - make a "silent" stop at the gas change depth | 2883 // YES - not moving, reset the 1/10 minute steps counter |
2713 // to figure in the gas change | 2884 backtrack_step_counter = 10; |
2714 silent_stop = 1; | |
2715 | |
2716 // locate the stop at the shallower one of the | |
2717 // gas change depth or the depth we came from | |
2718 char_depth_sim = (sim_gas_current_depth < char_depth_last) ? | |
2719 sim_gas_current_depth : char_depth_last; | |
2720 | |
2721 // calculate sim_pres_respiration for | |
2722 // the adjusted value of char_depth_sim | |
2723 calc_sim_pres_respiration(); | |
2724 | |
2725 // as we didn't travel the full distance, | |
2726 // account for the gas change time only | |
2727 tissue_increment = char_I_gas_change_time; | |
2728 | |
2729 // if run from the deco calculator, | |
2730 // put the gas change into the stops table or | |
2731 // abort deco calculation if the table is full | |
2732 if( deco_status & DECO_CALCULATOR_MODE ) | |
2733 if( !update_deco_table(tissue_increment) ) | |
2734 next_planning_phase = PHASE_80_RESULTS; | |
2735 } | 2885 } |
2736 } // better gas | 2886 else |
2737 | 2887 { |
2738 | 2888 // NO - on the move, switch back to SAC work |
2739 // if the stop is not a silent one, | 2889 gas_needs_usage_rate = char_I_SAC_work; |
2740 // add the stop to an existing stop or add a new stop, | 2890 |
2741 // or abort deco calculation if the deco table is full | 2891 // - decrement the 1/10 minute steps counter if not already zero |
2742 if( !silent_stop ) | 2892 if( backtrack_step_counter ) backtrack_step_counter--; |
2743 if( !update_deco_table(tissue_increment) ) | 2893 |
2744 next_planning_phase = PHASE_80_RESULTS; | 2894 // - target backtracking depth reached? |
2745 | 2895 if( char_depth_sim == backtrack_target_depth ) |
2896 { | |
2897 // YES - on target depth | |
2898 | |
2899 // target depth reached within first 1/10 minute? | |
2900 if( backtrack_step_counter == 9 ) | |
2901 { | |
2902 // YES - will not change depth any more while remaining 9/10 of | |
2903 // the minute, so can do the full full minute in one step | |
2904 tissue_increment = 1; | |
2905 backtrack_step_counter = 0; | |
2906 } | |
2907 | |
2908 // on the move for a minute or more now? | |
2909 // (incl. doing full minute in one step) | |
2910 if( backtrack_step_counter == 0 ) | |
2911 { | |
2912 // YES - get the data of the next backtracking data set | |
2913 read_backtrack_data(); | |
2914 } | |
2915 } | |
2916 } | |
2917 } // cave mode | |
2918 #endif | |
2746 | 2919 |
2747 // shall calculate gas needs? | 2920 // shall calculate gas needs? |
2748 if( main_status & CALC_VOLUME ) | 2921 if( main_status & CALC_VOLUME ) |
2749 { | 2922 { |
2750 // encountered a stop, so switch to deco usage rate (SAC deco) | 2923 overlay unsigned char index_last_gas = sim_gas_last_num-1; |
2751 gas_needs_usage_rate = char_I_SAC_deco; | 2924 overlay unsigned char index_curr_gas = sim_gas_current_num-1; |
2752 | 2925 |
2753 // set the depth for gas need calculation to the shallower one | 2926 #ifdef _cave_mode |
2754 // of the start depth (current real depth) and the stop depth | 2927 // in cave mode? |
2755 // (assumed depth to be) as we may be shallower than we should be | 2928 if( main_status & CAVE_MODE ) |
2756 gas_needs_depth = ( char_depth_sim_start < char_depth_sim ) ? | 2929 { |
2757 char_depth_sim_start : char_depth_sim; | 2930 // YES - set the depth for the gas needs calculation to the |
2758 | 2931 // simulated stop / on-the-move depth |
2759 // did a gas change occur and last gas is 1-5 and a gas change time set? | 2932 gas_needs_depth = char_depth_sim; |
2760 if( gas_change && sim_gas_last_num && char_I_gas_change_time ) | 2933 } |
2934 else | |
2935 #endif | |
2936 { | |
2937 // NO - set the depth for the gas needs calculation to the shallower | |
2938 // one of the actual depth (char_depth_start, current real depth) | |
2939 // and the simulated (stop) depth, as we may on purpose dive | |
2940 // shallower than we should to conserve on a low running gas supply | |
2941 gas_needs_depth = ( char_depth_start < char_depth_sim ) ? | |
2942 char_depth_start : char_depth_sim; | |
2943 } | |
2944 | |
2945 // doing a gas change and a gas change time is set? | |
2946 if( doing_gas_change && char_I_gas_change_time ) | |
2761 { | 2947 { |
2762 // YES - set time it takes for switching the gas | 2948 // YES - set time it takes for switching the gas |
2763 gas_needs_time = char_I_gas_change_time; | 2949 gas_needs_time = char_I_gas_change_time; |
2764 | 2950 |
2765 // calculate gas demand | 2951 // - calculate required gas volume for the gas change |
2766 calc_due_by_depth_time_sac(); | 2952 calc_required_volume(); |
2767 | 2953 |
2768 // add the demand to the overall demand on the last gas | 2954 // - add gas change demand to overall demand on the last gas |
2769 gas_volume_need[sim_gas_last_num-1] += gas_needs_volume_due; | 2955 if( sim_gas_last_num ) gas_volume_need[index_last_gas] += gas_needs_volume_due; |
2956 | |
2957 // - add gas change demand to overall demand on the current gas | |
2958 if( sim_gas_current_num ) gas_volume_need[index_curr_gas] += gas_needs_volume_due; | |
2770 } | 2959 } |
2771 | 2960 |
2772 // current gas is 1-5 ? | 2961 // current gas is 1-5 ? (i.e. not 0 aka gas 6) |
2773 if( sim_gas_current_num ) | 2962 if( sim_gas_current_num ) |
2774 { | 2963 { |
2775 // YES - time is 1 minute plus the gas change time (if set) | 2964 // set time: doing a deco stop -> 1 minute, encoded by tissue_increment = 1 |
2965 // no deco stop -> 1/10 minute, encoded by tissue_increment = 0 | |
2776 gas_needs_time = tissue_increment; | 2966 gas_needs_time = tissue_increment; |
2777 | 2967 |
2778 // calculate gas demand | 2968 // calculate required gas volume for the stop, ascent or travel |
2779 calc_due_by_depth_time_sac(); | 2969 calc_required_volume(); |
2780 | 2970 |
2781 // add the demand to the overall demand on the current gas | 2971 // add the demand to the overall demand on the current gas |
2782 gas_volume_need[sim_gas_current_num-1] += gas_needs_volume_due; | 2972 gas_volume_need[index_curr_gas] += gas_needs_volume_due; |
2783 } | 2973 } |
2784 } // gas need | 2974 |
2785 } | 2975 #ifdef _gas_contingency |
2786 else | 2976 // in gas contingency mode? |
2787 { | 2977 if( main_status & GAS_CONTINGENCY ) |
2788 //---- no stop required ----------------- | 2978 { |
2789 | 2979 overlay unsigned char all_peer_tanks_used_up = 1; |
2790 // switch to a better gas, but only: | 2980 |
2791 // | 2981 |
2792 // if extended stops are activated OR if in bailout OR if within NDL | 2982 // when doing a gas change and the there is an overdraw on the last gas, |
2793 // AND if the actual depth is below (deeper) or at the change depth of the | 2983 // then transfer the overdraw to the current gas if the current gas has |
2794 // better gas (switch depth has not been passed yet) | 2984 // an equal or deeper change depth than the overdrawn gas |
2795 // AND if the depth of the last stop is above (shallower) or at the change | 2985 if( doing_gas_change ) |
2796 // depth of the better gas (do not switch on final ascent) | 2986 if( gas_volume_need[index_last_gas] >= gas_volume_avail[index_last_gas] ) |
2797 // | 2987 if( char_I_deco_gas_change[index_last_gas] <= char_I_deco_gas_change[index_curr_gas] ) |
2798 // Attention: do not use a && formula over all 'if' terms, the | 2988 { |
2799 // conditions need to be evaluated in the given order! | 2989 overlay float overdraw; |
2800 // | 2990 |
2801 if( (main_status & EXTENDED_STOPS) || (deco_status & BAILOUT_MODE) || NDL_time ) | 2991 // calculate overdraw |
2802 if( gas_find_best() ) | 2992 overdraw = gas_volume_need[index_last_gas] - gas_volume_avail[index_last_gas]; |
2803 if( char_depth_real >= sim_gas_best_depth ) | 2993 |
2804 if( char_I_depth_last_deco <= sim_gas_best_depth ) | 2994 // transfer overdraw |
2995 gas_volume_need[index_last_gas] -= overdraw; | |
2996 gas_volume_need[index_curr_gas] += overdraw; | |
2997 | |
2998 // tag last gas as fully used up | |
2999 deco_gas_type[index_last_gas] |= GAS_FULLY_USED_UP; | |
3000 } | |
3001 | |
3002 // if there are peer tanks with the current gas (i.e. other tanks that have the same | |
3003 // change depth), check if there is at least one tank that is not yet fully used up | |
3004 if( peer_tank[index_curr_gas] ) | |
3005 { | |
3006 // scan all tanks | |
3007 for( i = 0; i < NUM_GAS; i++ ) | |
3008 { | |
3009 // check if | |
3010 // - tank is a peer tank | |
3011 // - tank is currently neither staged nor lost | |
3012 // - tank is not fully used up yet | |
3013 if( (peer_tank[index_curr_gas] & (1 << i) ) ) | |
3014 if( !(deco_gas_type[i] & GAS_AVAIL_MASK ) ) | |
3015 if( !(deco_gas_type[i] & GAS_FULLY_USED_UP) ) | |
3016 { | |
3017 // found a peer tank that is available and not fully used up yet | |
3018 all_peer_tanks_used_up = 0; | |
3019 } | |
3020 } | |
3021 } | |
3022 | |
3023 // select which threshold is sensible to check for | |
3024 if ( deco_gas_type[index_curr_gas] & GAS_FULLY_USED_UP ) | |
3025 { | |
3026 // already found as fully used up, nothing to do any more | |
3027 } | |
3028 else if( deco_gas_type[index_curr_gas] & GAS_NEARLY_USED_UP ) | |
3029 { | |
3030 // check for fully used up threshold | |
3031 if( gas_volume_need[index_curr_gas] >= gas_volume_avail[index_curr_gas] ) | |
3032 { | |
3033 // tag the gas as fully used up | |
3034 deco_gas_type[index_curr_gas] |= GAS_FULLY_USED_UP; | |
3035 | |
3036 // set warning if all peer tanks are fully used up, too | |
3037 if( all_peer_tanks_used_up ) deco_gas_type[index_curr_gas] |= GAS_NEED_WARNING; | |
3038 } | |
3039 } | |
3040 else | |
3041 { | |
3042 // check for nearly used up threshold | |
3043 if( gas_volume_need[index_curr_gas] >= gas_volume_atten[index_curr_gas] ) | |
3044 { | |
3045 // tag the gas as nearly used up | |
3046 deco_gas_type[index_curr_gas] |= GAS_NEARLY_USED_UP; | |
3047 | |
3048 // set attention if all peer tanks are already fully used up | |
3049 if( all_peer_tanks_used_up ) deco_gas_type[index_curr_gas] |= GAS_NEED_ATTENTION; | |
3050 } | |
3051 } | |
3052 } | |
3053 #endif // _gas_contingency | |
3054 | |
3055 } // gas needs | |
3056 | |
3057 // update the total stops time | |
3058 if( doing_deco_stop ) | |
2805 { | 3059 { |
2806 // YES - take the gas | 3060 // total stops time is counted in full minutes, add 1 minute |
2807 gas_take_best(); | 3061 TST_time += 1; |
2808 | 3062 } |
2809 // set the new calculation values for N2, He and O2 | 3063 |
2810 gas_set_ratios(); | 3064 // update the total ascent / cave return time |
2811 | 3065 if( tissue_increment ) |
2812 // set char_depth_sim to the gas change depth | |
2813 char_depth_sim = sim_gas_current_depth; | |
2814 | |
2815 // calculate sim_pres_respiration for | |
2816 // the adjusted value of char_depth_sim | |
2817 calc_sim_pres_respiration(); | |
2818 | |
2819 // as we didn't travel the full distance, | |
2820 // account for the gas change time only | |
2821 tissue_increment = char_I_gas_change_time; | |
2822 | |
2823 // if in deco and | |
2824 // if run from the deco calculator: | |
2825 // create a stop for the gas change in the stops table, | |
2826 // abort deco calculation if the deco table is full | |
2827 if( !NDL_time ) | |
2828 if( deco_status & DECO_CALCULATOR_MODE ) | |
2829 if( !update_deco_table(tissue_increment) ) | |
2830 next_planning_phase = PHASE_80_RESULTS; | |
2831 | |
2832 // shall calculate gas needs and gas change time is set? | |
2833 if( main_status & CALC_VOLUME ) | |
2834 if( char_I_gas_change_time ) | |
2835 { | |
2836 // YES - set depth to current depth | |
2837 gas_needs_depth = char_depth_sim; | |
2838 | |
2839 // set time it takes for switching the gas | |
2840 gas_needs_time = tissue_increment; | |
2841 | |
2842 // calculate gas demand | |
2843 calc_due_by_depth_time_sac(); | |
2844 | |
2845 // add gas demand to the overall demand on the new gas | |
2846 gas_volume_need[sim_gas_current_num-1] += gas_needs_volume_due; | |
2847 | |
2848 // was the last gas one of the gases 1-5 ? | |
2849 if( sim_gas_last_num ) | |
2850 { | |
2851 // YES - add the same demand to the overall demand on the last gas | |
2852 gas_volume_need[sim_gas_last_num-1] += gas_needs_volume_due; | |
2853 } | |
2854 } // gas switching needs | |
2855 } // gas switch | |
2856 | |
2857 // shall calculate gas needs and | |
2858 // last (or still current) gas is 1-5 ? | |
2859 if( main_status & CALC_VOLUME ) | |
2860 if( sim_gas_last_num ) | |
2861 { | 3066 { |
2862 // YES - compute distance traveled | 3067 // total time to surface is counted in 1/10 minutes, add 1 minute |
2863 gas_needs_depth = char_depth_last - char_depth_sim; | 3068 TTS_time += 10 * tissue_increment; |
2864 | 3069 } |
2865 // at least some positive distance traveled? | 3070 else |
2866 if( gas_needs_depth > 1 ) | 3071 { |
2867 { | 3072 // total time to surface is counted in 1/10 minutes, add 1/10 minute |
2868 // YES - set depth to average depth along the distance | 3073 TTS_time += 1; |
2869 gas_needs_depth += 1; | 3074 } |
2870 gas_needs_depth /= 2; | 3075 |
2871 gas_needs_depth += char_depth_sim; | 3076 } // overlay |
2872 | 3077 |
2873 // ascent time is 1 minute | 3078 // calculate absolute pressure at the current depth |
2874 gas_needs_time = 1; | 3079 sim_pres_respiration = (float)char_depth_sim * METER_TO_BAR + pres_surface; |
2875 | |
2876 // calculate gas demand | |
2877 calc_due_by_depth_time_sac(); | |
2878 | |
2879 // add to overall demand | |
2880 gas_volume_need[sim_gas_last_num-1] += gas_needs_volume_due; | |
2881 } | |
2882 } // gas travel needs | |
2883 | |
2884 } // stop / no stop | |
2885 | |
2886 // --- one or more minutes have passed by now --- | |
2887 | |
2888 // update the ascent time | |
2889 ascent_time += tissue_increment; | |
2890 | 3080 |
2891 // compute current ppO2, ppN2 and ppHe | 3081 // compute current ppO2, ppN2 and ppHe |
2892 calc_alveolar_pressures(); | 3082 calc_alveolar_pressures(); |
2893 | 3083 |
2894 // update the tissues | 3084 // update the tissues |
2895 calc_tissues(); | 3085 calc_tissues(); |
2896 | 3086 |
2897 // update the CNS value | 3087 // update the CNS |
2898 calc_CNS(); | 3088 calc_CNS(); |
2899 | 3089 |
2900 // finish stops calculation if the surface is reached | 3090 // finish stops calculation if the surface is reached or |
2901 if( char_depth_sim == 0 ) next_planning_phase = PHASE_80_RESULTS; | 3091 // if the deco table is full / calculations took too long |
3092 if( (char_depth_sim == 0) || (deco_warnings & DECO_WARNING_INCOMPLETE) ) | |
3093 next_planning_phase = PHASE_80_RESULTS; | |
2902 | 3094 |
2903 break; | 3095 break; |
2904 | 3096 |
2905 | 3097 |
2906 /// | 3098 /// |
2909 case PHASE_80_RESULTS: | 3101 case PHASE_80_RESULTS: |
2910 | 3102 |
2911 // convert the CNS value to integer | 3103 // convert the CNS value to integer |
2912 convert_sim_CNS_for_display(); | 3104 convert_sim_CNS_for_display(); |
2913 | 3105 |
3106 // normal or alternative plan? | |
2914 if( deco_status & CALC_NORM ) | 3107 if( deco_status & CALC_NORM ) |
2915 { | 3108 { |
2916 // export the integer CNS value | 3109 // normal plan - export the integer CNS value |
2917 int_O_CNS_norm = int_sim_CNS_fraction; | 3110 int_O_CNS_norm = int_sim_CNS_fraction; |
2918 } | 3111 } |
2919 else | 3112 else |
2920 { | 3113 { |
2921 // export the integer CNS value | 3114 // alternative plan - export the integer CNS value |
2922 int_O_CNS_alt = int_sim_CNS_fraction; | 3115 int_O_CNS_alt = int_sim_CNS_fraction; |
2923 } | 3116 } |
3117 | |
3118 // limit total time to surface to display max. and rescale to full minutes | |
3119 if( TTS_time < 9995 ) TTS_time = (TTS_time + 5) / 10; | |
3120 else TTS_time = 999 | INT_FLAG_INVALID; | |
2924 | 3121 |
2925 // The next calculation phase will | 3122 // The next calculation phase will |
2926 // - publish the stops table if in normal plan mode, | 3123 // - publish the stops table if in normal plan mode, |
2927 // - proceed with remaining results dependent on if within NDL, or | 3124 // - proceed with remaining results dependent on if within NDL, or |
2928 // - in deco | 3125 // - in deco |
2944 // When entering deco and the ceiling depth becomes > 0 but the | 3141 // When entering deco and the ceiling depth becomes > 0 but the |
2945 // deco calculation reveals no distinct deco stop yet because | 3142 // deco calculation reveals no distinct deco stop yet because |
2946 // the deco obligation will vanish during the ascent, create an | 3143 // the deco obligation will vanish during the ascent, create an |
2947 // artificial stop to signal that expedite surfacing ("popping | 3144 // artificial stop to signal that expedite surfacing ("popping |
2948 // up") is not allowed anymore. | 3145 // up") is not allowed anymore. |
2949 if( char_O_deco_depth[0] == 0 ) // simulated ascent reveals no required stops | 3146 if( char_O_deco_depth[0] == 0 ) // simulated ascent reveals no required stops |
2950 if( int_O_ceiling > 0 ) // real tissues have a ceiling | 3147 if( int_O_ceiling > 0 ) // real tissues have a ceiling |
2951 { | 3148 { |
2952 // set a pro forma stop at the configured last stop depth | 3149 // set a pro forma stop at the configured last stop depth |
2953 char_O_deco_depth[0] = char_I_depth_last_deco; | 3150 char_O_deco_depth[0] = char_I_last_stop_depth; |
2954 | 3151 |
2955 // set a stop time of 0 minutes, this will be displayed as "..'" | 3152 // set a stop time of 0 minutes, this will be displayed as "..'" |
2956 char_O_deco_time[0] = 0; | 3153 char_O_deco_time[0] = 0; |
2957 } | 3154 } |
2958 | |
2959 // update deco info vector | |
2960 if( char_O_deco_depth[0] ) deco_info |= DECO_STOPS; // set flag for deco stops found | |
2961 else deco_info &= ~DECO_STOPS; // clear flag for deco stops found | |
2962 | 3155 |
2963 // The next calculation phase will publish the main results dependent on being | 3156 // The next calculation phase will publish the main results dependent on being |
2964 // - within NDL, | 3157 // - within NDL, |
2965 // - in deco. | 3158 // - in deco. |
2966 if ( NDL_time ) next_planning_phase = PHASE_82_RESULTS_NDL; | 3159 if ( NDL_time ) next_planning_phase = PHASE_82_RESULTS_NDL; |
2972 /// | 3165 /// |
2973 //--- Results - within NDL ---------------------------------------------------------------- | 3166 //--- Results - within NDL ---------------------------------------------------------------- |
2974 // | 3167 // |
2975 case PHASE_82_RESULTS_NDL: | 3168 case PHASE_82_RESULTS_NDL: |
2976 | 3169 |
2977 // results to publish depend on normal or alternative plan | 3170 // normal or alternative plan? |
2978 if( deco_status & CALC_NORM ) | 3171 if( deco_status & CALC_NORM ) |
2979 { | 3172 { |
2980 // output the NDL time | 3173 // normal plan - output the NDL and TTS time |
2981 char_O_NDL_norm = NDL_time; | 3174 int_O_NDL_norm = NDL_time; |
2982 | 3175 int_O_TTS_norm = TTS_time; |
2983 // clear the normal ascent time | 3176 |
2984 int_O_TTS_norm = 0; | 3177 // clear the stops time |
3178 int_O_TST_norm = 0; | |
2985 } | 3179 } |
2986 else | 3180 else |
2987 { | 3181 { |
2988 // output the NDL time | 3182 // alternative plan - output the NDL time |
2989 char_O_NDL_alt = NDL_time; | 3183 int_O_NDL_alt = NDL_time; |
2990 | 3184 int_O_TTS_alt = TTS_time; |
2991 // clear the alternative ascent time | 3185 |
2992 int_O_TTS_alt = 0; | 3186 // clear the alternative TTS and stops time |
3187 int_O_TST_alt = 0 + INT_FLAG_ZERO; | |
2993 } | 3188 } |
2994 | 3189 |
2995 // The next calculation phase will | 3190 // The next calculation phase will |
2996 // - finish the calculation cycle if no gas needs calculation configured, else | 3191 // - convert the gas needs from volume to pressure if gas needs calculation is configured |
2997 // - calculate the gas needs pressures | 3192 // - else finish the calculation cycle |
2998 if ( !(main_status & CALC_VOLUME ) ) next_planning_phase = PHASE_90_FINISH; | 3193 if ( main_status & CALC_VOLUME ) next_planning_phase = PHASE_84_GAS_NEEDS_PRESSURES; |
2999 else next_planning_phase = PHASE_84_GAS_NEEDS_PRESSURES; | 3194 else next_planning_phase = PHASE_90_FINISH; |
3000 | 3195 |
3001 break; | 3196 break; |
3002 | 3197 |
3003 | 3198 |
3004 /// | 3199 /// |
3005 //--- Results - in Deco ------------------------------------------------------------------- | 3200 //--- Results - in Deco ------------------------------------------------------------------- |
3006 // | 3201 // |
3007 case PHASE_83_RESULTS_DECO: | 3202 case PHASE_83_RESULTS_DECO: |
3008 | 3203 |
3009 // limit ascent time to display max. | 3204 // limit total stops time to display max. |
3010 if( ascent_time > 999) ascent_time = 999; | 3205 if( TST_time > 999 ) TST_time = 999 | INT_FLAG_INVALID; |
3011 | 3206 |
3012 // tag ascent time as invalid if there is an overflow in the stops table | 3207 |
3013 if( deco_warnings & DECO_WARNING_INCOMPLETE ) ascent_time |= INT_FLAG_INVALID; | 3208 // normal or alternative plan? |
3014 | |
3015 // results to publish depend on normal or alternative plan | |
3016 if( deco_status & CALC_NORM ) | 3209 if( deco_status & CALC_NORM ) |
3017 { | 3210 { |
3018 // clear the normal NDL time | 3211 // normal plan - clear the normal NDL time |
3019 char_O_NDL_norm = 0; | 3212 int_O_NDL_norm = 0; |
3020 | 3213 |
3021 // export the ascent time | 3214 // export the TTS and total stops time |
3022 int_O_TTS_norm = ascent_time; | 3215 int_O_TTS_norm = TTS_time; |
3216 int_O_TST_norm = TST_time; | |
3023 } | 3217 } |
3024 else | 3218 else |
3025 { | 3219 { |
3026 // clear the alternative NDL time | 3220 // alternative plan - clear the alternative NDL time |
3027 char_O_NDL_alt = 0; | 3221 int_O_NDL_alt = 0; |
3028 | 3222 |
3029 // export the ascent time | 3223 // export the TTS and total stops time |
3030 int_O_TTS_alt = ascent_time; | 3224 int_O_TTS_alt = TTS_time; |
3225 int_O_TST_alt = TST_time; | |
3031 } | 3226 } |
3032 | 3227 |
3033 // The next calculation phase will | 3228 // The next calculation phase will |
3034 // - finish the calculation cycle if no gas needs calculation configured, else | 3229 // - convert the gas needs from volume to pressure if gas needs calculation is configured |
3035 // - calculate the gas needs along the ascent | 3230 // - else finish the calculation cycle |
3036 if ( !(main_status & CALC_VOLUME ) ) next_planning_phase = PHASE_90_FINISH; | 3231 if ( main_status & CALC_VOLUME ) next_planning_phase = PHASE_84_GAS_NEEDS_PRESSURES; |
3037 else next_planning_phase = PHASE_84_GAS_NEEDS_PRESSURES; | 3232 else next_planning_phase = PHASE_90_FINISH; |
3038 | 3233 |
3039 break; | 3234 break; |
3040 | 3235 |
3041 | 3236 |
3042 // | 3237 // |
3044 // | 3239 // |
3045 case PHASE_84_GAS_NEEDS_PRESSURES: | 3240 case PHASE_84_GAS_NEEDS_PRESSURES: |
3046 | 3241 |
3047 // convert required volume of the gas pointed to by gas_needs_gas_index | 3242 // convert required volume of the gas pointed to by gas_needs_gas_index |
3048 // into the respective pressure and set the flags | 3243 // into the respective pressure and set the flags |
3049 convert_gas_needs_to_press(); | 3244 convert_volume_to_pressure(); |
3050 | 3245 |
3051 // increment index to address next gas | 3246 // increment index to address next gas |
3052 gas_needs_gas_index++; | 3247 gas_needs_gas_index++; |
3053 | 3248 |
3054 // if all gases have been converted, advance to next calculation phase | 3249 // if all gases have been converted, advance to next calculation phase |
3250 #ifdef _cave_mode | |
3251 if( gas_needs_gas_index == NUM_GAS ) next_planning_phase = PHASE_85_GAS_NEEDS_CAVE; | |
3252 #else | |
3055 if( gas_needs_gas_index == NUM_GAS ) next_planning_phase = PHASE_90_FINISH; | 3253 if( gas_needs_gas_index == NUM_GAS ) next_planning_phase = PHASE_90_FINISH; |
3254 #endif | |
3056 | 3255 |
3057 break; | 3256 break; |
3257 | |
3258 | |
3259 #ifdef _cave_mode | |
3260 // | |
3261 //--- Results - tag Gas Needs as Cave or Open Water Mode ---------------------------------- | |
3262 // | |
3263 case PHASE_85_GAS_NEEDS_CAVE: | |
3264 | |
3265 // in cave mode? | |
3266 if( main_status & CAVE_MODE ) | |
3267 { | |
3268 // YES - tag gas needs as calculated in cave mode (return along recorded depth profile) | |
3269 deco_info |= GAS_NEEDS_CAVE; | |
3270 } | |
3271 else | |
3272 { | |
3273 // NO - tag gas needs as calculated in open water mode (vertical ascent) | |
3274 deco_info &= ~GAS_NEEDS_CAVE; | |
3275 } | |
3276 | |
3277 // advance to next calculation phase | |
3278 next_planning_phase = PHASE_90_FINISH; | |
3279 | |
3280 break; | |
3281 #endif | |
3058 | 3282 |
3059 | 3283 |
3060 // | 3284 // |
3061 //--- finish Calculation Cycle ------------------------------------------------------------ | 3285 //--- finish Calculation Cycle ------------------------------------------------------------ |
3062 // | 3286 // |
3063 case PHASE_90_FINISH: | 3287 case PHASE_90_FINISH: |
3064 | 3288 |
3065 // Check if deco obligation is steady state or decreasing. | 3289 // Check if deco obligation is steady state or decreasing. |
3066 // This works only when an alternative plan is enabled and if it is not a bailout plan, | 3290 // Update the result only: |
3067 // thus BAILOUT_MODE must not be set while doing the alternative plan. | 3291 // - if an alternative plan is enabled, and |
3068 if( (deco_status & CALC_ALT) && !(deco_status & BAILOUT_MODE) ) | 3292 // - if a valid alternative plan TTS exists, and |
3293 // - if it is not a bailout plan | |
3294 if( (deco_status & CALC_ALT ) ) | |
3295 if( (int_O_TTS_alt & INT_FLAG_INVALID) ) | |
3296 if( !(deco_status & BAILOUT_MODE ) ) | |
3069 { | 3297 { |
3070 if( int_O_TTS_alt < int_O_TTS_norm ) deco_info |= DECO_ZONE; | 3298 if( int_O_TTS_alt < int_O_TTS_norm ) deco_info |= DECO_ZONE; |
3071 if( int_O_TTS_alt > int_O_TTS_norm ) deco_info &= ~DECO_ZONE; | 3299 if( int_O_TTS_alt > int_O_TTS_norm ) deco_info &= ~DECO_ZONE; |
3072 } | 3300 } |
3073 | 3301 |
3213 ////////////////////////////////////////////////////////////////////////////// | 3441 ////////////////////////////////////////////////////////////////////////////// |
3214 // calc_tissues | 3442 // calc_tissues |
3215 // | 3443 // |
3216 // INPUT: ppN2 partial pressure of inspired N2 | 3444 // INPUT: ppN2 partial pressure of inspired N2 |
3217 // ppHe partial pressure of inspired He | 3445 // ppHe partial pressure of inspired He |
3218 // tissue_increment integration time and tissue selector (real or simulated) | 3446 // tissue_increment tissue selector (real or simulated) and interval time |
3219 // | 3447 // |
3220 // MODIFIED: real_pres_tissue_N2[] tissue N2 pressures (in real tissues context) | 3448 // MODIFIED: real_pres_tissue_N2[] tissue N2 pressures (in real tissues context) |
3221 // real_pres_tissue_He[] tissue He pressures (in real tissues context) | 3449 // real_pres_tissue_He[] tissue He pressures (in real tissues context) |
3222 // sim_pres_tissue_N2[] tissue N2 pressures (in simulated tissues context) | 3450 // sim_pres_tissue_N2[] tissue N2 pressures (in simulated tissues context) |
3223 // sim_pres_tissue_He[] tissue He pressures (in simulated tissues context) | 3451 // sim_pres_tissue_He[] tissue He pressures (in simulated tissues context) |
3240 assert( 0.00 <= ppHe && ppHe < 12.6 ); // 90% He at 130m | 3468 assert( 0.00 <= ppHe && ppHe < 12.6 ); // 90% He at 130m |
3241 | 3469 |
3242 | 3470 |
3243 for( ci=0; ci < NUM_COMP; ci++ ) // iterate through all compartments | 3471 for( ci=0; ci < NUM_COMP; ci++ ) // iterate through all compartments |
3244 { | 3472 { |
3245 i = tissue_increment & TIME_MASK; // extract number of minutes to do (if i > 0) | 3473 i = tissue_increment & TIME_MASK; // i > 0: do a number of i full minutes |
3246 // or if one 2 second period is to do (if i = 0) | 3474 // I = 0: do 2 (real tissues) or 6 (simulated tissues) seconds |
3247 | 3475 |
3248 if( i == 0 ) // check if we shall do one 2-seconds period | 3476 if( i == 0 ) // check if we shall do one 2 or 6 seconds interval |
3249 { | 3477 { |
3250 read_Buhlmann_times(0); // YES - program coefficients for a 2 seconds period | 3478 read_Buhlmann_times(0); // YES - program coefficients for a 2 or 6 seconds period |
3251 period = 1; // - set period length (in cycles) | 3479 period = 1; // - set period length (in cycles) |
3252 i = 1; // - and one cycle to do | 3480 i = 1; // - and one cycle to do |
3253 } | 3481 } |
3254 else if( i > 9 ) // check if we can start with 10 minutes periods | 3482 else if( i > 9 ) // check if we can start with 10 minutes periods |
3255 { | 3483 { |
3434 // | 3662 // |
3435 // Modified: deco_warnings for IBCD, micro bubbles and outside warning (only in real tissues context) | 3663 // Modified: deco_warnings for IBCD, micro bubbles and outside warning (only in real tissues context) |
3436 // | 3664 // |
3437 static void calc_limit(PARAMETER float GF_parameter) | 3665 static void calc_limit(PARAMETER float GF_parameter) |
3438 { | 3666 { |
3439 overlay float pres_respiration_min_total = 0.0; | 3667 overlay float pres_ambient_min_overall = 0.0; |
3440 overlay unsigned char surface_mode = 0; // 0: off, 1: on | 3668 overlay unsigned char surface_mode = 0; // 0: off, 1: on |
3441 | 3669 |
3442 | 3670 |
3443 // check mode | 3671 // check mode |
3444 if( GF_parameter < 0 ) | 3672 if( GF_parameter < 0 ) |
3445 { | 3673 { |
3464 } | 3692 } |
3465 | 3693 |
3466 // loop over all tissues | 3694 // loop over all tissues |
3467 for( ci = 0; ci < NUM_COMP; ci++ ) | 3695 for( ci = 0; ci < NUM_COMP; ci++ ) |
3468 { | 3696 { |
3469 overlay float pres_respiration_min_tissue; | 3697 overlay float pres_ambient_min_tissue; |
3470 | 3698 |
3471 | 3699 |
3472 // get the coefficients for tissue ci | 3700 // get the coefficients for tissue ci |
3473 read_Buhlmann_coefficients(); | 3701 read_Buhlmann_coefficients(); |
3474 | 3702 |
3567 } | 3795 } |
3568 } | 3796 } |
3569 } // real tissues | 3797 } // real tissues |
3570 | 3798 |
3571 // calculate the minimum ambient pressure that the tissue can withstand | 3799 // calculate the minimum ambient pressure that the tissue can withstand |
3572 if( char_I_deco_model == 0 ) | 3800 if( char_I_model == 0 ) |
3573 { | 3801 { |
3574 // straight Buhlmann | 3802 // straight Buhlmann |
3575 pres_respiration_min_tissue = (pres_tissue - var_a) * var_b; | 3803 pres_ambient_min_tissue = (pres_tissue - var_a) * var_b; |
3576 } | 3804 } |
3577 else | 3805 else |
3578 { | 3806 { |
3579 // Buhlmann with Eric Baker's varying gradient factor correction | 3807 // Buhlmann with Eric Baker's varying gradient factor correction |
3580 // note: this equation [1] is the inverse of equation [2] | 3808 // note: this equation [1] is the inverse of equation [2] |
3581 pres_respiration_min_tissue = ( pres_tissue - (var_a * GF_parameter) ) | 3809 pres_ambient_min_tissue = ( pres_tissue - (var_a * GF_parameter) ) |
3582 / ( 1.0 - GF_parameter + (GF_parameter / var_b ) ); | 3810 / ( 1.0 - GF_parameter + (GF_parameter / var_b ) ); |
3583 } | 3811 } |
3584 | 3812 |
3585 // check if this tissue requires a higher ambient pressure than was found to be needed up to now | 3813 // check if this tissue requires a higher ambient pressure than was found to be needed up to now |
3586 if( pres_respiration_min_tissue > pres_respiration_min_total ) | 3814 if( pres_ambient_min_tissue > pres_ambient_min_overall ) |
3587 { | 3815 { |
3588 pres_respiration_min_total = pres_respiration_min_tissue; | 3816 pres_ambient_min_overall = pres_ambient_min_tissue; |
3589 lead_tissue = ci; | 3817 lead_tissue = ci; |
3590 } | 3818 } |
3591 } // for | 3819 } // for |
3592 | 3820 |
3593 // compute ceiling for the real tissues in bar relative pressure | 3821 // compute ceiling in bar relative pressure |
3594 ceiling = pres_respiration_min_total - pres_surface; | 3822 ceiling = pres_ambient_min_overall - pres_surface; |
3823 | |
3824 // limit ceiling to positive values | |
3825 if( ceiling < 0.0 ) ceiling = 0.0; | |
3595 | 3826 |
3596 #ifdef _helium | 3827 #ifdef _helium |
3597 // IBCD is checked for real tissues only | 3828 // IBCD is checked for real tissues only |
3598 if( tissue_increment & TISSUE_SELECTOR ) | 3829 if( tissue_increment & TISSUE_SELECTOR ) |
3599 { | 3830 { |
3679 | 3910 |
3680 #endif | 3911 #endif |
3681 | 3912 |
3682 // compute the maximum tissue pressure allowed to be exposed to an | 3913 // compute the maximum tissue pressure allowed to be exposed to an |
3683 // ambient pressure equaling the surface pressure | 3914 // ambient pressure equaling the surface pressure |
3684 if( char_I_deco_model != 0 ) | 3915 if( char_I_model != 0 ) |
3685 { | 3916 { |
3686 // GF model enabled, this equation [2] is the inverse of equation [1] | 3917 // GF model enabled, this equation [2] is the inverse of equation [1] |
3687 pres_limit = (1.0 - GF_high + GF_high / var_b) * pres_surface + GF_high * var_a; | 3918 pres_limit = (1.0 - GF_high + GF_high / var_b) * pres_surface + GF_high * var_a; |
3688 } | 3919 } |
3689 else | 3920 else |
3857 // | 4088 // |
3858 // Updated: internal_deco_depth[] depth (in meters) of each stop | 4089 // Updated: internal_deco_depth[] depth (in meters) of each stop |
3859 // internal_deco_time [] time (in minutes) of each stop | 4090 // internal_deco_time [] time (in minutes) of each stop |
3860 // internal_deco_gas [] gas used (index 1-5) at each stop | 4091 // internal_deco_gas [] gas used (index 1-5) at each stop |
3861 // | 4092 // |
3862 static unsigned char update_deco_table(PARAMETER unsigned char time_increment) | 4093 static void update_deco_table(PARAMETER unsigned char time_increment) |
3863 { | 4094 { |
3864 assert( char_depth_sim > 0 ); // no stop at surface | 4095 assert( char_depth_sim > 0 ); // no stop at surface |
3865 | 4096 |
3866 | 4097 |
3867 // is there already a stop entry matching with the current depth and gas? | 4098 // is there already a stop entry matching with the current depth and gas? |
3871 // YES - increment stop time if possible, stop time entries are | 4102 // YES - increment stop time if possible, stop time entries are |
3872 // limited to 99 minutes because of display constraints | 4103 // limited to 99 minutes because of display constraints |
3873 if( internal_deco_time[stop_index] < (100 - time_increment) ) | 4104 if( internal_deco_time[stop_index] < (100 - time_increment) ) |
3874 { | 4105 { |
3875 // YES - time increment fits into current stop entry, | 4106 // YES - time increment fits into current stop entry, |
3876 // increment stop time and return with status 'success' | 4107 // increment stop time |
3877 internal_deco_time[stop_index] += time_increment; | 4108 internal_deco_time[stop_index] += time_increment; |
3878 return 1; | 4109 |
4110 // done | |
4111 return; | |
3879 } | 4112 } |
3880 else | 4113 else |
3881 { | 4114 { |
3882 // NO - A chained stop entry will be created further down in the | 4115 // NO - A chained stop entry will be created further down in the |
3883 // code to continue the stop, but we will limit the number | 4116 // code to continue the stop, but we will limit the number |
3884 // of chained stop table entries in order to abort an ever- | 4117 // of chained stop table entries in order to abort an ever- |
3885 // running deco calculation. Too many chained entries? | 4118 // running deco calculation. Too many chained entries? |
3886 if( ++chained_stops >= STOP_CHAINING_LIMIT ) | 4119 if( ++chained_stops >= STOP_CHAINING_LIMIT ) |
3887 { | 4120 { |
3888 // YES - set overflow warning and return with status 'failed' | 4121 // YES - set warning that calculations took too long |
3889 deco_warnings |= DECO_WARNING_INCOMPLETE; | 4122 deco_warnings |= DECO_WARNING_INCOMPLETE; |
3890 return 0; | 4123 |
4124 // done | |
4125 return; | |
3891 } | 4126 } |
3892 } | 4127 } |
3893 } | 4128 } |
3894 | 4129 |
3895 // the current stop entry does not match the current depth and gas, | 4130 // the current stop entry does not match the current depth and gas, |
3907 // NO - move on to next entry position | 4142 // NO - move on to next entry position |
3908 stop_index += 1; | 4143 stop_index += 1; |
3909 } | 4144 } |
3910 else | 4145 else |
3911 { | 4146 { |
3912 // YES - set overflow warning and return with status 'failed' | 4147 // YES - if run in deco calculator mode, set a warning that there is an overflow in the stops table |
3913 deco_warnings |= DECO_WARNING_INCOMPLETE; | 4148 if( main_status & CALCULATE_BOTTOM ) deco_warnings |= DECO_WARNING_INCOMPLETE; |
3914 return 0; | 4149 |
3915 } | 4150 // limit runtime via reached TTS (scaled in 1/10 minutes here) |
3916 } | 4151 if( TTS_time > 9999 ) deco_warnings |= DECO_WARNING_INCOMPLETE; |
3917 | 4152 |
3918 // initial use of a new (or the very first) stop entry, | 4153 // done |
3919 // store all stop data and return with status 'success' | 4154 return; |
4155 } | |
4156 } | |
4157 | |
4158 // initial use of a new (or the very first) stop entry, store all stop data | |
3920 internal_deco_time [stop_index] = time_increment; | 4159 internal_deco_time [stop_index] = time_increment; |
3921 internal_deco_depth[stop_index] = char_depth_sim; | 4160 internal_deco_depth[stop_index] = char_depth_sim; |
3922 internal_deco_gas [stop_index] = sim_gas_current_num; | 4161 internal_deco_gas [stop_index] = sim_gas_current_num; |
3923 return 1; | 4162 |
4163 // done | |
4164 return; | |
3924 } | 4165 } |
3925 | 4166 |
3926 | 4167 |
3927 ////////////////////////////////////////////////////////////////////////////// | 4168 ////////////////////////////////////////////////////////////////////////////// |
3928 // publish_deco_table | 4169 // publish_deco_table |
4131 // safe side, too. | 4372 // safe side, too. |
4132 pres_tissue_max = (P_ambient_altitude/var_N2_b + var_N2_a); | 4373 pres_tissue_max = (P_ambient_altitude/var_N2_b + var_N2_a); |
4133 | 4374 |
4134 // adjust target pressure by GF-high in case the GF model is in use, but not | 4375 // adjust target pressure by GF-high in case the GF model is in use, but not |
4135 // for the no-fly time as it's target pressure is hard to reach anyhow | 4376 // for the no-fly time as it's target pressure is hard to reach anyhow |
4136 if( char_I_deco_model && char_I_altitude_wait ) | 4377 if( char_I_model && char_I_altitude_wait ) |
4137 pres_tissue_max = P_ambient_altitude + | 4378 pres_tissue_max = P_ambient_altitude + |
4138 0.01 * char_I_GF_High_percentage * (pres_tissue_max - P_ambient_altitude); | 4379 0.01 * char_I_GF_High_percentage * (pres_tissue_max - P_ambient_altitude); |
4139 | 4380 |
4140 | 4381 |
4141 #ifdef _helium | 4382 #ifdef _helium |
4329 // Input: int_I_pres_surface surface pressure in mbar | 4570 // Input: int_I_pres_surface surface pressure in mbar |
4330 // time_interval time interval in minutes, must be limited to 254 at max | 4571 // time_interval time interval in minutes, must be limited to 254 at max |
4331 // | 4572 // |
4332 // Modified: tissue pressures N2 and He pressures of the tissues | 4573 // Modified: tissue pressures N2 and He pressures of the tissues |
4333 // CNS_fraction_real current real CNS value | 4574 // CNS_fraction_real current real CNS value |
4334 // ceiling minimum allowed depth in mbar relative pressure | 4575 // ceiling minimum allowed depth in bar relative pressure |
4335 // lead_supersat supersaturation of the leading tissue (float) | 4576 // lead_supersat supersaturation of the leading tissue (float) |
4336 // int_O_lead_supersat supersaturation of the leading tissue (integer) | 4577 // int_O_lead_supersat supersaturation of the leading tissue (integer) |
4578 // char_O_lead_tissue number of the leading tissue | |
4337 // | 4579 // |
4338 static void calc_interval(PARAMETER unsigned char time_interval) | 4580 static void calc_interval(PARAMETER unsigned char time_interval) |
4339 { | 4581 { |
4340 overlay unsigned char time; | 4582 overlay unsigned char time; |
4341 | 4583 |
4345 | 4587 |
4346 | 4588 |
4347 // safeguard and convert surface pressure | 4589 // safeguard and convert surface pressure |
4348 if( int_I_pres_surface < 500) pres_surface = 0.500; | 4590 if( int_I_pres_surface < 500) pres_surface = 0.500; |
4349 else pres_surface = 0.001 * int_I_pres_surface; | 4591 else pres_surface = 0.001 * int_I_pres_surface; |
4592 | |
4593 // safeguard time interval | |
4594 if( time_interval > 254 ) time_interval = 254; | |
4350 | 4595 |
4351 // set breathed pressure to surface pressure | 4596 // set breathed pressure to surface pressure |
4352 real_pres_respiration = pres_surface; | 4597 real_pres_respiration = pres_surface; |
4353 | 4598 |
4354 // calculate partial pressure of N2 in respired air at surface pressure | 4599 // calculate partial pressure of N2 in respired air at surface pressure |
4424 | 4669 |
4425 ////////////////////////////////////////////////////////////////////////////// | 4670 ////////////////////////////////////////////////////////////////////////////// |
4426 // calc_CNS | 4671 // calc_CNS |
4427 // | 4672 // |
4428 // Input: char_ppO2 current ppO2 [in 0.1 bars] | 4673 // Input: char_ppO2 current ppO2 [in 0.1 bars] |
4429 // tissue_increment time increment and tissue selector | 4674 // tissue_increment tissue selector and time interval |
4430 // | 4675 // |
4431 // Modified: CNS_fraction_real accumulated CNS (real tissue context) | 4676 // Modified: CNS_fraction_real accumulated CNS (real tissue context) |
4432 // CNS_fraction_sim accumulated CNS (simulated tissue context) | 4677 // CNS_fraction_sim accumulated CNS (simulated tissue context) |
4433 // | 4678 // |
4434 static void calc_CNS(void) | 4679 static void calc_CNS(void) |
4435 { | 4680 { |
4436 overlay float CNS_fraction_inc; // increment of CNS load, 0.01 = 1% | 4681 overlay float CNS_fraction_inc; // increment of CNS load, 0.01 = 1% |
4437 | 4682 |
4438 | 4683 |
4439 // calculate CNS increment for 2 seconds interval | 4684 // calculate CNS increment for a 2 seconds interval |
4440 if( char_ppO2 > 160 ) | 4685 if( char_ppO2 > 160 ) |
4441 { | 4686 { |
4442 // step-wise CNS increment | 4687 // step-wise CNS increment |
4443 | 4688 |
4444 // calculate index for increment look-up | 4689 // calculate index for increment look-up (uses integer division) |
4445 cns_i = (char_ppO2 - 161) / 5; // integer division | 4690 cns_i = (char_ppO2 - 161) / 5; |
4446 | 4691 |
4447 // indexes > 17 use increment of index 17 | 4692 // indexes > 17 use increment of index 17 |
4448 if( cns_i > 17 ) cns_i = 17; | 4693 if( cns_i > 17 ) cns_i = 17; |
4449 | 4694 |
4450 // read coefficient (increment) | 4695 // read coefficient (increment) |
4451 read_CNS_c_coefficient(); | 4696 read_CNS_c_coefficient(); |
4452 | 4697 |
4453 // re-scale coefficient from storage format in [1/100000] to productive value | 4698 // re-scale coefficient from storage format in [1/100000] to productive value |
4454 CNS_fraction_inc = (float)var_cns_c / 100000.0; | 4699 CNS_fraction_inc = (float)var_cns_value / 100000.0; |
4455 } | 4700 } |
4456 else if( char_ppO2 > 50 ) | 4701 else if( char_ppO2 > 50 ) |
4457 { | 4702 { |
4458 // range wise CNS increment approximation | 4703 // range wise CNS increment approximation |
4459 | 4704 |
4460 // calculate index for approximation coefficients look-up | 4705 // calculate index for approximation coefficients look-up (uses integer division) |
4461 cns_i = (char_ppO2 - 51) / 10; // integer division | 4706 cns_i = (char_ppO2 - 51) / 10; |
4462 | 4707 |
4463 // read coefficients | 4708 // read coefficients |
4464 read_CNS_ab_coefficient(); | 4709 read_CNS_ab_coefficient(); |
4465 | 4710 |
4466 // calculate the CNS increment | 4711 // calculate the CNS increment |
4467 CNS_fraction_inc = 1.0 / (var_cns_a * char_ppO2 + var_cns_b ); | 4712 CNS_fraction_inc = 1.0 / (var_cns_gain * char_ppO2 + var_cns_offset ); |
4468 } | 4713 } |
4469 else | 4714 else |
4470 { // no increment up to 0.5 bar ppO2 | 4715 { // no increment for a ppO2 of up to 0.5 bar |
4471 CNS_fraction_inc = 0.0; | 4716 CNS_fraction_inc = 0.0; |
4472 } | 4717 } |
4473 | 4718 |
4474 // apply a time factor in case of minute-based interval (factor = N * 30.0) | 4719 // apply a time factor in case of: |
4475 if( tissue_increment & TIME_MASK ) | 4720 // - simulated tissues and interval = 0 (i.e. 6 seconds to do) -> factor 3 |
4476 { | 4721 // - any tissues and interval > 0 (i.e. i minutes to do) -> factor 30 * i |
4477 CNS_fraction_inc *= (float)(tissue_increment & TIME_MASK) * 30.0; | 4722 if( tissue_increment == 0 ) CNS_fraction_inc *= 3.0; |
4478 } | 4723 else if( tissue_increment & TIME_MASK ) CNS_fraction_inc *= 30.0 * (float)(tissue_increment & TIME_MASK); |
4724 | |
4479 | 4725 |
4480 // update the CNS accumulator | 4726 // update the CNS accumulator |
4481 if ( tissue_increment & TISSUE_SELECTOR ) CNS_fraction_real += CNS_fraction_inc; // real tissues | 4727 if ( tissue_increment & TISSUE_SELECTOR ) CNS_fraction_real += CNS_fraction_inc; // real tissues |
4482 else CNS_fraction_sim += CNS_fraction_inc; // simulated tissues | 4728 else CNS_fraction_sim += CNS_fraction_inc; // simulated tissues |
4483 } | 4729 } |
4484 | 4730 |
4485 | 4731 |
4486 ////////////////////////////////////////////////////////////////////////////// | 4732 ////////////////////////////////////////////////////////////////////////////// |
4487 // calc_due_by_depth_time_sac (Helper Function saving Code Space) | 4733 // calc_required_volume |
4488 // | 4734 // |
4489 // Calculates the gas volume required for a given depth, time and usage (SAC) | 4735 // Calculates the gas volume required for a given depth, time and usage (SAC) |
4490 // rate. It uses a fixed surface pressure of 1.0 bar to deliver stable results | 4736 // rate. It uses a fixed surface pressure of 1.0 bar to deliver stable results |
4491 // when used through the deco calculator. | 4737 // when used through the deco calculator. |
4492 // | 4738 // |
4493 // Input: gas_needs_depth depth in meters | 4739 // Input: gas_needs_depth depth in meters |
4494 // gas_needs_time time in minutes | 4740 // gas_needs_time time in minutes (0 encodes 1/10 minute) |
4495 // gas_needs_usage_rate gas usage in liters per minute at surface pressure | 4741 // gas_needs_usage_rate gas usage in liters per minute at surface pressure |
4496 // | 4742 // |
4497 // Output: gas_needs_volume_due required gas volume in liters | 4743 // Output: gas_needs_volume_due required gas volume in liters |
4498 // | 4744 // |
4499 static void calc_due_by_depth_time_sac(void) | 4745 static void calc_required_volume(void) |
4500 { | 4746 { |
4501 gas_needs_volume_due = ((float)gas_needs_depth * METER_TO_BAR + pres_surface) * gas_needs_time * gas_needs_usage_rate; | 4747 // calculate volume for 1 minute |
4748 gas_needs_volume_due = ((float)gas_needs_depth * METER_TO_BAR + pres_surface) * gas_needs_usage_rate; | |
4749 | |
4750 // multiply 1-minute-volume with time factor if time factor <> 1 | |
4751 if ( gas_needs_time == 0 ) gas_needs_volume_due *= 0.1; // 1/10 minute | |
4752 else if ( gas_needs_time > 1 ) gas_needs_volume_due *= gas_needs_time; // multiple minutes | |
4502 } | 4753 } |
4503 | 4754 |
4755 | |
4756 | |
4757 #ifdef _rx_functions | |
4504 | 4758 |
4505 ////////////////////////////////////////////////////////////////////////////// | 4759 ////////////////////////////////////////////////////////////////////////////// |
4506 // calc_TR_functions | 4760 // calc_TR_functions |
4507 // | 4761 // |
4508 // Process Pressure Readings (OSTC TR only) | 4762 // Process Pressure Readings (OSTC TR only) |
4509 // | 4763 // |
4510 // Input: todo | 4764 // Input: todo |
4511 // | 4765 // |
4512 // Output: todo | 4766 // Output: todo |
4513 // | 4767 // |
4514 #ifdef _rx_functions | |
4515 static void calc_TR_functions(void) | 4768 static void calc_TR_functions(void) |
4516 { | 4769 { |
4517 // pressure warnings for reading 1, but only if enabled and pressure value available | 4770 // pressure warnings for reading 1, but only if enabled and pressure value available |
4518 if( (char_I_pressure_gas[0] > 0) && !(int_IO_pressure_value[0] & INT_FLAG_NOT_AVAIL) ) | 4771 if( (char_I_pressure_gas[0] > 0) && !(int_IO_pressure_value[0] & INT_FLAG_NOT_AVAIL) ) |
4519 { | 4772 { |
4661 else int_O_tank_pressure = 0; | 4914 else int_O_tank_pressure = 0; |
4662 | 4915 |
4663 // strip flags | 4916 // strip flags |
4664 int_O_tank_pressure &= 0x0FFF; | 4917 int_O_tank_pressure &= 0x0FFF; |
4665 | 4918 |
4666 // TODO: decide if log shall be in 0.1 bar of full bar only | 4919 // scale to recording format of full bar only |
4667 // scale to full bar only | |
4668 int_O_tank_pressure /= 10; | 4920 int_O_tank_pressure /= 10; |
4669 | 4921 |
4670 | 4922 |
4671 // calculate SAC - modes 1 & 2 | 4923 // calculate SAC - modes 1 & 2 |
4672 if( (char_I_SAC_mode == 1) || (char_I_SAC_mode == 2) ) | 4924 if( (char_I_SAC_mode == 1) || (char_I_SAC_mode == 2) ) |
4732 int_O_SAC_measured |= INT_FLAG_OUTDATED; | 4984 int_O_SAC_measured |= INT_FLAG_OUTDATED; |
4733 } | 4985 } |
4734 } | 4986 } |
4735 } | 4987 } |
4736 } | 4988 } |
4737 #endif | 4989 #endif // _rx_functions |
4738 | 4990 |
4991 | |
4992 #ifdef _cave_mode | |
4739 | 4993 |
4740 ////////////////////////////////////////////////////////////////////////////// | 4994 ////////////////////////////////////////////////////////////////////////////// |
4741 // convert_gas_needs_to_press | 4995 // read_backtrack_data |
4996 // | |
4997 // Gets the data of the next backtracking data set | |
4998 // | |
4999 // Modified: backtrack_index last current position in backtracking storage | |
5000 // | |
5001 // Output: backtrack_step_counter number of 1/10 min calculation steps to do on next target depth | |
5002 // backtrack_target_depth next target depth | |
5003 // | |
5004 static void read_backtrack_data(void) | |
5005 { | |
5006 overlay unsigned char firstround = 1; | |
5007 | |
5008 | |
5009 // load the step counter with the default of ten 1/10 minute steps to go between two depth samples | |
5010 backtrack_step_counter = 10; | |
5011 | |
5012 // repeat until having read the whole data set or having reached the first storage position | |
5013 while(backtrack_index) | |
5014 { | |
5015 // backtracking data recording format: | |
5016 // --------------------------------------------------------------------------- | |
5017 // 0ddddddd -> datum is a depth recording with d = 0..127 depth in meters | |
5018 // 10tttttt -> delta time with t = 0.. 59 time in seconds | |
5019 // 110ggggg -> gas staging status with g = 1 gas staged | |
5020 // 111nnnnn -> waypoint marker with n = 1.. 31 waypoint number | |
5021 // | |
5022 // gas availability vector: LSB : gas 1 (and so on) | |
5023 // waypoint marker : 1 - 30: user waypoints, last waypoint is turn point | |
5024 // : 31: spare for turn point if all 30 waypoints used up | |
5025 // : 0: reserved | |
5026 | |
5027 // read recording entry and then advance (backward direction!) the reading index | |
5028 overlay unsigned char datum = char_I_backtrack_storage[backtrack_index--]; | |
5029 | |
5030 // is it a target depth? | |
5031 if( datum < 128 ) | |
5032 { | |
5033 // YES - assign the target depth | |
5034 backtrack_target_depth = datum; | |
5035 | |
5036 // a depth entry closes a data set, so done with this data set | |
5037 return; | |
5038 } | |
5039 | |
5040 // is it a delta time entry? | |
5041 else if( datum < 128 + 64 ) | |
5042 { | |
5043 // YES - When a delta time entry is contained in a data set, the time | |
5044 // stored in the delta time entry is the time that has elapsed | |
5045 // between storage of the depth that is part of this data set | |
5046 // and the previous depth recording. | |
5047 // This entry is stored whenever the delta time is shorter than | |
5048 // the default 1 minute depth sampling interval time. | |
5049 | |
5050 // assign the delta time to the step counter: remove entry tag and | |
5051 // convert datum from 0..59 seconds to 0..9 steps by integer division | |
5052 backtrack_step_counter = (datum - 128) / 6; | |
5053 } | |
5054 | |
5055 // is it a gas staging status entry? | |
5056 else if( datum < 128 + 64 + 32 ) | |
5057 { | |
5058 // YES - extract gas staging status | |
5059 overlay unsigned char gas_status = datum - (128 + 64); | |
5060 | |
5061 // decode and update gas staging status | |
5062 // | |
5063 // bit set : gas is staged (not available) during next section of backtracking, | |
5064 // bit cleared: gas is not staged ( available) during next section of backtracking. | |
5065 // | |
5066 // bit 0 corresponds to gas 1, ..., bit 4 corresponds to gas 5 | |
5067 // | |
5068 for( i = 0; i < NUM_GAS; i++ ) | |
5069 { | |
5070 if ( gas_status & (1 << i) ) deco_gas_type[i] |= GAS_AVAIL_STAGED; // staged | |
5071 else deco_gas_type[i] &= ~GAS_AVAIL_STAGED; // not staged | |
5072 } | |
5073 } | |
5074 | |
5075 // must be waypoint marker entry then | |
5076 else | |
5077 { | |
5078 // set step counter to zero if first entry read is a waypoint entry | |
5079 if( firstround ) backtrack_step_counter = 0; | |
5080 } | |
5081 | |
5082 // first round done | |
5083 firstround = 0; | |
5084 | |
5085 } // while | |
5086 | |
5087 // first storage position reached, by convention it contains | |
5088 // the final target depth which is zero meters aka the surface | |
5089 backtrack_target_depth = 0; | |
5090 } | |
5091 | |
5092 #endif // _cave_mode | |
5093 | |
5094 | |
5095 | |
5096 ////////////////////////////////////////////////////////////////////////////// | |
5097 // convert_volume_to_pressure | |
4742 // | 5098 // |
4743 // Converts gas volumes into pressures and sets respective flags | 5099 // Converts gas volumes into pressures and sets respective flags |
4744 // | 5100 // |
4745 // Input: gas_needs_gas_index index of the gas to convert (0-4) | 5101 // Input: gas_needs_gas_index index of the gas to convert (0-4) |
4746 // gas_volume_need[] needed gas volume in liters | 5102 // gas_volume_need[] needed gas volume in liters |
4747 // char_I_gas_avail_pres[] available gas volume in bar | 5103 // char_I_gas_avail_pres[] available gas volume in bar |
4748 // char_I_gas_avail_size[] size of the tanks in liters | 5104 // char_I_gas_avail_size[] size of the tanks in liters |
4749 // char_I_pressure_gas[] gas configured on reading 1/2 (TR only) | 5105 // char_I_pressure_gas[] gas configured on reading 1/2 (TR only) |
4750 // | 5106 // |
4751 // Output: int_O_gas_need_vol[] required gas amount in liters, including flags | 5107 // Output: int_O_gas_need_vol[] required gas amount in liters |
4752 // int_O_gas_need_pres[] required gas amount in bar, including flags | 5108 // int_O_gas_need_pres[] required gas amount in bar, including flags |
4753 // int_O_pressure_need[] required gas amount for reading 1/2 (TR only) | 5109 // int_O_pressure_need[] required gas amount for reading 1/2 (TR only) |
4754 // | 5110 // |
4755 static void convert_gas_needs_to_press(void) | 5111 static void convert_volume_to_pressure(void) |
4756 { | 5112 { |
4757 | |
4758 // just to make the code more readable... | 5113 // just to make the code more readable... |
4759 i = gas_needs_gas_index; | 5114 i = gas_needs_gas_index; |
4760 | 5115 |
4761 if( gas_volume_need[i] >= 65534.5 ) | 5116 if( gas_volume_need[i] >= 65534.5 ) |
4762 { | 5117 { |
4763 int_O_gas_need_vol[i] = 65535; // clip at 65535 liters | 5118 int_O_gas_need_vol[i] = 65535; // clip at 65535 liters |
4764 int_O_gas_need_pres[i] = 999 | INT_FLAG_WARNING | INT_FLAG_HIGH; // 999 bar + warning flag + >999 flag | 5119 int_O_gas_need_pres[i] = 999 | INT_FLAG_WARNING | INT_FLAG_HIGH; // 999 bar + warning flag + >999 flag |
4765 } | 5120 } |
4766 else | 5121 else |
4767 { | 5122 { |
4768 overlay unsigned short int_pres_warn; | 5123 // convert gas volume need from float to integer [in liter] |
4769 overlay unsigned short int_pres_attn; | 5124 int_O_gas_need_vol[i] = (unsigned short)( gas_volume_need[i] + 0.5 ); |
4770 | |
4771 // set warning and attention thresholds | |
4772 int_pres_warn = 10.0 * (unsigned short)char_I_gas_avail_pres[i]; | |
4773 int_pres_attn = GAS_NEEDS_LIMIT_ATTENTION * int_pres_warn; | |
4774 | |
4775 // convert ascent gas volume need from float to integer [in liter] | |
4776 int_O_gas_need_vol[i] = (unsigned short)gas_volume_need[i]; | |
4777 | 5125 |
4778 // compute how much pressure in the tank will be needed [in bar] | 5126 // compute how much pressure in the tank will be needed [in bar] |
4779 int_O_gas_need_pres[i] = (unsigned short)( gas_volume_need[i] / char_I_gas_avail_size[i] + 0.999 ); | 5127 int_O_gas_need_pres[i] = (unsigned short)( gas_volume_need[i] / char_I_gas_avail_size[i] + 0.5 ); |
4780 | 5128 |
4781 // limit result to 999 bar because of display constraints | 5129 // limit result to 999 bar because of display constraints |
4782 if( int_O_gas_need_pres[i] > 999 ) int_O_gas_need_pres[i] = 999 | INT_FLAG_HIGH; | 5130 if( int_O_gas_need_pres[i] > 999 ) int_O_gas_need_pres[i] = 999 | INT_FLAG_HIGH; |
4783 | 5131 |
4784 // set flags for fast evaluation by dive mode | 5132 // set flags for fast evaluation by output routine |
4785 if ( int_O_gas_need_pres[i] == 0 ) int_O_gas_need_pres[i] |= INT_FLAG_ZERO; | 5133 if( int_O_gas_need_pres[i] == 0 ) int_O_gas_need_pres[i] |= INT_FLAG_ZERO; |
4786 else if ( int_O_gas_need_pres[i] >= int_pres_warn ) int_O_gas_need_pres[i] |= INT_FLAG_WARNING; | 5134 else |
4787 else if ( int_O_gas_need_pres[i] >= int_pres_attn ) int_O_gas_need_pres[i] |= INT_FLAG_ATTENTION; | 5135 #ifdef _gas_contingency |
4788 } | 5136 if( main_status & GAS_CONTINGENCY ) |
4789 | 5137 { |
4790 // set invalid flag if there is an overflow in the stops table | 5138 // take warning and attention computed en-route |
5139 if ( deco_gas_type[i] & GAS_NEED_WARNING ) | |
5140 { | |
5141 // tag the tank with a warning | |
5142 int_O_gas_need_pres[i] |= INT_FLAG_WARNING; | |
5143 | |
5144 // tag the peer tanks with a warning, too | |
5145 for( j = 0; j < NUM_GAS; j++ ) | |
5146 { | |
5147 if( peer_tank[i] & (1 << j) ) int_O_gas_need_pres[j] |= INT_FLAG_WARNING; | |
5148 } | |
5149 } | |
5150 else if( deco_gas_type[i] & GAS_NEED_ATTENTION ) | |
5151 { | |
5152 // tag the tank with an attention | |
5153 int_O_gas_need_pres[i] |= INT_FLAG_ATTENTION; | |
5154 | |
5155 // tag the peer tanks with an attention, too | |
5156 for( j = 0; j < NUM_GAS; j++ ) | |
5157 { | |
5158 if( peer_tank[i] & (1 << j) ) int_O_gas_need_pres[j] |= INT_FLAG_ATTENTION; | |
5159 } | |
5160 } | |
5161 } | |
5162 else | |
5163 #endif | |
5164 { | |
5165 // compute warning and attention now | |
5166 if ( gas_volume_need[i] >= gas_volume_avail[i] ) int_O_gas_need_pres[i] |= INT_FLAG_WARNING; | |
5167 else if( gas_volume_need[i] >= gas_volume_atten[i] ) int_O_gas_need_pres[i] |= INT_FLAG_ATTENTION; | |
5168 } | |
5169 } | |
5170 | |
5171 // set invalid flag if there is an overflow in the stops table or calculation took too long | |
4791 if( deco_warnings & DECO_WARNING_INCOMPLETE ) int_O_gas_need_pres[i] |= INT_FLAG_INVALID; | 5172 if( deco_warnings & DECO_WARNING_INCOMPLETE ) int_O_gas_need_pres[i] |= INT_FLAG_INVALID; |
4792 | 5173 |
4793 #ifdef _rx_functions | 5174 #ifdef _rx_functions |
4794 // only for OSTC TR model with TR functions enabled | 5175 // only for OSTC TR model with TR functions enabled |
4795 if( main_status & TR_FUNCTIONS ) | 5176 if( main_status & TR_FUNCTIONS ) |
4796 { | 5177 { |
4797 // char_I_pressure_gas[] uses gas indexes from 1-10, loop variable i runs from 0 to 4 | 5178 // char_I_pressure_gas[] uses gas indexes from 1-10, loop variable i runs from 0 to 4 |
4798 overlay unsigned char j = i+1; | 5179 j = i+1; |
4799 | 5180 |
4800 // check if the current gas is configured on pressure reading 1 or 2 | 5181 // check if the current gas is configured on pressure reading 1 or 2 |
4801 if( (char_I_pressure_gas[0] == j) || (char_I_pressure_gas[1] == j) ) | 5182 if( (char_I_pressure_gas[0] == j) || (char_I_pressure_gas[1] == j) ) |
4802 { | 5183 { |
4803 // get a copy of the required pressure in full bar | 5184 // get a copy of the required pressure in full bar |
4807 int_pres_need &= 1023; | 5188 int_pres_need &= 1023; |
4808 | 5189 |
4809 // limit to 400 bar and multiply by 10 to get required pressure in 0.1 bar | 5190 // limit to 400 bar and multiply by 10 to get required pressure in 0.1 bar |
4810 int_pres_need = (int_pres_need > 400) ? 4000 | INT_FLAG_OUT_OF_RANGE : 10 * int_pres_need; | 5191 int_pres_need = (int_pres_need > 400) ? 4000 | INT_FLAG_OUT_OF_RANGE : 10 * int_pres_need; |
4811 | 5192 |
4812 // tag as not available if there is an overflow in the stops table | 5193 // tag as not available if there is an overflow in the stops table or calculation took too long |
4813 if( deco_warnings & DECO_WARNING_INCOMPLETE ) int_pres_need |= INT_FLAG_NOT_AVAIL; | 5194 if( deco_warnings & DECO_WARNING_INCOMPLETE ) int_pres_need |= INT_FLAG_NOT_AVAIL; |
4814 | 5195 |
4815 // copy to reading data (in both readings the same gas could be configured) | 5196 // copy to reading data (in both readings the same gas could be configured) |
4816 if( char_I_pressure_gas[0] == j ) int_O_pressure_need[0] = int_pres_need; | 5197 if( char_I_pressure_gas[0] == j ) int_O_pressure_need[0] = int_pres_need; |
4817 if( char_I_pressure_gas[1] == j ) int_O_pressure_need[1] = int_pres_need; | 5198 if( char_I_pressure_gas[1] == j ) int_O_pressure_need[1] = int_pres_need; |
4855 | 5236 |
4856 // set warning & attention flags | 5237 // set warning & attention flags |
4857 if ( int_sim_CNS_fraction >= CNS_LIMIT_WARNING ) int_sim_CNS_fraction |= INT_FLAG_WARNING; | 5238 if ( int_sim_CNS_fraction >= CNS_LIMIT_WARNING ) int_sim_CNS_fraction |= INT_FLAG_WARNING; |
4858 else if ( int_sim_CNS_fraction >= CNS_LIMIT_ATTENTION ) int_sim_CNS_fraction |= INT_FLAG_ATTENTION; | 5239 else if ( int_sim_CNS_fraction >= CNS_LIMIT_ATTENTION ) int_sim_CNS_fraction |= INT_FLAG_ATTENTION; |
4859 | 5240 |
4860 // set invalid flag if there is an overflow in the stops table | 5241 // set invalid flag if there is an overflow in the stops table or calculation took too long |
4861 if ( deco_warnings & DECO_WARNING_INCOMPLETE ) int_sim_CNS_fraction |= INT_FLAG_INVALID; | 5242 if ( deco_warnings & DECO_WARNING_INCOMPLETE ) int_sim_CNS_fraction |= INT_FLAG_INVALID; |
4862 } | 5243 } |
4863 | 5244 |
4864 | 5245 |
4865 ////////////////////////////////////////////////////////////////////////////// | 5246 ////////////////////////////////////////////////////////////////////////////// |
4886 if( int_O_lead_supersat > 100 ) | 5267 if( int_O_lead_supersat > 100 ) |
4887 { | 5268 { |
4888 int_O_lead_supersat |= INT_FLAG_WARNING; // make GF factor shown in red | 5269 int_O_lead_supersat |= INT_FLAG_WARNING; // make GF factor shown in red |
4889 deco_warnings |= DECO_WARNING_OUTSIDE; // make depth shown in red | 5270 deco_warnings |= DECO_WARNING_OUTSIDE; // make depth shown in red |
4890 } | 5271 } |
4891 else if( (char_I_deco_model != 0) && (int_O_lead_supersat > char_I_GF_High_percentage) | 5272 else if( (char_I_model != 0) && (int_O_lead_supersat > char_I_GF_High_percentage) |
4892 || (char_I_deco_model == 0) && (int_O_lead_supersat > 99 ) ) | 5273 || (char_I_model == 0) && (int_O_lead_supersat > 99 ) ) |
4893 { | 5274 { |
4894 int_O_lead_supersat |= INT_FLAG_ATTENTION; // make GF factor shown in yellow | 5275 int_O_lead_supersat |= INT_FLAG_ATTENTION; // make GF factor shown in yellow |
4895 deco_warnings |= DECO_ATTENTION_OUTSIDE; // make depth shown in yellow | 5276 deco_warnings |= DECO_ATTENTION_OUTSIDE; // make depth shown in yellow |
4896 } | 5277 } |
4897 | 5278 |