51
+ − 1 /* getrennte Gase f�r die verschiedenen Modi
+ − 2 um Gaswechsel Eintr�ge zu vereinfachen
38
+ − 3 das heisst:
+ − 4 oc == bailout in cc mode
+ − 5 */
+ − 6
+ − 7 /* Konvention:
+ − 8 float extExample_variable_can_be_used_with_extern;
+ − 9 */
+ − 10
+ − 11 #include <string.h>
+ − 12 #include <math.h>
+ − 13 #include <stdbool.h>
+ − 14 #include "buehlmann.h"
+ − 15 #include "decom.h"
+ − 16
+ − 17 extern const float buehlmann_N2_a[];
+ − 18 extern const float buehlmann_N2_b[];
+ − 19 extern const float buehlmann_He_a[];
+ − 20 extern const float buehlmann_He_b[];
+ − 21
+ − 22 typedef struct
+ − 23 {
+ − 24 float depth;
+ − 25 int id;
+ − 26 } SStop;
+ − 27
+ − 28 #define DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS 59940 // 999 minuten; before: 18000 // 5(h) * 60(min) * 60 sec = 18000 sec
+ − 29 #define DECO_STOPS_MAX_TTS_FOR_EVERY_SECOND_CALC_IN_SECONDS 7200
+ − 30 #define NINETY_NINE_MINUTES_IN_SECONDS 59940
+ − 31
+ − 32 # define PRESSURE_TEN_METER 1.0f
+ − 33 # define PRESSURE_THREE_METER 0.333334f
+ − 34 # define PRESSURE_150_CM 0.15f
+ − 35 # define PRESSURE_HALF_METER 0.05f
+ − 36
253
+ − 37 static void buehlmann_backup_and_restore(_Bool backup_restore_otherwise);
+ − 38 static float tissue_tolerance(void);
255
+ − 39 static void ambient_bar_to_deco_stop_depth_bar(SDiveSettings *pDiveSettings, float ceiling);
+ − 40 static int ascend_with_all_gaschanges(SDiveSettings *pDiveSettings, float pressure_decrease);
+ − 41 static float next_stop_depth_input_is_actual_stop_id(SDiveSettings *pDiveSettings, int actual_id);
+ − 42 static float get_gf_at_pressure(SDiveSettings *pDiveSettings, float pressure);
257
+ − 43 static int buehlmann_calc_ndl(SDiveSettings *pDiveSettings);
255
+ − 44 static _Bool dive1_check_deco(SDiveSettings *pDiveSettings);
38
+ − 45
253
+ − 46 static float gSurface_pressure_bar;
+ − 47 static float gPressure;
+ − 48 static int gGas_id;
+ − 49 static float gTissue_nitrogen_bar[16];
+ − 50 static float gTissue_helium_bar[16];
+ − 51 static float gGF_value;
+ − 52 static float gCNS;
38
+ − 53
+ − 54 float gGF_low_depth_bar;
+ − 55 SStop gStop;
+ − 56
+ − 57 void buehlmann_init(void)
+ − 58 {
+ − 59 }
+ − 60
253
+ − 61 static void buehlmann_backup_and_restore(_Bool backup_restore_otherwise)
38
+ − 62 {
+ − 63 static float pressure;
+ − 64 static float gas_id;
+ − 65 static float tissue_nitrogen_bar[16];
+ − 66 static float tissue_helium_bar[16];
+ − 67 static float gf_value;
+ − 68 static float cns;
+ − 69
+ − 70 if(backup_restore_otherwise)
+ − 71 {
+ − 72 pressure = gPressure;
+ − 73 gas_id = gGas_id;
+ − 74 gf_value = gGF_value;
+ − 75 cns = gCNS;
+ − 76 memcpy(tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16));
+ − 77 memcpy(tissue_helium_bar, gTissue_helium_bar, (4*16));
+ − 78 }
+ − 79 else
+ − 80 {
+ − 81 gPressure = pressure;
+ − 82 gGas_id = gas_id;
+ − 83 gGF_value = gf_value;
+ − 84 gCNS = cns;
+ − 85 memcpy(gTissue_nitrogen_bar, tissue_nitrogen_bar, (4*16));
+ − 86 memcpy(gTissue_helium_bar, tissue_helium_bar, (4*16));
+ − 87 }
+ − 88
+ − 89 }
+ − 90
+ − 91 float buehlmann_get_gCNS(void)
+ − 92 {
+ − 93 return gCNS;
+ − 94 }
+ − 95
+ − 96 void buehlmann_calc_deco(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo)
+ − 97 {
+ − 98 float ceiling;
+ − 99 int ascend_time;
+ − 100 int tts_seconds;
+ − 101 float pressure_delta;
+ − 102 float next_depth;
+ − 103 _Bool deco_reached = false;
+ − 104 unsigned short *stoplist;
+ − 105 int i;
+ − 106
+ − 107 gCNS = 0;
253
+ − 108 pDecoInfo->output_time_to_surface_seconds = 0;
38
+ − 109 pDecoInfo->output_ndl_seconds = 0;
+ − 110 for(int i=0;i<DECOINFO_STRUCT_MAX_STOPS;i++)
+ − 111 {
+ − 112 pDecoInfo->output_stop_length_seconds[i] = 0;
+ − 113 }
+ − 114
+ − 115 /* internal copying */
+ − 116 gSurface_pressure_bar = pLifeData->pressure_surface_bar;
+ − 117
+ − 118 gPressure = pLifeData->pressure_ambient_bar;
+ − 119 gGas_id = 0;
+ − 120 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16));
+ − 121 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16));
255
+ − 122 gGF_value = ((float)pDiveSettings->gf_low) / 100.0f;
38
+ − 123
258
+ − 124 stoplist = pDecoInfo->output_stop_length_seconds;
38
+ − 125
305
305f251cc981
bugfix, consistency: show deco/NDL really after 1 minute divetime
Jan Mulder <jlmulder@xs4all.nl>
diff
changeset
+ − 126 if(pLifeData->dive_time_seconds_without_surface_time < 60)
253
+ − 127 return;
38
+ − 128
+ − 129 // clean stop list
+ − 130 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++)
+ − 131 stoplist[i] = 0;
+ − 132
253
+ − 133 if(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero >= (gPressure - PRESSURE_150_CM))
+ − 134 {
+ − 135 deco_reached = true;
+ − 136 }
38
+ − 137
255
+ − 138 gGF_value = ((float)pDiveSettings->gf_high) / 100.0f;
257
+ − 139 buehlmann_backup_and_restore(true);
255
+ − 140 if(!dive1_check_deco(pDiveSettings) )
38
+ − 141 {
257
+ − 142 buehlmann_backup_and_restore(false);
38
+ − 143 // no deco
257
+ − 144 pDecoInfo->output_time_to_surface_seconds = 0;
38
+ − 145 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++)
254
+ − 146 pDecoInfo->output_stop_length_seconds[i] = 0;
38
+ − 147 // calc NDL
257
+ − 148 pDecoInfo->output_ndl_seconds = buehlmann_calc_ndl(pDiveSettings);;
38
+ − 149 return;
+ − 150 }
+ − 151 buehlmann_backup_and_restore(false);
254
+ − 152 pDecoInfo->output_ndl_seconds = 0;
38
+ − 153
255
+ − 154 gGF_value = get_gf_at_pressure(pDiveSettings, gPressure);
38
+ − 155 //current ceiling at actual position
+ − 156 ceiling = tissue_tolerance();
255
+ − 157 ambient_bar_to_deco_stop_depth_bar(pDiveSettings, ceiling);
38
+ − 158
+ − 159 // set the base for all upcoming parameters
+ − 160 ceiling = gStop.depth + gSurface_pressure_bar;
+ − 161 tts_seconds = 0;
+ − 162
+ − 163 // modify parameters if there is ascend or parameter fine adjustment
+ − 164 if(ceiling < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling
+ − 165 {
+ − 166 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr.
+ − 167 if(ceiling < (gPressure - PRESSURE_TEN_METER) )
+ − 168 { do {
255
+ − 169 ascend_time = ascend_with_all_gaschanges(pDiveSettings, PRESSURE_TEN_METER);
38
+ − 170 tts_seconds += ascend_time;
+ − 171 ceiling = tissue_tolerance();
+ − 172 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS)
+ − 173 {
254
+ − 174 pDecoInfo->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS;
38
+ − 175 return;// NINETY_NINE_MINUTES_IN_SECONDS;
+ − 176 }
+ − 177 } while ((ascend_time > 0 ) && ((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER)));
+ − 178 }
+ − 179 do {
+ − 180 buehlmann_backup_and_restore(true);
255
+ − 181 ascend_time = ascend_with_all_gaschanges(pDiveSettings, PRESSURE_THREE_METER);
38
+ − 182 tts_seconds += ascend_time;
+ − 183 ceiling = tissue_tolerance();
+ − 184 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS)
+ − 185 {
254
+ − 186 pDecoInfo->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS;
38
+ − 187 return;// NINETY_NINE_MINUTES_IN_SECONDS;
+ − 188 }
255
+ − 189 ambient_bar_to_deco_stop_depth_bar(pDiveSettings, ceiling);
38
+ − 190 } while ((ascend_time > 0 ) && ((gStop.depth + gSurface_pressure_bar) < gPressure));
+ − 191
+ − 192 if(gStop.depth + gSurface_pressure_bar > gPressure)
+ − 193 {
+ − 194 gPressure += PRESSURE_THREE_METER;
+ − 195 buehlmann_backup_and_restore(false);
+ − 196 tts_seconds -= ascend_time;
+ − 197 }
+ − 198 // calculate first stop based on tissue saturation within 10 meters of stop
+ − 199 //ambient_bar_to_deco_stop_depth_bar(ceiling);
+ − 200 }
+ − 201 else
+ − 202 {
+ − 203 // initial values, upper code might not be executed (is within 150 cm)
+ − 204 }
+ − 205
253
+ − 206 if (ceiling > gSurface_pressure_bar)
+ − 207 {
+ − 208 ceiling = gStop.depth + gSurface_pressure_bar;
+ − 209 // ascend the last meters to first stop (especially consider any gas changes around)
+ − 210 pressure_delta = gPressure - ceiling;
+ − 211 ascend_time = (int) ceil(pressure_delta * 50.0f);
255
+ − 212 tts_seconds += ascend_with_all_gaschanges(pDiveSettings, pressure_delta);
253
+ − 213 }
38
+ − 214 // NDL check
+ − 215 if(ceiling <= gSurface_pressure_bar)
+ − 216 {
+ − 217 // NDL with GF_low
254
+ − 218 pDecoInfo->output_time_to_surface_seconds = 0;
38
+ − 219 return;
+ − 220 }
253
+ − 221 if (ceiling > pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero)
+ − 222 pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = ceiling;
38
+ − 223
+ − 224 // calc gf loop
+ − 225 if(deco_reached)
+ − 226 gGF_low_depth_bar = pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - gSurface_pressure_bar;
+ − 227 else
+ − 228 gGF_low_depth_bar = ceiling - gSurface_pressure_bar;
+ − 229
+ − 230 while(gStop.depth > 0)
+ − 231 {
+ − 232 do
+ − 233 {
255
+ − 234 next_depth = next_stop_depth_input_is_actual_stop_id(pDiveSettings, gStop.id);
+ − 235 gGF_value = get_gf_at_pressure(pDiveSettings, next_depth + gSurface_pressure_bar);
38
+ − 236 buehlmann_backup_and_restore(true);
255
+ − 237 ascend_time = ascend_with_all_gaschanges(pDiveSettings, gStop.depth - next_depth);
38
+ − 238 ceiling = tissue_tolerance();
+ − 239 /* pre check actual limit */
258
+ − 240 if(pDecoInfo->output_stop_length_seconds[gStop.id] >= 999*60)
38
+ − 241 {
258
+ − 242 tts_seconds -= 999*60 - pDecoInfo->output_stop_length_seconds[gStop.id];
+ − 243 pDecoInfo->output_stop_length_seconds[gStop.id] = 999*60;
38
+ − 244 }
+ − 245 else
+ − 246 /* more deco on the actual depth */
+ − 247 if(ceiling > next_depth + gSurface_pressure_bar)
+ − 248 {
+ − 249 next_depth = -1;
+ − 250 buehlmann_backup_and_restore(false);
255
+ − 251 decom_tissues_exposure2(10, &pDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); // some seconds at least at each stop
+ − 252 decom_oxygen_calculate_cns_exposure(10, &pDiveSettings->decogaslist[gGas_id], gPressure, &gCNS);
258
+ − 253 pDecoInfo->output_stop_length_seconds[gStop.id] += 10;
38
+ − 254 tts_seconds += 10;
+ − 255 }
+ − 256 } while(next_depth == -1);
253
+ − 257 tts_seconds += ascend_time;
38
+ − 258 gStop.depth = next_depth;
+ − 259 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 260 {
255
+ − 261 if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
38
+ − 262 break;
255
+ − 263 float pressureChange = ((float)pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10;
38
+ − 264 if(gStop.depth <= pressureChange + 0.00001f)
+ − 265 {
+ − 266 gGas_id = i;
+ − 267 }
+ − 268 else
+ − 269 {
+ − 270 break;
+ − 271 }
+ − 272 }
+ − 273 gStop.id--;
+ − 274 }
+ − 275
258
+ − 276 pDecoInfo->output_time_to_surface_seconds = tts_seconds;
38
+ − 277 }
+ − 278
+ − 279
253
+ − 280 static float tissue_tolerance(void)
38
+ − 281 {
+ − 282 float tissue_inertgas_saturation;
+ − 283 float inertgas_a;
+ − 284 float inertgas_b;
+ − 285 float ceiling;
+ − 286 float global_ceiling;
+ − 287 int ci;
+ − 288
+ − 289 global_ceiling = -1;
+ − 290
+ − 291 for (ci = 0; ci < 16; ci++)
+ − 292 {
+ − 293 if(gTissue_helium_bar[ci] == 0)
+ − 294 {
+ − 295 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 296 //
+ − 297 inertgas_a = buehlmann_N2_a[ci];
+ − 298 inertgas_b = buehlmann_N2_b[ci];
+ − 299 }
+ − 300 else
+ − 301 {
+ − 302 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 303 //
+ − 304 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 305 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 306 }
+ − 307 //
+ − 308 ceiling = (inertgas_b * ( tissue_inertgas_saturation - gGF_value * inertgas_a ) ) / (gGF_value - (inertgas_b * gGF_value) + inertgas_b);
+ − 309 if(ceiling > global_ceiling)
+ − 310 global_ceiling = ceiling;
+ − 311 }
+ − 312 return global_ceiling;
+ − 313 }
+ − 314
246
+ − 315 void buehlmann_super_saturation_calculator(SLifeData* pLifeData, SDecoinfo * pDecoInfo)
38
+ − 316 {
+ − 317 float tissue_inertgas_saturation;
+ − 318 float inertgas_a;
+ − 319 float inertgas_b;
+ − 320 float ceiling;
246
+ − 321 float super_saturation;
+ − 322 float pres_respiration = pLifeData->pressure_ambient_bar;
38
+ − 323 int ci;
+ − 324
246
+ − 325 pDecoInfo->super_saturation = 0;
38
+ − 326
+ − 327 for (ci = 0; ci < 16; ci++)
+ − 328 {
+ − 329 if(gTissue_helium_bar[ci] == 0)
+ − 330 {
+ − 331 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 332 inertgas_a = buehlmann_N2_a[ci];
+ − 333 inertgas_b = buehlmann_N2_b[ci];
+ − 334 }
+ − 335 else
+ − 336 {
+ − 337 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 338 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 339 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 340 }
246
+ − 341
+ − 342 ceiling = pres_respiration / inertgas_b + inertgas_a;
+ − 343 if(tissue_inertgas_saturation > pres_respiration)
38
+ − 344 {
246
+ − 345 super_saturation =
+ − 346 (tissue_inertgas_saturation - pres_respiration) / (ceiling - pres_respiration);
+ − 347
+ − 348 if (super_saturation > pDecoInfo->super_saturation)
+ − 349 pDecoInfo->super_saturation = super_saturation;
38
+ − 350 }
+ − 351 }
+ − 352 }
+ − 353
+ − 354
253
+ − 355 static float buehlmann_tissue_test_tolerance(float depth_in_bar_absolute)
38
+ − 356 {
+ − 357 float tissue_inertgas_saturation;
+ − 358 float inertgas_a;
+ − 359 float inertgas_b;
+ − 360 float inertgas_tolerance;
+ − 361 float gf_minus_1;
+ − 362
+ − 363 gf_minus_1 = gGF_value - 1.0f;
+ − 364
+ − 365 for (int ci = 0; ci < 16; ci++)
+ − 366 {
+ − 367 if(gTissue_helium_bar[ci] == 0)
+ − 368 {
+ − 369 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 370 inertgas_a = buehlmann_N2_a[ci];
+ − 371 inertgas_b = buehlmann_N2_b[ci];
+ − 372 }
+ − 373 else
+ − 374 {
+ − 375 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 376 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 377 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 378 }
+ − 379 inertgas_tolerance = ( (gGF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( gGF_value * inertgas_a );
+ − 380 if(inertgas_tolerance < tissue_inertgas_saturation)
250
+ − 381 return tissue_inertgas_saturation - inertgas_tolerance; // positive
38
+ − 382 }
250
+ − 383 return tissue_inertgas_saturation - inertgas_tolerance; // negative
38
+ − 384 }
+ − 385
+ − 386
255
+ − 387 static void ambient_bar_to_deco_stop_depth_bar(SDiveSettings *pDiveSettings, float ceiling)
38
+ − 388 {
+ − 389 int i;
+ − 390
+ − 391 ceiling -= gSurface_pressure_bar;
+ − 392
+ − 393 if(ceiling <= 0)
+ − 394 {
255
+ − 395 gStop.depth = pDiveSettings->last_stop_depth_bar;
38
+ − 396 gStop.id = 0;
+ − 397 return;
+ − 398 }
+ − 399
255
+ − 400 if((ceiling - pDiveSettings->last_stop_depth_bar) <= 0)
38
+ − 401 {
255
+ − 402 gStop.depth = pDiveSettings->last_stop_depth_bar;
38
+ − 403 gStop.id = 0;
+ − 404 return;
+ − 405 }
+ − 406
255
+ − 407 gStop.depth = pDiveSettings->input_second_to_last_stop_depth_bar;
38
+ − 408 gStop.id = 1;
255
+ − 409 ceiling -= pDiveSettings->input_second_to_last_stop_depth_bar;
38
+ − 410
+ − 411 if(ceiling <= 0)
+ − 412 return;
+ − 413
+ − 414 for(i = 1; i < (DECOINFO_STRUCT_MAX_STOPS - 2); i++)
+ − 415 {
255
+ − 416 ceiling -= pDiveSettings->input_next_stop_increment_depth_bar;
38
+ − 417 if(ceiling <= 0)
+ − 418 break;
+ − 419 }
255
+ − 420 gStop.depth += i * pDiveSettings->input_next_stop_increment_depth_bar;
38
+ − 421 gStop.id += i;
+ − 422 return;
+ − 423 }
+ − 424
255
+ − 425 static float next_stop_depth_input_is_actual_stop_id(SDiveSettings *pDiveSettings, int actual_id)
38
+ − 426 {
+ − 427 if(actual_id == 0)
+ − 428 return 0;
+ − 429
+ − 430 if(actual_id == 1)
255
+ − 431 return pDiveSettings->last_stop_depth_bar;
38
+ − 432
+ − 433 actual_id -= 2;
255
+ − 434 return pDiveSettings->input_second_to_last_stop_depth_bar + (actual_id * pDiveSettings->input_next_stop_increment_depth_bar);
38
+ − 435 }
+ − 436
255
+ − 437 static int ascend_with_all_gaschanges(SDiveSettings *pDiveSettings, float pressure_decrease)
38
+ − 438 {
+ − 439 float pressureTop, pressureTop_tmp, pressureBottom, pressureChange, ascendrate_in_seconds_for_one_bar, pressure_difference;
51
+ − 440 int time_for_ascend = 0;
38
+ − 441 int seconds;
+ − 442 int i;
+ − 443
255
+ − 444 ascendrate_in_seconds_for_one_bar = 60 * 10 / pDiveSettings->ascentRate_meterperminute;
38
+ − 445
+ − 446 if(fabsf(gPressure - gSurface_pressure_bar) < PRESSURE_HALF_METER)
+ − 447 {
+ − 448 gPressure = gSurface_pressure_bar;
+ − 449 return 0;
+ − 450 }
+ − 451
+ − 452 pressureTop = gPressure - pressure_decrease;
+ − 453 if( gSurface_pressure_bar > pressureTop)
+ − 454 pressureTop = gSurface_pressure_bar;
+ − 455 pressureBottom = gPressure;
+ − 456 seconds = 0;
+ − 457 do{
+ − 458 pressureTop_tmp = pressureTop;
+ − 459 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 460 {
255
+ − 461 if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
38
+ − 462 break;
255
+ − 463 pressureChange = gSurface_pressure_bar + ((float)pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10;
38
+ − 464 if(pressureBottom <= pressureChange)
+ − 465 {
+ − 466 gGas_id = i;
+ − 467 }
+ − 468 else
+ − 469 {
+ − 470 break;
+ − 471 }
+ − 472
+ − 473 }
+ − 474 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 475 {
255
+ − 476 if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
38
+ − 477 break;
255
+ − 478 pressureChange = gSurface_pressure_bar + ((float)pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero)/ 10;
38
+ − 479 if((pressureChange < pressureBottom) && (pressureChange > pressureTop))
+ − 480 {
+ − 481 pressureTop_tmp = pressureChange;
+ − 482 }
+ − 483 }
+ − 484 pressure_difference = pressureBottom - pressureTop_tmp;
+ − 485 if(pressure_difference > 0.0001f)
+ − 486 {
+ − 487 time_for_ascend = (int)ceilf(pressure_difference * ascendrate_in_seconds_for_one_bar);
255
+ − 488 decom_tissues_exposure_stage_schreiner(time_for_ascend, &pDiveSettings->decogaslist[gGas_id],
38
+ − 489 pressureBottom, pressureTop_tmp, gTissue_nitrogen_bar, gTissue_helium_bar);
255
+ − 490 decom_oxygen_calculate_cns_stage_SchreinerStyle(time_for_ascend,&pDiveSettings->decogaslist[gGas_id],
38
+ − 491 pressureBottom, pressureTop_tmp, &gCNS);
+ − 492 }
+ − 493 pressureBottom = pressureTop_tmp;
+ − 494 seconds += time_for_ascend;
+ − 495 }while(pressureTop_tmp > pressureTop);
+ − 496 gPressure = pressureTop;
+ − 497 return seconds;
+ − 498 }
+ − 499
+ − 500
255
+ − 501 static float get_gf_at_pressure(SDiveSettings *pDiveSettings, float pressure)
38
+ − 502 {
+ − 503 float gfSteigung = 0.0f;
+ − 504
+ − 505 if(gGF_low_depth_bar < 0)
+ − 506 gGF_low_depth_bar = PRESSURE_THREE_METER; // just to prevent erratic behaviour if variable is not set
+ − 507
255
+ − 508 gfSteigung = ((float)(pDiveSettings->gf_high - pDiveSettings->gf_low))/ gGF_low_depth_bar;
38
+ − 509
+ − 510
+ − 511 if((pressure - gSurface_pressure_bar) <= PRESSURE_HALF_METER)
255
+ − 512 return ((float)pDiveSettings->gf_high) / 100.0f;
38
+ − 513
+ − 514 if(pressure >= gSurface_pressure_bar + gGF_low_depth_bar)
255
+ − 515 return ((float)pDiveSettings->gf_low) / 100.0f;
38
+ − 516
255
+ − 517 return (pDiveSettings->gf_high - gfSteigung * (pressure - gSurface_pressure_bar) )/ 100.0f;
38
+ − 518 }
+ − 519
291
+ − 520 #define MAX_NDL 240
257
+ − 521 static int buehlmann_calc_ndl(SDiveSettings *pDiveSettings)
38
+ − 522 {
+ − 523 float local_tissue_nitrogen_bar[16];
+ − 524 float local_tissue_helium_bar[16];
+ − 525 int i;
257
+ − 526 int ndl = 0;
38
+ − 527
+ − 528 //Check ndl always use gHigh
255
+ − 529 gGF_value = ((float)pDiveSettings->gf_high) / 100.0f;
38
+ − 530 //10 minutes steps
291
+ − 531 while(ndl < (MAX_NDL * 60))
38
+ − 532 {
+ − 533 memcpy(local_tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16));
+ − 534 memcpy(local_tissue_helium_bar, gTissue_helium_bar, (4*16));
+ − 535 //
257
+ − 536 ndl += 600;
255
+ − 537 decom_tissues_exposure2(600, &pDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar);
+ − 538 decom_oxygen_calculate_cns_exposure(600,&pDiveSettings->decogaslist[gGas_id],gPressure,&gCNS);
38
+ − 539 buehlmann_backup_and_restore(true);
255
+ − 540 if(dive1_check_deco(pDiveSettings))
38
+ − 541 {
+ − 542 buehlmann_backup_and_restore(false);
+ − 543 break;
+ − 544 }
+ − 545 buehlmann_backup_and_restore(false);
+ − 546 }
+ − 547
291
+ − 548 if(ndl < (MAX_NDL * 60))
257
+ − 549 ndl -= 600;
38
+ − 550
291
+ − 551 if(ndl > (MAX_NDL/2 * 60))
257
+ − 552 return ndl;
38
+ − 553
+ − 554 // refine
+ − 555 memcpy(gTissue_nitrogen_bar, local_tissue_nitrogen_bar, (4*16));
+ − 556 memcpy(gTissue_helium_bar, local_tissue_helium_bar, (4*16));
+ − 557
+ − 558 //One minutes step
256
+ − 559 for(i = 0; i < 10; i++)
38
+ − 560 {
257
+ − 561 ndl += 60;
255
+ − 562 decom_tissues_exposure2(60, &pDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar);
+ − 563 decom_oxygen_calculate_cns_exposure(60,&pDiveSettings->decogaslist[gGas_id],gPressure,&gCNS);
38
+ − 564 buehlmann_backup_and_restore(true);
255
+ − 565 if(dive1_check_deco(pDiveSettings))
38
+ − 566 break;
+ − 567 buehlmann_backup_and_restore(false);
+ − 568 }
257
+ − 569 return ndl;
38
+ − 570 }
+ − 571
+ − 572
+ − 573 // ===============================================================================
+ − 574 // dive1_check_deco
+ − 575 /// @brief for NDL calculations
+ − 576 /// 160614 using ceilingOther and not ceiling
+ − 577 // ===============================================================================
255
+ − 578 static _Bool dive1_check_deco(SDiveSettings *pDiveSettings)
38
+ − 579 {
+ − 580 // gGF_value is set in call routine;
+ − 581 // internes Backup!
+ − 582
+ − 583 // calc like in deco
+ − 584 float ceiling;
+ − 585 float ceilingOther; // new hw 160614
+ − 586
+ − 587 ceiling = tissue_tolerance();
255
+ − 588 ambient_bar_to_deco_stop_depth_bar(pDiveSettings, ceiling); // this will set gStop.depth :-) (and gStop.id)
38
+ − 589
+ − 590 // set the base for all upcoming parameters
+ − 591 ceilingOther = gStop.depth + gSurface_pressure_bar;
+ − 592
+ − 593 // modify parameters if there is ascend or parameter fine adjustment
+ − 594 if(ceilingOther < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling
+ − 595 {
+ − 596 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr.
+ − 597 while(((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER)))
+ − 598 {
255
+ − 599 ascend_with_all_gaschanges(pDiveSettings, PRESSURE_TEN_METER);
38
+ − 600 ceiling = tissue_tolerance();
+ − 601 }
+ − 602 while(((gPressure - PRESSURE_THREE_METER )> gSurface_pressure_bar) && (ceiling < gPressure))
+ − 603 {
255
+ − 604 ascend_with_all_gaschanges(pDiveSettings, PRESSURE_THREE_METER);
38
+ − 605 ceiling = tissue_tolerance();
+ − 606 }
+ − 607 }
255
+ − 608 return ceiling > gSurface_pressure_bar;
38
+ − 609 }
+ − 610
250
+ − 611 // compute ceiling recursively, with a resolution of 10cm. Notice
+ − 612 // that the initial call shall guarantee that the found ceiling
+ − 613 // is between low and high parameters.
+ − 614 static float compute_ceiling(float low, float high)
38
+ − 615 {
250
+ − 616 if ((high - low) < 0.01)
+ − 617 return low;
+ − 618 else {
+ − 619 float next_pressure_absolute = (low + high)/2;
+ − 620 float test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute);
+ − 621 if (test_result < 0)
+ − 622 return compute_ceiling(low, next_pressure_absolute);
+ − 623 else
+ − 624 return compute_ceiling(next_pressure_absolute, high);
+ − 625 }
+ − 626 }
38
+ − 627
250
+ − 628 void buehlmann_ceiling_calculator(SLifeData *pLifeData, SDecoinfo *pDecoInfo)
+ − 629 {
+ − 630 float ceiling;
224
+ − 631
261
+ − 632 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16));
+ − 633 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16));
+ − 634
250
+ − 635 // this is just performance optimizing. The code below runs just fine
+ − 636 // without this. There is never a ceiling in NDL deco state
+ − 637 if (!pDecoInfo->output_time_to_surface_seconds) {
+ − 638 pDecoInfo->output_ceiling_meter = 0;
+ − 639 return;
38
+ − 640 }
+ − 641
250
+ − 642 ceiling = compute_ceiling(pLifeData->pressure_surface_bar, 1.0f + pLifeData->max_depth_meter/10.0f);
+ − 643 pDecoInfo->output_ceiling_meter = (ceiling - pLifeData->pressure_surface_bar) * 10.0f;
38
+ − 644 }