Mercurial > public > mk2
diff code_part1/OSTC_code_c_part2/p2_deco.c @ 217:ce6f16711567
BUGFIX gas switch
+ Make sure not to pass gas switch
+ Don't clobber ratio N2/He when canceling ascent passing gas switch.
+ Build-up GF_low history during the whole dive.
author | JeanDo |
---|---|
date | Thu, 24 Feb 2011 23:22:32 +0100 |
parents | c7e32ff65636 |
children | f4b79292e31f |
line wrap: on
line diff
--- a/code_part1/OSTC_code_c_part2/p2_deco.c Thu Feb 24 23:22:14 2011 +0100 +++ b/code_part1/OSTC_code_c_part2/p2_deco.c Thu Feb 24 23:22:32 2011 +0100 @@ -70,6 +70,7 @@ // 2011/01/25: [jDG] Use CF(54) to reverse deco order. // 2011/02/11: [jDG] Reworked gradient-factor implementation. // 2011/02/13: [jDG] CF55 for additional gas switch delay in decoplan. +// 2011/02/24: [jDG] Fixed inconsistencies introduced by gas switch delays. // // TODO: // + Allow to abort MD2 calculation (have to restart next time). @@ -127,7 +128,10 @@ static void calc_hauptroutine_calc_deco(void); static void sim_ascent_to_first_stop(void); -static void check_gas_switch(void); +static void deepest_gas_switch(void); +static void best_gas_switch(void); +static void set_gas(void); + static void calc_nextdecodepth(void); //---- Bank 4 parameters ----------------------------------------------------- @@ -700,8 +704,8 @@ temp_depth_limit = 0; // stop depth, in meter. } - //---- Check gas change -------------------------------------------------- - check_gas_switch(); // Update temp_depth_limit if there is a change, + //---- Check gas change -------------------------------------------------- + best_gas_switch(); // Update temp_depth_limit if there is a change, // Calculate N2_ratio and He_ratio too. } @@ -861,60 +865,44 @@ } ////////////////////////////////////////////////////////////////////////////// -// Calculate gas switches +// Find deepest available gas. // -// -// Input: N2_ratio, He_ratio. -// deco_gas_change* +// Input: deco_gas_change* // sim_gas_delay, sim_gas_last_used, sim_dive_mins. // -// Output: calc_N2_ratio, calc_He_ratio -// temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch. +// Output: temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch. // -static void check_gas_switch(void) +static void deepest_gas_switch(void) { overlay unsigned char temp_gas_switch = 0; overlay unsigned char switch_deco = 0; - calc_N2_ratio = N2_ratio; - calc_He_ratio = He_ratio; - if (char_I_const_ppO2 == 0) { // Keep selecting the best gas during the ascent simulation. // Add a one meter margin in depth comparaison. if( deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1)) { - calc_N2_ratio = deco_N2_ratio1; - calc_He_ratio = deco_He_ratio1; temp_gas_switch = 1; switch_deco = deco_gas_change1; - } - if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2)) + } + else if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2)) { - calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01; - calc_He_ratio = char_I_deco_He_ratio2 * 0.01; temp_gas_switch = 2; switch_deco = deco_gas_change2; - } - if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3)) + } + else if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3)) { - calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01; - calc_He_ratio = char_I_deco_He_ratio3 * 0.01; temp_gas_switch = 3; switch_deco = deco_gas_change3; } - if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4)) + else if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4)) { - calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01; - calc_He_ratio = char_I_deco_He_ratio4 * 0.01; temp_gas_switch = 4; switch_deco = deco_gas_change4; } - if(deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5)) + else if(deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5)) { - calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01; - calc_He_ratio = char_I_deco_He_ratio5 * 0.01; temp_gas_switch = 5; switch_deco = deco_gas_change5; } @@ -926,9 +914,9 @@ // Should restart gas-switch delay only when gas do changes... // sim_gas_last_used: used to detect just once in each ascent simu. // N2_ratio : used to detect when already breathing that gas. - if( sim_gas_last_used < temp_gas_switch - && sim_gas_delay <= sim_dive_mins - && (calc_N2_ratio != N2_ratio || calc_He_ratio != He_ratio)) + if( temp_depth_limit != switch_deco + && sim_gas_last_used < temp_gas_switch + && sim_gas_delay <= sim_dive_mins ) { sim_gas_last_used = temp_gas_switch; sim_gas_delay = read_custom_function(55); @@ -943,6 +931,115 @@ } else sim_gas_delay = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// Find best (shallowest) available gas. +// +// Input: deco_gas_change* +// sim_gas_delay, sim_gas_last_used, sim_dive_mins. +// +// Output: temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch. +// +static void best_gas_switch(void) +{ + overlay unsigned char temp_gas_switch = 0; + overlay unsigned char switch_deco = 0; + + if (char_I_const_ppO2 == 0) + { + // Keep selecting the best gas during the ascent simulation. + // Add a one meter margin in depth comparaison. + if( deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5)) + { + temp_gas_switch = 5; + switch_deco = deco_gas_change5; + } + else if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4)) + { + temp_gas_switch = 4; + switch_deco = deco_gas_change4; + } + else if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3)) + { + temp_gas_switch = 3; + switch_deco = deco_gas_change3; + } + else if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2)) + { + temp_gas_switch = 2; + switch_deco = deco_gas_change2; + } + else if(deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1)) + { + temp_gas_switch = 1; + switch_deco = deco_gas_change1; + } + } + + // If there is a better gas available + if( temp_gas_switch ) + { + // Should restart gas-switch delay only when gas do changes... + // sim_gas_last_used: used to detect just once in each ascent simu. + // N2_ratio : used to detect when already breathing that gas. + if( sim_gas_last_used < temp_gas_switch + && sim_gas_delay <= sim_dive_mins ) + { + sim_gas_last_used = temp_gas_switch; + sim_gas_delay = read_custom_function(55); + + // Apply depth correction ONLY if CF#55 is not null: + if( sim_gas_delay > 0 ) + { + sim_gas_delay += sim_dive_mins; + temp_depth_limit = switch_deco; + } + } + } + else + sim_gas_delay = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// Calculate gas switches +// +// +// Input: N2_ratio, He_ratio. +// sim_gas_last_used +// +// Output: calc_N2_ratio, calc_He_ratio +// +static void set_gas(void) +{ + switch(sim_gas_last_used) + { + default: + calc_N2_ratio = N2_ratio; + calc_He_ratio = He_ratio; + break; + case 1: + calc_N2_ratio = deco_N2_ratio1; + calc_He_ratio = deco_He_ratio1; + break; + + case 2: + calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01; + calc_He_ratio = char_I_deco_He_ratio2 * 0.01; + break; + case 3: + calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01; + calc_He_ratio = char_I_deco_He_ratio3 * 0.01; + break; + case 4: + calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01; + calc_He_ratio = char_I_deco_He_ratio4 * 0.01; + break; + case 5: + calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01; + calc_He_ratio = char_I_deco_He_ratio5 * 0.01; + break; + } assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 ); assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 ); @@ -1057,10 +1154,8 @@ // static void calc_hauptroutine(void) { - static float backup_GF_step; - static unsigned char backup_low_depth; - static unsigned char backup_gas_used; - static unsigned char backup_gas_delay; + static unsigned char backup_gas_used = 0; + static unsigned char backup_gas_delay = 0; calc_hauptroutine_data_input(); @@ -1087,14 +1182,15 @@ char_O_nullzeit = 0; // Reset bottom time. char_O_deco_status = 0; // Calc bottom-time/nullzeit next iteration. - // Values that should be reset just once for the full real dive - // (not every time we simulate an ascent): - low_depth = 0; // Reset GF history. - backup_low_depth = 255; // backup is empty... - sim_gas_last_used = 0; // Reset gas switch history. - sim_gas_delay = 0; + // Values that should be reset just once for the full real dive. + // This is used to record the lowest stop for the whole dive, + // Including ACCROSS all simulated ascent. + low_depth = 0; + + // Reset gas switch history. + backup_gas_used = sim_gas_last_used = 0; + backup_gas_delay = sim_gas_delay = 0; sim_dive_mins = 0; - break; case 0: //---- bottom time ----------------------------------------------- @@ -1104,15 +1200,11 @@ break; case 2: //---- Simulate ascent to first stop ----------------------------- - // Backup ascention state, so the simulation won't polute the real - // dive data. - backup_GF_step = locked_GF_step; - backup_low_depth = low_depth; - // Check proposed gas at begin of ascent simulation sim_dive_mins = int_I_divemins; // and time. temp_depth_limit = (int)(0.95 + (pres_respiration - pres_surface) / 0.09985) ; // Starts from current real depth. - check_gas_switch(); + best_gas_switch(); + set_gas(); backup_gas_used = sim_gas_last_used;// And save for later simu steps. backup_gas_delay = sim_gas_delay; @@ -1127,14 +1219,10 @@ // If simulation is finished, restore the GF low reference, so that // next ascent simulation is done from the current depth: - if( char_O_deco_status == 0 && backup_low_depth != 255) + if( char_O_deco_status == 0 ) { - locked_GF_step = backup_GF_step; - low_depth = backup_low_depth; sim_gas_last_used = backup_gas_used; sim_gas_delay = backup_gas_delay; - - backup_low_depth = 255; } break; } @@ -1313,6 +1401,7 @@ //---- Then update tissue and decoplan ------------------------------- sim_dive_mins++; // Advance simulated time by 1 minute. + set_gas(); // Apply any simulated gas change, once validated. sim_alveolar_presures(); // Updates ppN2 and ppHe. sim_tissue(1); // Simulate compartiments for 1 minute. } @@ -1364,7 +1453,7 @@ // Check gas change 5 meter below new depth. temp_depth_limit = (temp_deco + 0.5 - pres_surface) / 0.09985; - check_gas_switch(); + deepest_gas_switch(); if( sim_gas_delay > sim_dive_mins ) break;