Mercurial > public > mk2
diff code_part1/OSTC_code_c_part2/p2_deco.c @ 203:2d9af08ed0ac
BUGFIX Gas switch
+ To implement gas switch, the ascent engine have to know about dive duration.
author | JeanDo |
---|---|
date | Fri, 18 Feb 2011 00:23:51 +0100 |
parents | e5c484d59a91 |
children | 275befc5f39d |
line wrap: on
line diff
--- a/code_part1/OSTC_code_c_part2/p2_deco.c Wed Feb 16 11:23:46 2011 +0100 +++ b/code_part1/OSTC_code_c_part2/p2_deco.c Fri Feb 18 00:23:51 2011 +0100 @@ -65,7 +65,7 @@ // 12/25/10 v110: split in three files (deco.c, main.c, definitions.h) // 2011/01/20: [jDG] Create a common file included in ASM and C code. // 2011/01/23: [jDG] Added read_custom_function(). -// 2011/01/24: [jDG] Make ascenttime an int. No more overflow! +// 2011/01/24: [jDG] Make ascenttime an short. No more overflow! // 2011/01/25: [jDG] Fusion deco array for both models. // 2011/01/25: [jDG] Use CF(54) to reverse deco order. // 2011/02/11: [jDG] Reworked gradient-factor implementation. @@ -132,7 +132,6 @@ //---- Bank 4 parameters ----------------------------------------------------- #pragma udata bank4=0x400 -static unsigned char low_depth; static float temp_limit; static float GF_low; static float GF_high; @@ -181,7 +180,8 @@ static float deco_ppO2; // new in v.101 static unsigned char sim_gas_last_used; // Last used gas, to detected a gas switch. -static unsigned char sim_gas_delay; // Delay added for gas switch (count down) [min]. +static unsigned short sim_gas_delay; // Time of gas-switch-stop ends [min on dive]. +static unsigned short sim_dive_mins; // Simulated dive time. static float calc_N2_ratio; // Simulated (switched) nitrogen ratio. static float calc_He_ratio; // Simulated (switched) helium ratio. static float CNS_fraction; // new in v.101 @@ -258,7 +258,7 @@ // Magic table to compute the MD2 HASH // #pragma romdata hash_tables = 0x017E00 // Address fixed by ASM access... -rom const rom unsigned int md_pi[] = +rom const rom unsigned short md_pi[] = { 0x292E, 0x43C9, 0xA2D8, 0x7C01, 0x3D36, 0x54A1, 0xECF0, 0x0613 , 0x62A7, 0x05F3, 0xC0C7, 0x738C, 0x9893, 0x2BD9, 0xBC4C, 0x82CA @@ -405,7 +405,7 @@ // static void check_dbg(PARAMETER char is_post_check) { - overlay unsigned int temp_DBS = 0; + overlay unsigned short temp_DBS = 0; overlay unsigned char i; // Local loop index. if( (DBG_N2_ratio != N2_ratio) || (DBG_He_ratio != He_ratio) ) @@ -473,7 +473,7 @@ ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -static int read_custom_function(PARAMETER unsigned char cf) +static short read_custom_function(PARAMETER unsigned char cf) { #ifdef CROSS_COMPILE extern unsigned short custom_functions[]; @@ -610,6 +610,7 @@ // Recompute leading gas limit, at current depth: overlay float depth = (temp_deco - pres_surface) / 0.09995; assert( depth >= 0.0 ); + assert( low_depth < 255 ); if( depth > low_depth ) sim_limit( GF_low ); @@ -620,7 +621,7 @@ if( sim_lead_tissue_limit > pres_surface ) { // Deepest stop, in meter. - overlay unsigned char first_stop = 3 * (int)(0.99 + (sim_lead_tissue_limit - pres_surface) / 0.29985); + overlay unsigned char first_stop = 3 * (short)(0.99 + (sim_lead_tissue_limit - pres_surface) / 0.29985); assert( first_stop < 128 ); // Apply correction for the first stop. @@ -692,7 +693,7 @@ if (pres_gradient >= 0) { pres_gradient /= 0.29985; // Bar --> stop number; - temp_depth_limit = 3 * (int) (pres_gradient + 0.99); // --> meter : depth for deco + temp_depth_limit = 3 * (short) (pres_gradient + 0.99); // --> meter : depth for deco if (temp_depth_limit == 0) // At surface ? temp_deco = pres_surface; else @@ -873,7 +874,7 @@ // void check_gas_switch(void) { - overlay unsigned char temp_gas_switch = sim_gas_last_used; + overlay unsigned char temp_gas_switch = 0; overlay float switch_deco; calc_N2_ratio = N2_ratio; @@ -921,22 +922,30 @@ } } - // Should detect gas switch 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 - && (calc_N2_ratio != N2_ratio || calc_He_ratio != He_ratio)) + // If there is a better gas available + if( temp_gas_switch ) { - sim_gas_last_used = temp_gas_switch; - sim_gas_delay = read_custom_function(55); + // Should detect gas switch 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)) + { + sim_gas_last_used = temp_gas_switch; + sim_gas_delay = read_custom_function(55); - // Apply depth correction ONLY if there delay is not null: - if( sim_gas_delay > 0 ) - { - temp_deco = switch_deco - float_deco_distance; - temp_depth_limit = (temp_deco - pres_surface) / 0.09985; + // Apply depth correction ONLY if CF#55 is not null: + if( sim_gas_delay > 0 ) + { + sim_gas_delay += sim_dive_mins; + temp_deco = switch_deco - float_deco_distance; + temp_depth_limit = (temp_deco - pres_surface) / 0.09985; + } } } + else + sim_gas_delay = 0; assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 ); assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 ); @@ -1043,6 +1052,7 @@ static float backup_GF_step; static unsigned char backup_low_depth; static unsigned char backup_gas_used; + static unsigned char backup_gas_delay; calc_hauptroutine_data_input(); @@ -1073,10 +1083,11 @@ // (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; + sim_dive_mins = 0; - // No gas change (yet) for this ascent simulation. - sim_gas_last_used = 0; - break; + break; case 0: //---- bottom time ----------------------------------------------- calc_nullzeit(); @@ -1089,7 +1100,14 @@ // dive data. backup_GF_step = locked_GF_step; backup_low_depth = low_depth; - backup_gas_used = sim_gas_last_used; + + // Check proposed gas at begin of ascent simulation + temp_deco = pres_respiration; // Starts from current real depth. + sim_dive_mins = int_I_divemins; // and time. + check_gas_switch(); + + backup_gas_used = sim_gas_last_used;// And save for later simu steps. + backup_gas_delay = sim_gas_delay; sim_ascent_to_first_stop(); @@ -1106,7 +1124,9 @@ locked_GF_step = backup_GF_step; low_depth = backup_low_depth; sim_gas_last_used = backup_gas_used; - backup_low_depth = 255; + sim_gas_delay = backup_gas_delay; + + backup_low_depth = 255; } break; } @@ -1122,7 +1142,7 @@ // void calc_hauptroutine_data_input(void) { - overlay int int_temp; + overlay short int_temp; pres_respiration = int_I_pres_respiration * 0.001; pres_surface = int_I_pres_surface * 0.001; @@ -1137,6 +1157,7 @@ // _____________ G A S _ C H A N G E S ________________ // ____________________________________________________ + // Keep a marhin of 150mbar = 1.50m int_temp = (int_I_pres_respiration - int_I_pres_surface) + MBAR_REACH_GASCHANGE_AUTO_CHANGE_OFF; deco_gas_change1 = 0.0; @@ -1145,50 +1166,41 @@ deco_gas_change4 = 0.0; deco_gas_change5 = 0.0; + // Gas are selectable if we did not pass the change depth by more than 1.50m: if(char_I_deco_gas_change1) { - overlay int int_temp2 = ((int)char_I_deco_gas_change1) * 100; - if(int_temp > int_temp2) - { - deco_gas_change1 = (float)char_I_deco_gas_change1 / 9.995 + pres_surface; - deco_gas_change1 += float_deco_distance; - } + if( int_temp > 100 *(short)char_I_deco_gas_change1 ) + deco_gas_change1 = char_I_deco_gas_change1 / 9.995 + + pres_surface + + float_deco_distance; } if(char_I_deco_gas_change2) { - overlay int int_temp2 = ((int)char_I_deco_gas_change2) * 100; - if(int_temp > int_temp2) - { - deco_gas_change2 = (float)char_I_deco_gas_change2 / 9.995 + pres_surface; - deco_gas_change2 += float_deco_distance; - } + if( int_temp > 100 *(short)char_I_deco_gas_change2 ) + deco_gas_change2 = char_I_deco_gas_change2 / 9.995 + + pres_surface + + float_deco_distance; } if(char_I_deco_gas_change3) { - overlay int int_temp2 = ((int)char_I_deco_gas_change3) * 100; - if(int_temp > int_temp2) - { - deco_gas_change3 = (float)char_I_deco_gas_change3 / 9.995 + pres_surface; - deco_gas_change3 += float_deco_distance; - } + if( int_temp > 100 *(short)char_I_deco_gas_change3 ) + deco_gas_change3 = char_I_deco_gas_change3 / 9.995 + + pres_surface + + float_deco_distance; } if(char_I_deco_gas_change4) { - overlay int int_temp2 = ((int)char_I_deco_gas_change4) * 100; - if(int_temp > int_temp2) - { - deco_gas_change4 = (float)char_I_deco_gas_change4 / 9.995 + pres_surface; - deco_gas_change4 += float_deco_distance; - } + if( int_temp > 100 *(short)char_I_deco_gas_change4 ) + deco_gas_change4 = char_I_deco_gas_change4 / 9.995 + + pres_surface + + float_deco_distance; } if(char_I_deco_gas_change5) { - overlay int int_temp2 = ((int)char_I_deco_gas_change5) * 100; - if(int_temp > int_temp2) - { - deco_gas_change5 = (float)char_I_deco_gas_change5 / 9.995 + pres_surface; - deco_gas_change5 += float_deco_distance; - } + if( int_temp > 100 *(short)char_I_deco_gas_change5 ) + deco_gas_change5 = char_I_deco_gas_change5 / 9.995 + + pres_surface + + float_deco_distance; } const_ppO2 = char_I_const_ppO2 * 0.01; @@ -1241,8 +1253,8 @@ // Calc limit for surface, ie. GF_high. calc_limit(GF_high); - int_O_gtissue_limit = (int)(calc_lead_tissue_limit * 1000); - int_O_gtissue_press = (int)((pres_tissue[char_O_gtissue_no] + (pres_tissue+16)[char_O_gtissue_no]) * 1000); + int_O_gtissue_limit = (short)(calc_lead_tissue_limit * 1000); + int_O_gtissue_press = (short)((pres_tissue[char_O_gtissue_no] + (pres_tissue+16)[char_O_gtissue_no]) * 1000); // if guiding tissue can not be exposed to surface pressure immediately if( calc_lead_tissue_limit > pres_surface && char_O_deco_status == 0) @@ -1266,26 +1278,26 @@ for(loop = 0; loop < 16; ++loop) { // Do not ascent while doing a gas switch. - if( sim_gas_delay == 0 ) + if( sim_gas_delay <= sim_dive_mins ) + { calc_nextdecodepth(); - //---- Finish computations once surface is reached ------------------- - if( temp_depth_limit == 0 ) - { - copy_deco_table(); - calc_ascenttime(); - char_O_deco_status = 0; // calc nullzeit next time. - return; - } + //---- Finish computations once surface is reached --------------- + if( temp_depth_limit == 0 ) + { + copy_deco_table(); + calc_ascenttime(); + char_O_deco_status = 0; // calc nullzeit next time. + return; + } - //---- Else, continue simulating the stops --------------------------- - if( sim_gas_delay == 0 ) + //---- Else, continue simulating the stops ----------------------- check_gas_switch(); // Calculate N2_ratio and He_ratio. - if( sim_gas_delay > 0 ) - sim_gas_delay--; + } - alveolar_presures(); // Updates ppN2 and ppHe. - + //---- Then update tissue and decoplan ------------------------------- + sim_dive_mins++; // Advance simulated time by 1 minute. + alveolar_presures(); // Updates ppN2 and ppHe. sim_tissue(1); // Simulate compartiments for 1 minute. update_deco_table(); // Add one minute stops. } @@ -1308,44 +1320,44 @@ temp_deco = pres_respiration; // Starts from current real depth. - // Loop until first top or surface is reached. + // Loop until first stop, gas switch, or surface is reached. for(;;) { - // Do not ascent while doing a gas switch. - if( sim_gas_delay == 0 ) - temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min. + // Do we have a gas switch going on ? + if( sim_gas_delay > sim_dive_mins ) + break; + + // No: try ascending 1 full minute. + temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min. + + // Did we reach surface ? + if( temp_deco <= pres_surface ) + { + temp_deco = pres_surface; // Yes: finished ! + break; + } // Compute sim_lead_tissue_limit at GF_low (deepest stop). sim_limit(GF_low); - // Did we reach first stop ? + // Did we reach deepest remaining stop ? if( temp_deco <= sim_lead_tissue_limit ) { temp_deco = sim_lead_tissue_limit; break; // Return stop found ! } - // Next stop is surface ? - if( temp_deco <= pres_surface ) - break; // Yes: finished ! + temp_deco += 0.5; // Check gas change 5 meter below new depth. + check_gas_switch(); + temp_deco -= 0.5; // Back to new depth. - //---- Simulat gas switches - if( sim_gas_delay > 0 ) - { - sim_gas_delay--; // Decrement switch delay - update_deco_table(); // And mark stop in table - } - else - { - temp_deco += 0.5; // Check gas change 5 meter below new depth. - check_gas_switch(); - temp_deco -= 0.5; // Back to new depth. - } + sim_dive_mins++; // Advance simulated time by 1 minute. + alveolar_presures(); // Calculate ppO2/ppHe at new depth. + sim_tissue(1); // and update tissues for 1 min. + } - // Then simulate with the new gas pressures... (1min) - alveolar_presures(); // Calculated at true depth ! - sim_tissue(1); - } + // Always updates depth in meter, too: + temp_depth_limit = (temp_deco - pres_surface) / 0.09985; } ////////////////////////////////////////////////////////////////////////////// @@ -1426,7 +1438,7 @@ // static void calc_nullzeit(void) { - overlay int loop; + overlay unsigned char loop; update_startvalues(); char_O_nullzeit = 0; @@ -1494,10 +1506,10 @@ overlay float ascent = pres_respiration - pres_surface + 0.7; if (ascent < 0.0) ascent = 0.0; - int_O_ascenttime = (unsigned int)(ascent + 0.99); + int_O_ascenttime = (unsigned short)(ascent + 0.99); for(x=0; x<32 && internal_deco_depth[x]; x++) - int_O_ascenttime += (unsigned int)internal_deco_time[x]; + int_O_ascenttime += (unsigned short)internal_deco_time[x]; } else int_O_ascenttime = 0; @@ -1723,7 +1735,7 @@ // void deco_calc_desaturation_time(void) { - overlay unsigned int desat_time; // For a particular compartiment, in min. + overlay unsigned short desat_time; // For a particular compartiment, in min. overlay float temp1; overlay float temp2; overlay float temp3; @@ -1795,9 +1807,9 @@ // saturation_time (for flight) if (temp4 > temp2) - desat_time = (unsigned int)temp4; + desat_time = (unsigned short)temp4; else - desat_time = (unsigned int)temp2; + desat_time = (unsigned short)temp2; if(desat_time > int_O_desaturation_time) int_O_desaturation_time = desat_time; @@ -1865,7 +1877,7 @@ overlay unsigned char md_t; overlay unsigned char md_buffer[16]; overlay unsigned char md_temp; - overlay unsigned int md_pointer; + overlay unsigned short md_pointer; RESET_C_STACK @@ -2049,7 +2061,7 @@ void deco_calc_percentage(void) { RESET_C_STACK - int_I_temp = (int)(int_I_temp * (char_I_temp / 100.0)); + int_I_temp = (short)(int_I_temp * (char_I_temp / 100.0)); } //////////////////////////////////////////////////////////////////////////////