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