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 "arm_math.h"
+ − 13 #include <math.h>
+ − 14 #include <stdbool.h>
+ − 15 #include "buehlmann.h"
+ − 16 #include "decom.h"
+ − 17
+ − 18
+ − 19 extern const float helium_time_constant[16];
+ − 20 extern const float nitrogen_time_constant[16];
+ − 21
+ − 22 extern const float buehlmann_N2_a[];
+ − 23 extern const float buehlmann_N2_b[];
+ − 24 extern const float buehlmann_He_a[];
+ − 25 extern const float buehlmann_He_b[];
+ − 26
+ − 27
+ − 28 /*
+ − 29 typedef struct
+ − 30 {
+ − 31 float *pointer_array_tissue_nitrogen_bar;
+ − 32 float *pointer_array_tissue_helium_bar;
+ − 33 char gf_value;
+ − 34
+ − 35 float output_ceiling_ambient_bar_or_input;
+ − 36 _Bool output_ceiling_tolerated_if_ceiling_used_as_input;
+ − 37 } tissue_test_tolerance_struct;
+ − 38 */
+ − 39 typedef struct
+ − 40 {
+ − 41 float depth;
+ − 42 int id;
+ − 43 } SStop;
+ − 44
+ − 45 #define DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS 59940 // 999 minuten; before: 18000 // 5(h) * 60(min) * 60 sec = 18000 sec
+ − 46 #define DECO_STOPS_MAX_TTS_FOR_EVERY_SECOND_CALC_IN_SECONDS 7200
+ − 47 #define NINETY_NINE_MINUTES_IN_SECONDS 59940
+ − 48
+ − 49 # define PRESSURE_TEN_METER 1.0f
+ − 50 # define PRESSURE_THREE_METER 0.333334f
+ − 51 # define PRESSURE_150_CM 0.15f
+ − 52 # define PRESSURE_HALF_METER 0.05f
+ − 53 /*
+ − 54 # define PRESSURE_150_CM_MBAR 150
+ − 55 # define PRESSURE_TWO_M_MBAR 200
+ − 56 # define PRESSURE_FIVE_M_MBAR 500
+ − 57 # define PRESSURE_TEN_M_MBAR 1000
+ − 58 # define PRESSURE_120_METER 12.0
+ − 59 */
+ − 60 /*
+ − 61 _____________________________________________________________
+ − 62 */
+ − 63
+ − 64
+ − 65 void buehlmann_backup_and_restore(_Bool backup_restore_otherwise);
+ − 66 float tissue_tolerance(void);
+ − 67 void ambient_bar_to_deco_stop_depth_bar(float ceiling);
+ − 68 int ascend_with_all_gaschanges(float pressure_decrease);
+ − 69 float next_stop_depth_input_is_actual_stop_id(int actual_id);
+ − 70 float get_gf_at_pressure(float pressure);
+ − 71 void buehlmann_calc_ndl(void);
+ − 72 _Bool dive1_check_deco(void);
+ − 73 uint8_t buehlmann_tissue_test_tolerance(float depth_in_bar_absolute);
+ − 74
+ − 75 /*
+ − 76 _____________________________________________________________
+ − 77 */
+ − 78
+ − 79 SDecoinfo gDecotable;
+ − 80 float gSurface_pressure_bar;
+ − 81 float gPressure;
+ − 82 int gGas_id;
+ − 83 float gTTS;
+ − 84 float gTissue_nitrogen_bar[16];
+ − 85 float gTissue_helium_bar[16];
130
+ − 86 float gGF_value;
38
+ − 87 float gCNS;
+ − 88 //float gMax_ceiling_bar = 0;
+ − 89 int gNDL;
+ − 90
+ − 91
+ − 92 //SLifeData *pLifeData;
+ − 93 SDiveSettings *pBuDiveSettings;
+ − 94 SDecoinfo* pDecolistBuehlmann;
+ − 95 //signed char gGaschange_decreasing_depth_gas_id[BUEHLMANN_STRUCT_MAX_GASES];
+ − 96 float gGF_low_depth_bar;
+ − 97 SStop gStop;
+ − 98
+ − 99 void buehlmann_init(void)
+ − 100 {
+ − 101 //gMax_ceiling_bar = 0;
+ − 102 }
+ − 103
+ − 104 void buehlmann_backup_and_restore(_Bool backup_restore_otherwise)
+ − 105 {
+ − 106 static float pressure;
+ − 107 static float gas_id;
+ − 108 static float tts;
+ − 109 static float tissue_nitrogen_bar[16];
+ − 110 static float tissue_helium_bar[16];
+ − 111 static float gf_value;
+ − 112 static int ndl;
+ − 113 static float cns;
+ − 114
+ − 115 if(backup_restore_otherwise)
+ − 116 {
+ − 117 pressure = gPressure;
+ − 118 gas_id = gGas_id;
+ − 119 tts = gTTS;
+ − 120 gf_value = gGF_value;
+ − 121 ndl = gNDL;
+ − 122 cns = gCNS;
+ − 123 memcpy(tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16));
+ − 124 memcpy(tissue_helium_bar, gTissue_helium_bar, (4*16));
+ − 125 }
+ − 126 else
+ − 127 {
+ − 128 gPressure = pressure;
+ − 129 gGas_id = gas_id;
+ − 130 gTTS = tts;
+ − 131 gGF_value = gf_value;
+ − 132 gNDL = ndl;
+ − 133 gCNS = cns;
+ − 134 memcpy(gTissue_nitrogen_bar, tissue_nitrogen_bar, (4*16));
+ − 135 memcpy(gTissue_helium_bar, tissue_helium_bar, (4*16));
+ − 136 }
+ − 137
+ − 138 }
+ − 139 /*void buehlmann__test__saturate_tissues(SBuehlmann *pInput, int seconds)
+ − 140 {
+ − 141 pBuehlmann = pInput;
+ − 142 pInput->dive_time_seconds += seconds;
+ − 143 // internal copying
+ − 144 gSurface_pressure_bar = pBuehlmann->pressure_surface_bar;
+ − 145
+ − 146 gPressure = pBuehlmann->pressure_ambient_bar;
+ − 147 gGas_id = pBuehlmann->actual_gas_id;
+ − 148 memcpy(gTissue_nitrogen_bar, pBuehlmann->tissue_nitrogen_bar, (4*16));
+ − 149 memcpy(gTissue_helium_bar, pBuehlmann->tissue_helium_bar, (4*16));
+ − 150
+ − 151 tissues_exposure_at_gPressure_seconds(seconds);
+ − 152
+ − 153 memcpy(pBuehlmann->tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16));
+ − 154 memcpy(pBuehlmann->tissue_helium_bar, gTissue_helium_bar, (4*16));
+ − 155 }*/
+ − 156
+ − 157 float buehlmann_get_gCNS(void)
+ − 158 {
+ − 159 return gCNS;
+ − 160 }
+ − 161
+ − 162 void buehlmann_calc_deco(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo)
+ − 163 {
+ − 164 float ceiling;
+ − 165 int ascend_time;
+ − 166 int tts_seconds;
+ − 167 float pressure_delta;
+ − 168 float next_depth;
+ − 169 _Bool deco_reached = false;
+ − 170 // tissue_test_tolerance_struct tolerance_data;
+ − 171 unsigned short *stoplist;
+ − 172 int i;
+ − 173
+ − 174 // decom_CreateGasChangeList(pDiveSettings, pLifeData);
+ − 175
+ − 176 gCNS = 0;
+ − 177 pDecoInfo->output_time_to_surface_seconds = 0;
+ − 178 pDecoInfo->output_ndl_seconds = 0;
+ − 179 for(int i=0;i<DECOINFO_STRUCT_MAX_STOPS;i++)
+ − 180 {
+ − 181 pDecoInfo->output_stop_length_seconds[i] = 0;
+ − 182 }
+ − 183 /* make input available global*/
+ − 184 pBuDiveSettings = pDiveSettings;
+ − 185
+ − 186 pDecolistBuehlmann = pDecoInfo;
+ − 187 /* internal copying */
+ − 188 gSurface_pressure_bar = pLifeData->pressure_surface_bar;
+ − 189
+ − 190 gPressure = pLifeData->pressure_ambient_bar;
+ − 191 gGas_id = 0;
+ − 192 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16));
+ − 193 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16));
+ − 194 gGF_value = ((float)pBuDiveSettings->gf_low) / 100.0f;
+ − 195
+ − 196 //
+ − 197 memcpy(&gDecotable, pDecolistBuehlmann, sizeof(SDecoinfo));
+ − 198 stoplist = gDecotable.output_stop_length_seconds;
+ − 199
+ − 200
+ − 201 if(pLifeData->dive_time_seconds < 60)
+ − 202 return;
+ − 203 /* coupling */
+ − 204
+ − 205 /* functions */
+ − 206
+ − 207 // clean stop list
+ − 208 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++)
+ − 209 stoplist[i] = 0;
+ − 210 gTTS = 0;
+ − 211 gNDL = 0;
+ − 212
+ − 213 if(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero >= (gPressure - PRESSURE_150_CM))
+ − 214 {
+ − 215 deco_reached = true;
+ − 216 }
+ − 217
+ − 218
+ − 219 //ascend_with_all_gaschanges(gPressure - gSurface_pressure_bar);
+ − 220 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f;
+ − 221 //iling = tissue_tolerance();
+ − 222 // includes backup for gGF_value
+ − 223 // NDL
+ − 224 buehlmann_backup_and_restore(true); // includes backup for gGF_value
+ − 225 if(!dive1_check_deco() )
+ − 226 {
+ − 227 buehlmann_backup_and_restore(false);
+ − 228 // no deco
+ − 229 pDecolistBuehlmann->output_time_to_surface_seconds = 0;
+ − 230 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++)
+ − 231 pDecolistBuehlmann->output_stop_length_seconds[i] = 0;
+ − 232 // calc NDL
+ − 233 buehlmann_calc_ndl();
+ − 234 pDecolistBuehlmann->output_ndl_seconds = gNDL;
+ − 235 return;
+ − 236 }
+ − 237 buehlmann_backup_and_restore(false);
+ − 238 pDecolistBuehlmann->output_ndl_seconds = 0;
+ − 239
+ − 240 gGF_value = get_gf_at_pressure(gPressure);
+ − 241 //current ceiling at actual position
+ − 242 ceiling = tissue_tolerance();
+ − 243 //if(ceiling < pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero)
+ − 244 //ambient_bar_to_deco_stop_depth_bar(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero);
+ − 245 //else
+ − 246 ambient_bar_to_deco_stop_depth_bar(ceiling);
+ − 247
+ − 248 // set the base for all upcoming parameters
+ − 249 ceiling = gStop.depth + gSurface_pressure_bar;
+ − 250 tts_seconds = 0;
+ − 251
+ − 252 // modify parameters if there is ascend or parameter fine adjustment
+ − 253 if(ceiling < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling
+ − 254 {
+ − 255 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr.
+ − 256 if(ceiling < (gPressure - PRESSURE_TEN_METER) )
+ − 257 { do {
+ − 258 ascend_time = ascend_with_all_gaschanges(PRESSURE_TEN_METER);
+ − 259 tts_seconds += ascend_time;
+ − 260 ceiling = tissue_tolerance();
+ − 261 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS)
+ − 262 {
+ − 263 /* pInput == pBuehlmann */
+ − 264 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS;
+ − 265 return;// NINETY_NINE_MINUTES_IN_SECONDS;
+ − 266 }
+ − 267 } while ((ascend_time > 0 ) && ((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER)));
+ − 268 }
+ − 269 do {
+ − 270 buehlmann_backup_and_restore(true);
+ − 271 ascend_time = ascend_with_all_gaschanges(PRESSURE_THREE_METER);
+ − 272 tts_seconds += ascend_time;
+ − 273 ceiling = tissue_tolerance();
+ − 274 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS)
+ − 275 {
+ − 276 /* pInput == pBuehlmann */
+ − 277 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS;
+ − 278 return;// NINETY_NINE_MINUTES_IN_SECONDS;
+ − 279 }
+ − 280 ambient_bar_to_deco_stop_depth_bar(ceiling);
+ − 281 } while ((ascend_time > 0 ) && ((gStop.depth + gSurface_pressure_bar) < gPressure));
+ − 282
+ − 283 if(gStop.depth + gSurface_pressure_bar > gPressure)
+ − 284 {
+ − 285 gPressure += PRESSURE_THREE_METER;
+ − 286 buehlmann_backup_and_restore(false);
+ − 287 tts_seconds -= ascend_time;
+ − 288 }
+ − 289 // calculate first stop based on tissue saturation within 10 meters of stop
+ − 290 //ambient_bar_to_deco_stop_depth_bar(ceiling);
+ − 291 }
+ − 292 else
+ − 293 {
+ − 294 // initial values, upper code might not be executed (is within 150 cm)
+ − 295 }
+ − 296
+ − 297
+ − 298
+ − 299
+ − 300 if(ceiling > gSurface_pressure_bar)
+ − 301 {
+ − 302
+ − 303 ceiling = gStop.depth + gSurface_pressure_bar;
+ − 304 // ascend the last meters to first stop (especially consider any gas changes around)
+ − 305 pressure_delta = gPressure - ceiling;
+ − 306 ascend_time = (int)ceil(pressure_delta * 50.0f);
+ − 307 tts_seconds += ascend_with_all_gaschanges(pressure_delta);
+ − 308 }
+ − 309 // NDL check
+ − 310 if(ceiling <= gSurface_pressure_bar)
+ − 311 {
+ − 312 /* pInput == pBuehlmann same pointer*/
+ − 313 // NDL with GF_low
+ − 314 pDecolistBuehlmann->output_time_to_surface_seconds = 0;
+ − 315 return;
+ − 316 }
+ − 317 if(ceiling >pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero)
+ − 318 pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = ceiling;
+ − 319
+ − 320 // calc gf loop
+ − 321 if(deco_reached)
+ − 322 gGF_low_depth_bar = pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - gSurface_pressure_bar;
+ − 323 else
+ − 324 gGF_low_depth_bar = ceiling - gSurface_pressure_bar;
+ − 325
+ − 326 while(gStop.depth > 0)
+ − 327 {
+ − 328 do
+ − 329 {
+ − 330 next_depth = next_stop_depth_input_is_actual_stop_id(gStop.id);
+ − 331 gGF_value = get_gf_at_pressure(next_depth + gSurface_pressure_bar);
+ − 332 buehlmann_backup_and_restore(true);
+ − 333 ascend_time = ascend_with_all_gaschanges(gStop.depth - next_depth);
+ − 334 ceiling = tissue_tolerance();
+ − 335 /* pre check actual limit */
+ − 336 if(gDecotable.output_stop_length_seconds[gStop.id] >= 999*60)
+ − 337 {
+ − 338 tts_seconds -= 999*60 - gDecotable.output_stop_length_seconds[gStop.id];
+ − 339 gDecotable.output_stop_length_seconds[gStop.id] = 999*60;
+ − 340 }
+ − 341 else
+ − 342 /* more deco on the actual depth */
+ − 343 if(ceiling > next_depth + gSurface_pressure_bar)
+ − 344 {
+ − 345 next_depth = -1;
+ − 346 buehlmann_backup_and_restore(false);
+ − 347 decom_tissues_exposure2(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); // some seconds at least at each stop
+ − 348 decom_oxygen_calculate_cns_exposure(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure, &gCNS);
+ − 349 gDecotable.output_stop_length_seconds[gStop.id] += 10;
+ − 350 tts_seconds += 10;
+ − 351 }
+ − 352 } while(next_depth == -1);
+ − 353 tts_seconds += ascend_time;
+ − 354 gStop.depth = next_depth;
+ − 355 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 356 {
+ − 357 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
+ − 358 break;
+ − 359 float pressureChange = ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10;
+ − 360 if(gStop.depth <= pressureChange + 0.00001f)
+ − 361 {
+ − 362 gGas_id = i;
+ − 363 }
+ − 364 else
+ − 365 {
+ − 366 break;
+ − 367 }
+ − 368 }
+ − 369 gStop.id--;
+ − 370 }
+ − 371
+ − 372 gDecotable.output_time_to_surface_seconds = tts_seconds;
+ − 373 memcpy(pDecolistBuehlmann, &gDecotable, sizeof(SDecoinfo));
+ − 374 }
+ − 375
+ − 376
+ − 377 float tissue_tolerance(void)
+ − 378 {
+ − 379 float tissue_inertgas_saturation;
+ − 380 float inertgas_a;
+ − 381 float inertgas_b;
+ − 382 float ceiling;
+ − 383 float global_ceiling;
+ − 384 int ci;
+ − 385
+ − 386 global_ceiling = -1;
+ − 387
+ − 388 for (ci = 0; ci < 16; ci++)
+ − 389 {
+ − 390 if(gTissue_helium_bar[ci] == 0)
+ − 391 {
+ − 392 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 393 //
+ − 394 inertgas_a = buehlmann_N2_a[ci];
+ − 395 inertgas_b = buehlmann_N2_b[ci];
+ − 396 }
+ − 397 else
+ − 398 {
+ − 399 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 400 //
+ − 401 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 402 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 403 }
+ − 404 //
+ − 405 ceiling = (inertgas_b * ( tissue_inertgas_saturation - gGF_value * inertgas_a ) ) / (gGF_value - (inertgas_b * gGF_value) + inertgas_b);
+ − 406 if(ceiling > global_ceiling)
+ − 407 global_ceiling = ceiling;
+ − 408 }
+ − 409 return global_ceiling;
+ − 410 }
+ − 411
+ − 412 // hw 161121 for relative gradient
+ − 413 float tissue_tolerance_without_gf_correction(float *tissue_inertgas_saturation_output)
+ − 414 {
+ − 415 float tissue_inertgas_saturation;
+ − 416 float inertgas_a;
+ − 417 float inertgas_b;
+ − 418 float ceiling;
+ − 419 float global_ceiling;
+ − 420 int ci;
+ − 421
+ − 422 global_ceiling = -1;
+ − 423
+ − 424 for (ci = 0; ci < 16; ci++)
+ − 425 {
+ − 426 if(gTissue_helium_bar[ci] == 0)
+ − 427 {
+ − 428 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 429 //
+ − 430 inertgas_a = buehlmann_N2_a[ci];
+ − 431 inertgas_b = buehlmann_N2_b[ci];
+ − 432 }
+ − 433 else
+ − 434 {
+ − 435 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 436 //
+ − 437 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 438 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 439 }
+ − 440 //
+ − 441 ceiling = inertgas_b * ( tissue_inertgas_saturation - inertgas_a );
+ − 442 if(ceiling > global_ceiling)
+ − 443 {
+ − 444 global_ceiling = ceiling;
+ − 445 if(tissue_inertgas_saturation_output)
+ − 446 {
+ − 447 *tissue_inertgas_saturation_output = tissue_inertgas_saturation;
+ − 448 }
+ − 449 }
+ − 450 }
+ − 451 return global_ceiling;
+ − 452 }
+ − 453
+ − 454
+ − 455 uint8_t buehlmann_tissue_test_tolerance(float depth_in_bar_absolute)
+ − 456 {
+ − 457 float tissue_inertgas_saturation;
+ − 458 float inertgas_a;
+ − 459 float inertgas_b;
+ − 460 float inertgas_tolerance;
+ − 461 float gf_minus_1;
+ − 462
+ − 463 gf_minus_1 = gGF_value - 1.0f;
+ − 464
+ − 465 for (int ci = 0; ci < 16; ci++)
+ − 466 {
+ − 467 if(gTissue_helium_bar[ci] == 0)
+ − 468 {
+ − 469 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci];
+ − 470 //
+ − 471 inertgas_a = buehlmann_N2_a[ci];
+ − 472 inertgas_b = buehlmann_N2_b[ci];
+ − 473 }
+ − 474 else
+ − 475 {
+ − 476 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci];
+ − 477 //
+ − 478 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 479 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation;
+ − 480 }
+ − 481 //
+ − 482 inertgas_tolerance = ( (gGF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( gGF_value * inertgas_a );
+ − 483 //
+ − 484 if(inertgas_tolerance < tissue_inertgas_saturation)
+ − 485 return 0;
+ − 486 }
+ − 487 return 1;
+ − 488 }
+ − 489
+ − 490
+ − 491 void ambient_bar_to_deco_stop_depth_bar(float ceiling)
+ − 492 {
+ − 493 int i;
+ − 494
+ − 495 ceiling -= gSurface_pressure_bar;
+ − 496
+ − 497 if(ceiling <= 0)
+ − 498 {
+ − 499 gStop.depth = pBuDiveSettings->last_stop_depth_bar;
+ − 500 gStop.id = 0;
+ − 501 return;
+ − 502 }
+ − 503
+ − 504
+ − 505 //for(int i = 1; i < 10; i++)
+ − 506
+ − 507 if((ceiling - pBuDiveSettings->last_stop_depth_bar) <= 0)
+ − 508 {
+ − 509 gStop.depth = pBuDiveSettings->last_stop_depth_bar;
+ − 510 gStop.id = 0;
+ − 511 return;
+ − 512 }
+ − 513
+ − 514 gStop.depth = pBuDiveSettings->input_second_to_last_stop_depth_bar;
+ − 515 gStop.id = 1;
+ − 516 ceiling -= pBuDiveSettings->input_second_to_last_stop_depth_bar;
+ − 517
+ − 518 if(ceiling <= 0)
+ − 519 return;
+ − 520
+ − 521 for(i = 1; i < (DECOINFO_STRUCT_MAX_STOPS - 2); i++)
+ − 522 {
+ − 523 ceiling -= pBuDiveSettings->input_next_stop_increment_depth_bar;
+ − 524 if(ceiling <= 0)
+ − 525 break;
+ − 526 }
+ − 527 gStop.depth += i * pBuDiveSettings->input_next_stop_increment_depth_bar;
+ − 528 gStop.id += i;
+ − 529 return;
+ − 530 }
+ − 531
+ − 532 float next_stop_depth_input_is_actual_stop_id(int actual_id)
+ − 533 {
+ − 534 if(actual_id == 0)
+ − 535 return 0;
+ − 536
+ − 537 if(actual_id == 1)
+ − 538 return pBuDiveSettings->last_stop_depth_bar;
+ − 539
+ − 540 actual_id -= 2;
+ − 541 return pBuDiveSettings->input_second_to_last_stop_depth_bar + (actual_id * pBuDiveSettings->input_next_stop_increment_depth_bar);
+ − 542 }
+ − 543
+ − 544 int ascend_with_all_gaschanges(float pressure_decrease)
+ − 545 {
+ − 546 float pressureTop, pressureTop_tmp, pressureBottom, pressureChange, ascendrate_in_seconds_for_one_bar, pressure_difference;
51
+ − 547 int time_for_ascend = 0;
38
+ − 548 int seconds;
+ − 549 int i;
+ − 550
+ − 551 ascendrate_in_seconds_for_one_bar = 60 * 10 / pBuDiveSettings->ascentRate_meterperminute;
+ − 552
+ − 553 if(fabsf(gPressure - gSurface_pressure_bar) < PRESSURE_HALF_METER)
+ − 554 {
+ − 555 gPressure = gSurface_pressure_bar;
+ − 556 return 0;
+ − 557 }
+ − 558
+ − 559 pressureTop = gPressure - pressure_decrease;
+ − 560 if( gSurface_pressure_bar > pressureTop)
+ − 561 pressureTop = gSurface_pressure_bar;
+ − 562 pressureBottom = gPressure;
+ − 563 seconds = 0;
+ − 564 do{
+ − 565 pressureTop_tmp = pressureTop;
+ − 566 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 567 {
+ − 568 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
+ − 569 break;
+ − 570 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10;
+ − 571 if(pressureBottom <= pressureChange)
+ − 572 {
+ − 573 gGas_id = i;
+ − 574 }
+ − 575 else
+ − 576 {
+ − 577 break;
+ − 578 }
+ − 579
+ − 580 }
+ − 581 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
+ − 582 {
+ − 583 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0)
+ − 584 break;
+ − 585 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero)/ 10;
+ − 586 if((pressureChange < pressureBottom) && (pressureChange > pressureTop))
+ − 587 {
+ − 588 pressureTop_tmp = pressureChange;
+ − 589 }
+ − 590 }
+ − 591 pressure_difference = pressureBottom - pressureTop_tmp;
+ − 592 if(pressure_difference > 0.0001f)
+ − 593 {
+ − 594 time_for_ascend = (int)ceilf(pressure_difference * ascendrate_in_seconds_for_one_bar);
+ − 595 decom_tissues_exposure_stage_schreiner(time_for_ascend, &pBuDiveSettings->decogaslist[gGas_id],
+ − 596 pressureBottom, pressureTop_tmp, gTissue_nitrogen_bar, gTissue_helium_bar);
+ − 597 decom_oxygen_calculate_cns_stage_SchreinerStyle(time_for_ascend,&pBuDiveSettings->decogaslist[gGas_id],
+ − 598 pressureBottom, pressureTop_tmp, &gCNS);
+ − 599 }
+ − 600 pressureBottom = pressureTop_tmp;
+ − 601 seconds += time_for_ascend;
+ − 602 }while(pressureTop_tmp > pressureTop);
+ − 603 gPressure = pressureTop;
+ − 604 return seconds;
+ − 605 }
+ − 606
+ − 607
+ − 608 float get_gf_at_pressure(float pressure)
+ − 609 {
+ − 610 float gfSteigung = 0.0f;
+ − 611
+ − 612 if(gGF_low_depth_bar < 0)
+ − 613 gGF_low_depth_bar = PRESSURE_THREE_METER; // just to prevent erratic behaviour if variable is not set
+ − 614
+ − 615 gfSteigung = ((float)(pBuDiveSettings->gf_high - pBuDiveSettings->gf_low))/ gGF_low_depth_bar;
+ − 616
+ − 617
+ − 618 if((pressure - gSurface_pressure_bar) <= PRESSURE_HALF_METER)
+ − 619 return ((float)pBuDiveSettings->gf_high) / 100.0f;
+ − 620
+ − 621 if(pressure >= gSurface_pressure_bar + gGF_low_depth_bar)
+ − 622 return ((float)pBuDiveSettings->gf_low) / 100.0f;
+ − 623
+ − 624 return (pBuDiveSettings->gf_high - gfSteigung * (pressure - gSurface_pressure_bar) )/ 100.0f;
+ − 625 }
+ − 626
+ − 627
+ − 628 void buehlmann_calc_ndl(void)
+ − 629 {
+ − 630 float local_tissue_nitrogen_bar[16];
+ − 631 float local_tissue_helium_bar[16];
+ − 632 int i;
+ − 633
+ − 634 gNDL = 0;
+ − 635 //Check ndl always use gHigh
+ − 636 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f;
+ − 637 //10 minutes steps
+ − 638 while(gNDL < (300 * 60))
+ − 639 {
+ − 640 memcpy(local_tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16));
+ − 641 memcpy(local_tissue_helium_bar, gTissue_helium_bar, (4*16));
+ − 642 //
+ − 643 gNDL += 600;
+ − 644 decom_tissues_exposure2(600, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar);
+ − 645 decom_oxygen_calculate_cns_exposure(600,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS);
+ − 646 //tissues_exposure_at_gPressure_seconds(600);
+ − 647 buehlmann_backup_and_restore(true);
+ − 648 if(dive1_check_deco() == true)
+ − 649 {
+ − 650 buehlmann_backup_and_restore(false);
+ − 651 break;
+ − 652 }
+ − 653 buehlmann_backup_and_restore(false);
+ − 654 }
+ − 655
+ − 656 if(gNDL < (300 * 60))
+ − 657 gNDL -= 600;
+ − 658
+ − 659 if(gNDL > (150 * 60))
+ − 660 return;
+ − 661
+ − 662 // refine
+ − 663 memcpy(gTissue_nitrogen_bar, local_tissue_nitrogen_bar, (4*16));
+ − 664 memcpy(gTissue_helium_bar, local_tissue_helium_bar, (4*16));
+ − 665
+ − 666 //One minutes step
+ − 667 for(i = 0; i < 20; i++)
+ − 668 {
+ − 669 gNDL += 60;
+ − 670 //tissues_exposure_at_gPressure_seconds(60);
+ − 671 decom_tissues_exposure2(60, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar);
+ − 672 decom_oxygen_calculate_cns_exposure(60,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS);
+ − 673 buehlmann_backup_and_restore(true);
+ − 674 if(dive1_check_deco() == true)
+ − 675 break;
+ − 676 buehlmann_backup_and_restore(false);
+ − 677 }
+ − 678 //gNDL -= 60;
+ − 679 return;
+ − 680 }
+ − 681
+ − 682
+ − 683 // ===============================================================================
+ − 684 // dive1_check_deco
+ − 685 /// @brief for NDL calculations
+ − 686 /// 160614 using ceilingOther and not ceiling
+ − 687 // ===============================================================================
+ − 688 _Bool dive1_check_deco(void)
+ − 689 {
+ − 690 // gGF_value is set in call routine;
+ − 691 // internes Backup!
+ − 692
+ − 693 // calc like in deco
+ − 694 float ceiling;
+ − 695 float ceilingOther; // new hw 160614
+ − 696
+ − 697 ceiling = tissue_tolerance();
+ − 698 ambient_bar_to_deco_stop_depth_bar(ceiling); // this will set gStop.depth :-) (and gStop.id)
+ − 699
+ − 700 // set the base for all upcoming parameters
+ − 701 ceilingOther = gStop.depth + gSurface_pressure_bar;
+ − 702
+ − 703 // modify parameters if there is ascend or parameter fine adjustment
+ − 704 if(ceilingOther < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling
+ − 705 {
+ − 706 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr.
+ − 707 while(((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER)))
+ − 708 {
+ − 709 ascend_with_all_gaschanges(PRESSURE_TEN_METER);
+ − 710 ceiling = tissue_tolerance();
+ − 711 }
+ − 712 while(((gPressure - PRESSURE_THREE_METER )> gSurface_pressure_bar) && (ceiling < gPressure))
+ − 713 {
+ − 714 ascend_with_all_gaschanges(PRESSURE_THREE_METER);
+ − 715 ceiling = tissue_tolerance();
+ − 716 }
+ − 717 }
+ − 718 if(ceiling <= gSurface_pressure_bar)
+ − 719 return false;
+ − 720 else
+ − 721 return true;
+ − 722 }
+ − 723
+ − 724
+ − 725 void buehlmann_ceiling_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo)
+ − 726 {
+ − 727 float gf_low;
+ − 728 float gf_high;
+ − 729 float gf_delta;
+ − 730 int dv_gf_low_stop_meter;
+ − 731 _Bool test_result;
+ − 732 float next_gf_value;
+ − 733 float next_pressure_absolute;
+ − 734 int depth_in_meter;
+ − 735
+ − 736 gf_low = pDiveSettings->gf_low;
+ − 737 gf_high = pDiveSettings->gf_high;
+ − 738
+ − 739 //
+ − 740 dv_gf_low_stop_meter = (int)((pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - pLifeData->pressure_surface_bar) * 10);
+ − 741 //
+ − 742 if(dv_gf_low_stop_meter < 1)
+ − 743 {
+ − 744 next_gf_value = gf_high; // fix hw 161024
+ − 745 gf_delta = 0;
+ − 746 }
+ − 747 else
+ − 748 {
+ − 749 next_gf_value = gf_high;
+ − 750 gf_delta = gf_high - gf_low;
+ − 751 gf_delta /= dv_gf_low_stop_meter; // gf_delta is delta for each meter now!!
+ − 752 }
+ − 753 //
+ − 754 depth_in_meter = 0;
+ − 755 next_pressure_absolute = pLifeData->pressure_surface_bar;
+ − 756
+ − 757 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16));
+ − 758 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16));
+ − 759 gGF_value = next_gf_value / 100.0f;
+ − 760 //
+ − 761 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute);
+ − 762 //
+ − 763 while(!test_result && depth_in_meter < 200)
+ − 764 {
+ − 765 depth_in_meter += 1;
+ − 766 next_gf_value = fmaxf(gf_low, next_gf_value - gf_delta);
+ − 767 gGF_value = next_gf_value / 100.0f;
+ − 768 next_pressure_absolute += 0.1f; // 1 meter down
+ − 769 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute);
+ − 770 }
+ − 771 //
+ − 772 if(test_result)
+ − 773 {
+ − 774 // old direct paste
+ − 775 pDecoInfo->output_ceiling_meter = depth_in_meter;
+ − 776 // new sub-meter hw 160331
+ − 777 if(depth_in_meter >= 1)
+ − 778 {
+ − 779 for(int i = 0; i < 10; i++)
+ − 780 {
+ − 781 next_gf_value += gf_delta/10.0f;
+ − 782 gGF_value = next_gf_value / 100.0f;
+ − 783 next_pressure_absolute -= 0.01f; // 0.1 meter up
+ − 784 if(!buehlmann_tissue_test_tolerance(next_pressure_absolute))
+ − 785 {
+ − 786 pDecoInfo->output_ceiling_meter -= ((float)i)/10.0f;
+ − 787 break;
+ − 788 }
+ − 789 }
+ − 790 }
+ − 791 }
+ − 792 else
+ − 793 {
+ − 794 pDecoInfo->output_ceiling_meter = 999;
+ − 795 }
+ − 796 }
+ − 797
+ − 798
+ − 799 void buehlmann_relative_gradient_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo)
+ − 800 {
+ − 801 float gf_low;
+ − 802 float gf_high;
+ − 803 float gf_delta;
+ − 804 int dv_gf_low_stop_meter;
+ − 805
+ − 806 float rgf; // relative gradient factor by hwOS p2_deco.c
+ − 807 float temp_tissue;
+ − 808 float limit;
+ − 809 float pres_respiration;
+ − 810 float gf;
+ − 811
+ − 812 gf_low = pDiveSettings->gf_low;
+ − 813 gf_high = pDiveSettings->gf_high;
+ − 814
+ − 815 dv_gf_low_stop_meter = (int)((pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - pLifeData->pressure_surface_bar) * 10);
+ − 816
+ − 817 if(dv_gf_low_stop_meter < 1)
+ − 818 {
+ − 819 gf_delta = 0;
+ − 820 }
+ − 821 else
+ − 822 {
+ − 823 gf_delta = gf_high - gf_low;
+ − 824 gf_delta /= dv_gf_low_stop_meter; // gf_delta is delta for each meter now!!
+ − 825 }
+ − 826
+ − 827
+ − 828 limit = tissue_tolerance_without_gf_correction(&temp_tissue);
+ − 829 pres_respiration = pLifeData->pressure_ambient_bar;
+ − 830
+ − 831 if( temp_tissue <= pres_respiration )
+ − 832 {
+ − 833 gf = 0.0;
+ − 834 }
+ − 835 else
+ − 836 {
+ − 837 gf = (temp_tissue - pres_respiration)
+ − 838 / (temp_tissue - limit)
+ − 839 * 100.0f;
+ − 840 }
+ − 841
+ − 842 if(dv_gf_low_stop_meter < 1)
+ − 843 {
+ − 844 rgf = gf_high;
+ − 845 }
+ − 846 else
+ − 847 {
+ − 848 float temp1 = dv_gf_low_stop_meter;
+ − 849 float temp2 = pLifeData->depth_meter;
+ − 850
+ − 851 if (temp2 <= 0)
+ − 852 rgf = gf_high;
+ − 853 else if (temp2 >= temp1)
+ − 854 rgf = gf_low;
+ − 855 else
+ − 856 rgf = gf_low + (temp1 - temp2)*gf_delta;
+ − 857 }
+ − 858
+ − 859 rgf = gf / rgf;
+ − 860
+ − 861 // avoid discussions about values > 100 below next deco stop
+ − 862 if((rgf > 1.0f) && (pLifeData->depth_meter >= pDecoInfo->output_ceiling_meter))
+ − 863 rgf = 1.0f;
+ − 864
+ − 865 pDecoInfo->output_relative_gradient = rgf;
+ − 866 }