Mercurial > public > mk2
changeset 509:103051b4d9c1
NEW NDL analytic model (Erik Baker's formula)
author | JeanDo |
---|---|
date | Sun, 20 Nov 2011 23:14:18 +0100 |
parents | b595569e4bcc |
children | 6c0bf50610f7 |
files | code_part1/OSTC_code_c_part2/p2_deco.c code_part1/OSTC_code_c_part2/p2_deco.o |
diffstat | 2 files changed, 100 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/code_part1/OSTC_code_c_part2/p2_deco.c Sun Nov 20 22:52:13 2011 +0100 +++ b/code_part1/OSTC_code_c_part2/p2_deco.c Sun Nov 20 23:14:18 2011 +0100 @@ -103,7 +103,7 @@ #include "p2_definitions.h" #define TEST_MAIN -#include "shared_definitions.h" +#include "../OSTC_code_asm_part1/shared_definitions.h" // Water vapour partial pressure in the lumb. #define ppWater 0.0627 @@ -129,8 +129,6 @@ static void clear_deco_table(void); static unsigned char update_deco_table(void); -static void backup_sim_pres_tissue(void); -static void restore_sim_pres_tissue(void); static void sim_tissue(PARAMETER unsigned char period); static void sim_limit(PARAMETER float GF_current); static void sim_extra_time(void); @@ -193,6 +191,8 @@ static float var_He_b; // Bühlmann b, for current He tissue. static float var_N2_e; // Exposition, for current N2 tissue. static float var_He_e; // Exposition, for current He tissue. +static float var_N2_ht; // Half-time for current N2 tissue. +static float var_He_ht; // Half-time for current N2 tissue. static float pres_diluent; // new in v.101 static float const_ppO2; // new in v.101 @@ -216,14 +216,12 @@ float pres_tissue_N2[NUM_COMP]; float pres_tissue_He[NUM_COMP]; +float sim_pres_tissue_N2[NUM_COMP]; // 16 floats = 64 bytes. +float sim_pres_tissue_He[NUM_COMP]; // 16 floats = 64 bytes. //---- Bank 7 parameters ----------------------------------------------------- #pragma udata bank7=0x700 - -float sim_pres_tissue_N2[NUM_COMP]; // 32 floats = 128 bytes. -float sim_pres_tissue_He[NUM_COMP]; // 32 floats = 128 bytes. -static float sim_pres_tissue_backup_N2[NUM_COMP]; -static float sim_pres_tissue_backup_He[NUM_COMP]; +// EMPTY ... //---- Bank 8 parameters ----------------------------------------------------- #pragma udata bank8=0x800 @@ -680,11 +678,40 @@ } ////////////////////////////////////////////////////////////////////////////// +// read buhlmann tables for compatriment ci +// +static void read_buhlmann_ht(void) +{ + +#ifndef CROSS_COMPILE + // Note: we don't use far rom pointer, because the + // 24 bits is to complex, hence we have to set + // the UPPER page ourself... + // --> Set zero if tables are moved to lower pages ! + _asm + movlw 1 + movwf TBLPTRU,0 + _endasm +#endif + + assert( 0 <= ci && ci < NUM_COMP ); + { + overlay rom const float* ptr = &buhlmann_ht[2*ci]; + var_N2_ht = *ptr++; + var_He_ht = *ptr++; + } + + assert( 4.0 <= var_N2_ht && var_N2_ht <= 635.0 ); + assert( 1.5099 <= var_He_ht && var_He_ht <= 240.03 ); +} + +////////////////////////////////////////////////////////////////////////////// // calc_nextdecodepth // // new in v.102 // // INPUT, changing during dive: +// temp_deco // low_depth // // INPUT, fixed during dive: @@ -717,7 +744,7 @@ assert( depth >= -0.2 ); // Allow for 200mbar of weather change. //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ - if (char_I_deco_model == 1) + if( char_I_deco_model != 0 ) { if( depth >= low_depth ) sim_limit( GF_low ); @@ -1113,7 +1140,7 @@ ////////////////////////////////////////////////////////////////////////////// // // Input: calc_N2_ratio, calc_He_ratio : simulated gas mix. -// temp_deco : simulated respiration pressure + security offset (deco_distance) +// temp_deco : simulated respiration pressure // float_deco_distance : security factor. // Water-vapor pressure inside limbs (ppWater). // @@ -1265,6 +1292,9 @@ case 0: //---- bottom time ----------------------------------------------- default: + gas_switch_find_current(); // Lookup for current gas & time. + gas_switch_set(); // setup calc_ratio's + calc_nullzeit(); check_ndl(); char_O_deco_status = 2; // calc ascent next time. @@ -1275,9 +1305,6 @@ // Check proposed gas at begin of ascent simulation sim_dive_mins = int_I_divemins; // Init current time. - gas_switch_find_current(); // Lookup for current gas & time. - gas_switch_set(); // setup calc_ratio's - backup_gas_used = sim_gas_last_used; // And save for later simu steps. backup_gas_depth = sim_gas_last_depth; // And save for later simu steps. backup_gas_delay = sim_gas_delay; @@ -1667,7 +1694,7 @@ // *BUT* calc_tissue() is used to compute bottom time, // hence what would happend at surface, // hence at GF_high. - if( char_I_deco_model == 1 ) + if( char_I_deco_model != 0 ) p = ( p - var_N2_a * GF_high) * var_N2_b / (GF_high + var_N2_b * (1.0 - GF_high)); else @@ -1690,68 +1717,69 @@ // // calculates the remaining bottom time // -// unchanged in v.101 +// 2011-11-20 jDG: Changed (beta 2.06) to use Eric Baker's direct NDL formula. +// +// Input: pres_respiration +// Output: char_O_nullzeit // static void calc_nullzeit(void) { - overlay unsigned char loop; - update_startvalues(); - - char_O_nullzeit = 0; - for(loop = 1; loop <= 17; loop++) - { - backup_sim_pres_tissue(); - sim_tissue(2); // 10 min. - sim_limit(GF_high); + overlay float Pin; + + temp_deco = pres_respiration; + sim_alveolar_presures(); + Pin = ppN2 + ppHe; - if( sim_lead_tissue_limit > pres_surface ) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately - { - restore_sim_pres_tissue(); - break; - } - // Validate once we know its good. - char_O_nullzeit += 10; - } + char_O_nullzeit = 240; + for(ci=0; ci<NUM_COMP; ci++) + { + //---- Compute composite A/B values and half times for the mix ------- + overlay float N2 = pres_tissue_N2[ci]; + overlay float He = pres_tissue_He[ci]; + overlay float p = N2 + He; - if (char_O_nullzeit < 60) - { - for(loop=1; loop <= 10; loop++) - { - sim_tissue(1); // 1 min - sim_limit(GF_high); + read_buhlmann_ht(); + var_N2_ht = (var_N2_ht * N2 + var_He_ht * He) / p; - if( sim_lead_tissue_limit > pres_surface) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately - break; - char_O_nullzeit++; - } - } -} + read_buhlmann_coefficients(); + var_N2_a = (var_N2_a * N2 + var_He_a * He) / p; + var_N2_b = (var_N2_b * N2 + var_He_b * He) / p; + + //---- Calc time for that tissue ------------------------------------- + // Erik Baker's formula: + // M0 (M-value at surface) = var_N2_a + pres_surface/var_N2_b + // Pin = respirated pressure ppN2 + ppHe + // p = pressure inside tissue + // 0.6931 = log(2) + // NDL(ci) = log((Pin - p)/(Pin - M0))/log(2) * ht + // + if( Pin > p ) // Only when on-gasing + { + overlay float M0 = (var_N2_a + pres_surface/var_N2_b); -////////////////////////////////////////////////////////////////////////////// -// backup_sim_pres_tissue -// -void backup_sim_pres_tissue(void) -{ - overlay unsigned char x; + // Apply security margin when using the GF model + if( char_I_deco_model != 0 ) + M0 = GF_high * (M0 - pres_surface) + pres_surface; - for(x=0; x<NUM_COMP; x++) - { - sim_pres_tissue_backup_N2[x] = sim_pres_tissue_N2[x]; - sim_pres_tissue_backup_He[x] = sim_pres_tissue_He[x]; - } -} + if( Pin > M0 ) + { + overlay unsigned char indl; + + overlay float ndl = log((Pin - p)/(Pin - M0)) * var_N2_ht/0.6931; -////////////////////////////////////////////////////////////////////////////// -// restore_sim_pres_tissue -// -void restore_sim_pres_tissue(void) -{ - overlay unsigned char x; + // Apply non-GF model security margins: + // Saturation factor will be applied to gas loading, accelerating + // loading, hence we should decrease NDL accordingly. + if( char_I_deco_model == 0) + ndl /= float_saturation_multiplier; - for(x=0; x<NUM_COMP; x++) - { - sim_pres_tissue_N2[x] = sim_pres_tissue_backup_N2[x]; - sim_pres_tissue_He[x] = sim_pres_tissue_backup_He[x]; + if( ndl < 0.0f ) ndl = 0.0f; + if( ndl > 254.5f ) ndl = 255.0f; + indl = (unsigned char)(ndl + 0.5f); + if( indl < char_O_nullzeit ) + char_O_nullzeit = indl; + } + } } } @@ -1862,7 +1890,7 @@ // Actual values are in the 1.5 .. 1.0 range (for a GF=30%), // so that can change who is the leading gas... // Note: Also depends of the GF_current... - if( char_I_deco_model == 1 ) + if( char_I_deco_model != 0 ) p = ( p - var_N2_a * GF_current) / (GF_current / var_N2_b + 1.0 - GF_current); else @@ -1974,7 +2002,7 @@ // correction due to gradient factor. To compute the actual // current GF, we need to (re-)compute the raw ambiant-pressure // limit from the Bühlmann model. - if( char_I_deco_model == 1 ) + if( char_I_deco_model != 0 ) { ci = char_O_gtissue_no; read_buhlmann_coefficients(); @@ -1991,7 +2019,7 @@ } char_O_gradient_factor = (unsigned char)(gf+0.5f); - if (char_I_deco_model == 1) // calculate relative gradient factor + if( char_I_deco_model != 0 ) // calculate relative gradient factor { overlay float rgf; @@ -2031,43 +2059,26 @@ // void deco_calc_desaturation_time(void) { - overlay rom const float *ptr; - RESET_C_STACK assert( 800 < int_I_pres_surface && int_I_pres_surface < 1100 ); assert( 0 < char_I_desaturation_multiplier && char_I_desaturation_multiplier <= 100 ); -#ifndef CROSS_COMPILE - // Note: we don't use far rom pointer, because the - // 24 bits is to complex, hence we have to set - // the UPPER page ourself... - // --> Set zero if tables are moved to lower pages ! - _asm - movlw 1 - movwf TBLPTRU,0 - _endasm -#endif - N2_ratio = 0.7902; // FIXED sum as stated in bühlmann pres_surface = int_I_pres_surface * 0.001; ppN2 = N2_ratio * (pres_surface - ppWater); int_O_desaturation_time = 0; float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); - ptr = &buhlmann_ht[0]; for(ci=0; ci<NUM_COMP; ci++) { - overlay float var_N2_halftime = *ptr++; - overlay float var_He_halftime = *ptr++; overlay unsigned short desat_time; // For a particular compartiment, in min. overlay float temp1; overlay float temp2; overlay float temp3; overlay float temp4; - assert( 4.0 <= var_N2_halftime && var_N2_halftime <= 635.0 ); - assert( 1.5099 <= var_He_halftime && var_He_halftime <= 240.03 ); + read_buhlmann_ht(); // saturation_time (for flight) and N2_saturation in multiples of halftime // version v.100: 1.1 = 10 percent distance to totally clean (totally clean is not possible, would take infinite time ) @@ -2088,7 +2099,7 @@ // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. // minus because log is negative. temp1 = log(1.0 - temp1) / -0.6931; // temp1 is the multiples of half times necessary. - temp2 = var_N2_halftime * temp1 / float_desaturation_multiplier; // time necessary (in minutes ) for complete desaturation (see comment about 5 percent) , new in v.101: float_desaturation_multiplier + temp2 = var_N2_ht * temp1 / float_desaturation_multiplier; // time necessary (in minutes ) for complete desaturation (see comment about 5 percent) , new in v.101: float_desaturation_multiplier } else @@ -2111,7 +2122,7 @@ temp3 = log(1.0 - temp3) / -0.6931; // temp1 is the multiples of half times necessary. // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. // minus because log is negative - temp4 = var_He_halftime * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier + temp4 = var_He_ht * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier } else {