Mercurial > public > mk2
diff code_part1/OSTC_code_c_part2/p2_deco.c @ 569:ef667587b2b9
BUGFIX Don't forget missed stops
MINOR cleanups for MacOSX compiler.
author | JeanDo |
---|---|
date | Wed, 04 Apr 2012 00:24:32 +0200 |
parents | a4586e115ded |
children | fff1d38625f0 |
line wrap: on
line diff
--- a/code_part1/OSTC_code_c_part2/p2_deco.c Wed Feb 29 22:34:27 2012 +0100 +++ b/code_part1/OSTC_code_c_part2/p2_deco.c Wed Apr 04 00:24:32 2012 +0200 @@ -80,7 +80,9 @@ // 2011/05/17: [jDG] Various cleanups. // 2011/08/08: [jDG] Computes CNS during deco planning ascent. // 2011/11/24: [jDG] Slightly faster and better NDL computation. -// 2011/12/17: [mH] Remove of the useless debug stuff +// 2011/12/17: [mH] Remove of the useless debug stuff +// 2012/02/24: [jDG] Remove missed stop bug. +// 2012/02/25: [jDG] Looking for a more stable LOW grad factor reference. // // TODO: // + Allow to abort MD2 calculation (have to restart next time). @@ -153,14 +155,13 @@ //---- Bank 4 parameters ----------------------------------------------------- #pragma udata bank4=0x400 -static float temp_limit; static float GF_low; static float GF_high; static float GF_delta; -static float low_depth; // Depth of deepest stop static float locked_GF_step; // GF_delta / low_depth static unsigned char temp_depth_limit; +static unsigned char low_depth; // Depth of deepest stop // Simulation context: used to predict ascent. static unsigned char sim_lead_tissue_no; // Leading compatiment number. @@ -343,8 +344,8 @@ static short read_custom_function(PARAMETER unsigned char cf) { #ifdef CROSS_COMPILE - return (cf & 32) ? eeprom.bank1_CF[cf-32].value - : eeprom.bank0_CF[cf ].value; + return (cf & 32) ? eeprom.bank1_CF[cf-32].value.lo + : eeprom.bank0_CF[cf ].value.lo; #else extern unsigned char hi, lo; extern void getcustom15(); @@ -388,7 +389,7 @@ _endasm #endif - assert( 0 <= ci && ci < NUM_COMP ); + assert( ci < NUM_COMP ); // Use an interleaved array (AoS) to access coefficients with a // single addressing. @@ -419,7 +420,7 @@ _endasm #endif - assert( 0 <= ci && ci < NUM_COMP ); + assert( ci < NUM_COMP ); // Integration intervals. switch(period) @@ -470,7 +471,7 @@ _endasm #endif - assert( 0 <= ci && ci < NUM_COMP ); + assert( ci < NUM_COMP ); { overlay rom const float* ptr = &buhlmann_ht[2*ci]; var_N2_ht = *ptr++; @@ -522,106 +523,84 @@ //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ if( char_I_deco_model != 0 ) { - if( depth >= low_depth ) - sim_limit( GF_low ); - else - sim_limit( GF_high - depth * locked_GF_step ); + overlay unsigned char first_stop = 0; + overlay float p; - // Stops are needed ? - if( sim_lead_tissue_limit > pres_surface ) - { - // Compute tolerated depth, for the leading tissue [metre]: - overlay float depth_tol = (sim_lead_tissue_limit - pres_surface) * BAR_TO_METER; - overlay unsigned char first_stop; + sim_limit( GF_low ); + p = sim_lead_tissue_limit - pres_surface; + if( p <= 0.0f ) + goto no_deco_stop; // We can surface directly... - // If ascent is VERY fast, this can be lower than the actual depth... Because - // this happends only in simulation, just forget about it: - if( depth_tol > depth ) - depth_tol = depth; + p *= BAR_TO_METER; + if( p < min_depth ) + goto no_deco_stop; // First stop is higher than 1' ascent. - // Deepest stop, in multiples of 3 metres. - first_stop = 3 * (short)(0.99999 + depth_tol * 0.33333 ); - assert( first_stop < 128 ); + first_stop = 3 * (short)(0.99999 + p*0.333333); + assert( first_stop < 128 ); - // Is it a new deepest needed stop ? If yes this is the reference for - // the varying gradient factor. So reset that: - if( depth_tol > min_depth && depth_tol > low_depth ) - { - // Store the deepest stop depth, as reference for GF_low. - low_depth = depth_tol; - locked_GF_step = GF_delta / low_depth; - } + // Apply correction for the shallowest stop. + if( first_stop == 3 ) // new in v104 + first_stop = char_I_depth_last_deco; // Use last 3m..6m instead. -#if defined(__DEBUG) || defined(CROSS_COMPILE) - { - // Extra testing code to make sure the first_stop formula - // and rounding provides correct depth: - overlay float pres_stop = first_stop * METER_TO_BAR - + pres_surface; + // Store the deepest point needing a deco stop as the LOW reference for GF. + // NOTE: following stops will be validated using this LOW-HIGH gf scale, + // so if we want to keep coherency, we should not validate this stop + // yet, but apply the search to it, as for all the following stops afterward. + if( first_stop > low_depth ) + { + low_depth = first_stop; + locked_GF_step = GF_delta / first_stop; + } - // Keep GF_low until a first stop depth is found: - if( first_stop >= low_depth ) - sim_limit( GF_low ); - else - // current GF is GF_high - alpha (GF_high - GF_low) - // With alpha = currentDepth / maxDepth, hence in [0..1] - sim_limit( GF_high - first_stop * locked_GF_step ); - - // upper limit (lowest pressure tolerated), + 1mbar for rounding...: - assert( sim_lead_tissue_limit < (pres_stop + 0.001) ); - } -#endif + // We have a stop candidate. + // But maybe ascending to the next stop will diminish the constraint, + // because the GF might decrease more than the preassure gradient... + while(first_stop > 0) + { + overlay unsigned char next_stop; // Next depth (0..90m) + overlay float pres_stop; // Next pressure (bar) - // Apply correction for the shallowest stop. - if( first_stop == 3 ) // new in v104 - first_stop = char_I_depth_last_deco; // Use last 3m..6m instead. + // Check max speed, or reaching surface. + if( first_stop <= min_depth ) + goto no_deco_stop; - // Because gradient factor at first_stop might be bigger than at - // current depth, we might ascent a bit more. - // Hence, check all stops until one is indeed higher than tolerated presure: - while(first_stop > 0) - { - overlay unsigned char next_stop; // Next index (0..30) - overlay float pres_stop; // Next depth (0m..90m) + if( first_stop <= char_I_depth_last_deco ) // new in v104 + next_stop = 0; + else if( first_stop == 6 ) + next_stop = char_I_depth_last_deco; + else + next_stop = first_stop - 3; // Index of next (upper) stop. + + // Just a check we are indeed above LOW ref. + assert( next_stop < low_depth ); - // Check max speed, or reaching surface. - if( first_stop <= min_depth ) - break; + // Total preassure at the new stop candidate: + pres_stop = next_stop * METER_TO_BAR + + pres_surface; - // So, there is indeed a stop needed: - need_stop = 1; + // Keep GF_low until a first stop depth is found: + sim_limit( GF_high - next_stop * locked_GF_step ); - if( first_stop <= char_I_depth_last_deco ) // new in v104 - next_stop = 0; - else if( first_stop == 6 ) - next_stop = char_I_depth_last_deco; - else - next_stop = first_stop - 3; // Index of next (upper) stop. + // Check upper limit (lowest pressure tolerated): + if( sim_lead_tissue_limit >= pres_stop ) // check if ascent to next deco stop is ok + goto deco_stop_found; - pres_stop = next_stop * METER_TO_BAR - + pres_surface; + // Else, validate that stop and loop... + first_stop = next_stop; + } + assert( first_stop == 0 ); - // Keep GF_low until a first stop depth is found: - if( next_stop >= low_depth ) - sim_limit( GF_low ); - else - // current GF is GF_high - alpha (GF_high - GF_low) - // With alpha = currentDepth / maxDepth, hence in [0..1] - sim_limit( GF_high - next_stop * locked_GF_step ); +no_deco_stop: + temp_depth_limit = 0; + goto done; - // upper limit (lowest pressure tolerated): - if( sim_lead_tissue_limit >= pres_stop ) // check if ascent to next deco stop is ok - break; - - // Else, validate that stop and loop... - first_stop = next_stop; - } + // next stop is the last validated depth found, aka first_stop +deco_stop_found: + need_stop = 1; // Hit. + temp_depth_limit = first_stop; // Stop depth, in meter. - // next stop is the last validated depth found, aka first_stop - temp_depth_limit = first_stop; // Stop depth, in metre. - } - else - temp_depth_limit = 0; // stop depth, in metre. +done: + ; } else //---- ZH-L16 model ------------------------------------------------- { @@ -787,7 +766,6 @@ calc_dive_interval(); } - ////////////////////////////////////////////////////////////////////////////// // Find current gas in the list (if any). // @@ -895,7 +873,7 @@ // static void gas_switch_set(void) { - assert( 0 <= sim_gas_last_used && sim_gas_last_used <= NUM_GAS ); + assert( sim_gas_last_used <= NUM_GAS ); if( sim_gas_last_used == 0 ) // Gas6 = manualy set gas. { @@ -1044,7 +1022,8 @@ // 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.0; + low_depth = 0; + locked_GF_step = 0.0; // Reset gas switch history. backup_gas_used = sim_gas_last_used = 0; @@ -1784,7 +1763,7 @@ { overlay float rgf; - if( low_depth < 1.5 ) + if( low_depth < 3 ) rgf = GF_high; else { @@ -1977,7 +1956,7 @@ float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); float_saturation_multiplier = char_I_saturation_multiplier * 0.01; - // Make sure SURFACE_DESAT_FACTOR is applyed: + // Make sure SURFACE_DESAT_FACTOR is applied: backup_model = char_I_deco_model; char_I_deco_model = 0; @@ -2213,6 +2192,7 @@ overlay unsigned char i = 0; // Decostop loop counter overlay float actual_ppO2; overlay unsigned char time, t; + overlay unsigned char deepest_first = (read_custom_function(54) == 0); //---- Ascent to surface delay // NOTE: count as if time is spent with bottom pressure, @@ -2232,20 +2212,35 @@ sim_dive_mins++; } - //---- Do all further stops + //---- Do all further stops ------------------------------------------ for(i=0; i<NUM_STOPS; ++i) { - //---- Get next stop - time = char_O_deco_time[i]; - temp_depth_limit = char_O_deco_depth[i] & 0x7F; - if( time == 0 ) break; // End of table: done. + overlay unsigned char switch_gas; + + //---- Get next stop, possibly in reverse order ------------------ + if( deepest_first ) + { + time = char_O_deco_time[i]; + temp_depth_limit = char_O_deco_depth[i]; + } + else + { + time = char_O_deco_time[(NUM_STOPS-1)-i]; + temp_depth_limit = char_O_deco_depth[(NUM_STOPS-1)-i]; + } + if( time == 0 ) continue; - //---- Gas Switch ? - if( char_O_deco_depth[i] & 0x80 ) - if( gas_switch_deepest() ) - gas_switch_set(); - - //---- Convert Depth and N2_ratio to ppO2 + //---- Gas Switch ? ---------------------------------------------- + switch_gas = temp_depth_limit & 0x80; // Switch flag. + temp_depth_limit &= 0x7F; // True stop depth. + + if( switch_gas ) + { + gas_switch_deepest(); + gas_switch_set(); + } + + //---- Convert Depth and N2_ratio to ppO2 ------------------------ actual_ppO2 = (pres_surface + temp_depth_limit * METER_TO_BAR) * (1.0 - calc_N2_ratio - calc_He_ratio); if( actual_ppO2 < 0.0 ) actual_ppO2 = 0.0; @@ -2261,7 +2256,7 @@ } } - // Back to normal mode... + //---- Back to normal mode... -------------------------------------------- char_I_step_is_1min = 0; sim_gas_last_depth = backup_gas_last_depth; sim_gas_last_used = backup_gas_last_used; @@ -2305,7 +2300,7 @@ RESET_C_STACK assert( 60 <= char_I_temp && char_I_temp <= 100 ); - assert( 0 <= int_I_temp && int_I_temp < 5760 ); // Less than 4 days = 96h... + assert( int_I_temp < 5760 ); // Less than 4 days = 96h... int_I_temp = (unsigned short)(((float)int_I_temp * (float)char_I_temp) * 0.01 );