comparison 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
comparison
equal deleted inserted replaced
216:c7e32ff65636 217:ce6f16711567
68 // 2011/01/24: [jDG] Make ascenttime an short. No more overflow! 68 // 2011/01/24: [jDG] Make ascenttime an short. No more overflow!
69 // 2011/01/25: [jDG] Fusion deco array for both models. 69 // 2011/01/25: [jDG] Fusion deco array for both models.
70 // 2011/01/25: [jDG] Use CF(54) to reverse deco order. 70 // 2011/01/25: [jDG] Use CF(54) to reverse deco order.
71 // 2011/02/11: [jDG] Reworked gradient-factor implementation. 71 // 2011/02/11: [jDG] Reworked gradient-factor implementation.
72 // 2011/02/13: [jDG] CF55 for additional gas switch delay in decoplan. 72 // 2011/02/13: [jDG] CF55 for additional gas switch delay in decoplan.
73 // 2011/02/24: [jDG] Fixed inconsistencies introduced by gas switch delays.
73 // 74 //
74 // TODO: 75 // TODO:
75 // + Allow to abort MD2 calculation (have to restart next time). 76 // + Allow to abort MD2 calculation (have to restart next time).
76 // 77 //
77 // Literature: 78 // Literature:
125 static void calc_hauptroutine_data_input(void); 126 static void calc_hauptroutine_data_input(void);
126 static void calc_hauptroutine_update_tissues(void); 127 static void calc_hauptroutine_update_tissues(void);
127 static void calc_hauptroutine_calc_deco(void); 128 static void calc_hauptroutine_calc_deco(void);
128 static void sim_ascent_to_first_stop(void); 129 static void sim_ascent_to_first_stop(void);
129 130
130 static void check_gas_switch(void); 131 static void deepest_gas_switch(void);
132 static void best_gas_switch(void);
133 static void set_gas(void);
134
131 static void calc_nextdecodepth(void); 135 static void calc_nextdecodepth(void);
132 136
133 //---- Bank 4 parameters ----------------------------------------------------- 137 //---- Bank 4 parameters -----------------------------------------------------
134 #pragma udata bank4=0x400 138 #pragma udata bank4=0x400
135 139
698 } 702 }
699 else 703 else
700 temp_depth_limit = 0; // stop depth, in meter. 704 temp_depth_limit = 0; // stop depth, in meter.
701 } 705 }
702 706
703 //---- Check gas change -------------------------------------------------- 707 //---- Check gas change --------------------------------------------------
704 check_gas_switch(); // Update temp_depth_limit if there is a change, 708 best_gas_switch(); // Update temp_depth_limit if there is a change,
705 // Calculate N2_ratio and He_ratio too. 709 // Calculate N2_ratio and He_ratio too.
706 } 710 }
707 711
708 ////////////////////////////////////////////////////////////////////////////// 712 //////////////////////////////////////////////////////////////////////////////
709 // copy_deco_table 713 // copy_deco_table
859 { 863 {
860 RESET_C_STACK 864 RESET_C_STACK
861 } 865 }
862 866
863 ////////////////////////////////////////////////////////////////////////////// 867 //////////////////////////////////////////////////////////////////////////////
864 // Calculate gas switches 868 // Find deepest available gas.
865 // 869 //
866 // 870 // Input: deco_gas_change*
867 // Input: N2_ratio, He_ratio.
868 // deco_gas_change*
869 // sim_gas_delay, sim_gas_last_used, sim_dive_mins. 871 // sim_gas_delay, sim_gas_last_used, sim_dive_mins.
870 // 872 //
871 // Output: calc_N2_ratio, calc_He_ratio 873 // Output: temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch.
872 // temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch. 874 //
873 // 875 static void deepest_gas_switch(void)
874 static void check_gas_switch(void)
875 { 876 {
876 overlay unsigned char temp_gas_switch = 0; 877 overlay unsigned char temp_gas_switch = 0;
877 overlay unsigned char switch_deco = 0; 878 overlay unsigned char switch_deco = 0;
878 879
879 calc_N2_ratio = N2_ratio;
880 calc_He_ratio = He_ratio;
881
882 if (char_I_const_ppO2 == 0) 880 if (char_I_const_ppO2 == 0)
883 { 881 {
884 // Keep selecting the best gas during the ascent simulation. 882 // Keep selecting the best gas during the ascent simulation.
885 // Add a one meter margin in depth comparaison. 883 // Add a one meter margin in depth comparaison.
886 if( deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1)) 884 if( deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1))
887 { 885 {
888 calc_N2_ratio = deco_N2_ratio1;
889 calc_He_ratio = deco_He_ratio1;
890 temp_gas_switch = 1; 886 temp_gas_switch = 1;
891 switch_deco = deco_gas_change1; 887 switch_deco = deco_gas_change1;
892 } 888 }
893 if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2)) 889 else if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2))
894 { 890 {
895 calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01;
896 calc_He_ratio = char_I_deco_He_ratio2 * 0.01;
897 temp_gas_switch = 2; 891 temp_gas_switch = 2;
898 switch_deco = deco_gas_change2; 892 switch_deco = deco_gas_change2;
899 } 893 }
900 if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3)) 894 else if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3))
901 { 895 {
902 calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01;
903 calc_He_ratio = char_I_deco_He_ratio3 * 0.01;
904 temp_gas_switch = 3; 896 temp_gas_switch = 3;
905 switch_deco = deco_gas_change3; 897 switch_deco = deco_gas_change3;
906 } 898 }
907 if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4)) 899 else if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4))
908 { 900 {
909 calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01;
910 calc_He_ratio = char_I_deco_He_ratio4 * 0.01;
911 temp_gas_switch = 4; 901 temp_gas_switch = 4;
912 switch_deco = deco_gas_change4; 902 switch_deco = deco_gas_change4;
913 } 903 }
914 if(deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5)) 904 else if(deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5))
915 { 905 {
916 calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01;
917 calc_He_ratio = char_I_deco_He_ratio5 * 0.01;
918 temp_gas_switch = 5; 906 temp_gas_switch = 5;
919 switch_deco = deco_gas_change5; 907 switch_deco = deco_gas_change5;
920 } 908 }
921 } 909 }
922 910
924 if( temp_gas_switch ) 912 if( temp_gas_switch )
925 { 913 {
926 // Should restart gas-switch delay only when gas do changes... 914 // Should restart gas-switch delay only when gas do changes...
927 // sim_gas_last_used: used to detect just once in each ascent simu. 915 // sim_gas_last_used: used to detect just once in each ascent simu.
928 // N2_ratio : used to detect when already breathing that gas. 916 // N2_ratio : used to detect when already breathing that gas.
929 if( sim_gas_last_used < temp_gas_switch 917 if( temp_depth_limit != switch_deco
930 && sim_gas_delay <= sim_dive_mins 918 && sim_gas_last_used < temp_gas_switch
931 && (calc_N2_ratio != N2_ratio || calc_He_ratio != He_ratio)) 919 && sim_gas_delay <= sim_dive_mins )
932 { 920 {
933 sim_gas_last_used = temp_gas_switch; 921 sim_gas_last_used = temp_gas_switch;
934 sim_gas_delay = read_custom_function(55); 922 sim_gas_delay = read_custom_function(55);
935 923
936 // Apply depth correction ONLY if CF#55 is not null: 924 // Apply depth correction ONLY if CF#55 is not null:
941 } 929 }
942 } 930 }
943 } 931 }
944 else 932 else
945 sim_gas_delay = 0; 933 sim_gas_delay = 0;
934 }
935
936 //////////////////////////////////////////////////////////////////////////////
937 // Find best (shallowest) available gas.
938 //
939 // Input: deco_gas_change*
940 // sim_gas_delay, sim_gas_last_used, sim_dive_mins.
941 //
942 // Output: temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch.
943 //
944 static void best_gas_switch(void)
945 {
946 overlay unsigned char temp_gas_switch = 0;
947 overlay unsigned char switch_deco = 0;
948
949 if (char_I_const_ppO2 == 0)
950 {
951 // Keep selecting the best gas during the ascent simulation.
952 // Add a one meter margin in depth comparaison.
953 if( deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5))
954 {
955 temp_gas_switch = 5;
956 switch_deco = deco_gas_change5;
957 }
958 else if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4))
959 {
960 temp_gas_switch = 4;
961 switch_deco = deco_gas_change4;
962 }
963 else if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3))
964 {
965 temp_gas_switch = 3;
966 switch_deco = deco_gas_change3;
967 }
968 else if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2))
969 {
970 temp_gas_switch = 2;
971 switch_deco = deco_gas_change2;
972 }
973 else if(deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1))
974 {
975 temp_gas_switch = 1;
976 switch_deco = deco_gas_change1;
977 }
978 }
979
980 // If there is a better gas available
981 if( temp_gas_switch )
982 {
983 // Should restart gas-switch delay only when gas do changes...
984 // sim_gas_last_used: used to detect just once in each ascent simu.
985 // N2_ratio : used to detect when already breathing that gas.
986 if( sim_gas_last_used < temp_gas_switch
987 && sim_gas_delay <= sim_dive_mins )
988 {
989 sim_gas_last_used = temp_gas_switch;
990 sim_gas_delay = read_custom_function(55);
991
992 // Apply depth correction ONLY if CF#55 is not null:
993 if( sim_gas_delay > 0 )
994 {
995 sim_gas_delay += sim_dive_mins;
996 temp_depth_limit = switch_deco;
997 }
998 }
999 }
1000 else
1001 sim_gas_delay = 0;
1002 }
1003
1004 //////////////////////////////////////////////////////////////////////////////
1005 // Calculate gas switches
1006 //
1007 //
1008 // Input: N2_ratio, He_ratio.
1009 // sim_gas_last_used
1010 //
1011 // Output: calc_N2_ratio, calc_He_ratio
1012 //
1013 static void set_gas(void)
1014 {
1015 switch(sim_gas_last_used)
1016 {
1017 default:
1018 calc_N2_ratio = N2_ratio;
1019 calc_He_ratio = He_ratio;
1020 break;
1021 case 1:
1022 calc_N2_ratio = deco_N2_ratio1;
1023 calc_He_ratio = deco_He_ratio1;
1024 break;
1025
1026 case 2:
1027 calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01;
1028 calc_He_ratio = char_I_deco_He_ratio2 * 0.01;
1029 break;
1030 case 3:
1031 calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01;
1032 calc_He_ratio = char_I_deco_He_ratio3 * 0.01;
1033 break;
1034 case 4:
1035 calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01;
1036 calc_He_ratio = char_I_deco_He_ratio4 * 0.01;
1037 break;
1038 case 5:
1039 calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01;
1040 calc_He_ratio = char_I_deco_He_ratio5 * 0.01;
1041 break;
1042 }
946 1043
947 assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 ); 1044 assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 );
948 assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 ); 1045 assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 );
949 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 ); 1046 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 );
950 } 1047 }
1055 // | +------< not finished 1152 // | +------< not finished
1056 // +--------< finish 1153 // +--------< finish
1057 // 1154 //
1058 static void calc_hauptroutine(void) 1155 static void calc_hauptroutine(void)
1059 { 1156 {
1060 static float backup_GF_step; 1157 static unsigned char backup_gas_used = 0;
1061 static unsigned char backup_low_depth; 1158 static unsigned char backup_gas_delay = 0;
1062 static unsigned char backup_gas_used;
1063 static unsigned char backup_gas_delay;
1064 1159
1065 calc_hauptroutine_data_input(); 1160 calc_hauptroutine_data_input();
1066 1161
1067 if(!flag_in_divemode) 1162 if(!flag_in_divemode)
1068 { 1163 {
1085 copy_deco_table(); 1180 copy_deco_table();
1086 int_O_ascenttime = 0; // Reset DTR. 1181 int_O_ascenttime = 0; // Reset DTR.
1087 char_O_nullzeit = 0; // Reset bottom time. 1182 char_O_nullzeit = 0; // Reset bottom time.
1088 char_O_deco_status = 0; // Calc bottom-time/nullzeit next iteration. 1183 char_O_deco_status = 0; // Calc bottom-time/nullzeit next iteration.
1089 1184
1090 // Values that should be reset just once for the full real dive 1185 // Values that should be reset just once for the full real dive.
1091 // (not every time we simulate an ascent): 1186 // This is used to record the lowest stop for the whole dive,
1092 low_depth = 0; // Reset GF history. 1187 // Including ACCROSS all simulated ascent.
1093 backup_low_depth = 255; // backup is empty... 1188 low_depth = 0;
1094 sim_gas_last_used = 0; // Reset gas switch history. 1189
1095 sim_gas_delay = 0; 1190 // Reset gas switch history.
1191 backup_gas_used = sim_gas_last_used = 0;
1192 backup_gas_delay = sim_gas_delay = 0;
1096 sim_dive_mins = 0; 1193 sim_dive_mins = 0;
1097
1098 break; 1194 break;
1099 1195
1100 case 0: //---- bottom time ----------------------------------------------- 1196 case 0: //---- bottom time -----------------------------------------------
1101 calc_nullzeit(); 1197 calc_nullzeit();
1102 check_ndl(); 1198 check_ndl();
1103 char_O_deco_status = 2; // calc ascent next time. 1199 char_O_deco_status = 2; // calc ascent next time.
1104 break; 1200 break;
1105 1201
1106 case 2: //---- Simulate ascent to first stop ----------------------------- 1202 case 2: //---- Simulate ascent to first stop -----------------------------
1107 // Backup ascention state, so the simulation won't polute the real
1108 // dive data.
1109 backup_GF_step = locked_GF_step;
1110 backup_low_depth = low_depth;
1111
1112 // Check proposed gas at begin of ascent simulation 1203 // Check proposed gas at begin of ascent simulation
1113 sim_dive_mins = int_I_divemins; // and time. 1204 sim_dive_mins = int_I_divemins; // and time.
1114 temp_depth_limit = (int)(0.95 + (pres_respiration - pres_surface) / 0.09985) ; // Starts from current real depth. 1205 temp_depth_limit = (int)(0.95 + (pres_respiration - pres_surface) / 0.09985) ; // Starts from current real depth.
1115 check_gas_switch(); 1206 best_gas_switch();
1207 set_gas();
1116 1208
1117 backup_gas_used = sim_gas_last_used;// And save for later simu steps. 1209 backup_gas_used = sim_gas_last_used;// And save for later simu steps.
1118 backup_gas_delay = sim_gas_delay; 1210 backup_gas_delay = sim_gas_delay;
1119 1211
1120 sim_ascent_to_first_stop(); 1212 sim_ascent_to_first_stop();
1125 case 1: //---- Simulate stops -------------------------------------------- 1217 case 1: //---- Simulate stops --------------------------------------------
1126 calc_hauptroutine_calc_deco(); 1218 calc_hauptroutine_calc_deco();
1127 1219
1128 // If simulation is finished, restore the GF low reference, so that 1220 // If simulation is finished, restore the GF low reference, so that
1129 // next ascent simulation is done from the current depth: 1221 // next ascent simulation is done from the current depth:
1130 if( char_O_deco_status == 0 && backup_low_depth != 255) 1222 if( char_O_deco_status == 0 )
1131 { 1223 {
1132 locked_GF_step = backup_GF_step;
1133 low_depth = backup_low_depth;
1134 sim_gas_last_used = backup_gas_used; 1224 sim_gas_last_used = backup_gas_used;
1135 sim_gas_delay = backup_gas_delay; 1225 sim_gas_delay = backup_gas_delay;
1136
1137 backup_low_depth = 255;
1138 } 1226 }
1139 break; 1227 break;
1140 } 1228 }
1141 1229
1142 check_post_dbg(); 1230 check_post_dbg();
1311 update_deco_table(); // This is a one minute stops. 1399 update_deco_table(); // This is a one minute stops.
1312 } 1400 }
1313 1401
1314 //---- Then update tissue and decoplan ------------------------------- 1402 //---- Then update tissue and decoplan -------------------------------
1315 sim_dive_mins++; // Advance simulated time by 1 minute. 1403 sim_dive_mins++; // Advance simulated time by 1 minute.
1404 set_gas(); // Apply any simulated gas change, once validated.
1316 sim_alveolar_presures(); // Updates ppN2 and ppHe. 1405 sim_alveolar_presures(); // Updates ppN2 and ppHe.
1317 sim_tissue(1); // Simulate compartiments for 1 minute. 1406 sim_tissue(1); // Simulate compartiments for 1 minute.
1318 } 1407 }
1319 1408
1320 // Surface not reached, need more stops... 1409 // Surface not reached, need more stops...
1362 break; 1451 break;
1363 } 1452 }
1364 1453
1365 // Check gas change 5 meter below new depth. 1454 // Check gas change 5 meter below new depth.
1366 temp_depth_limit = (temp_deco + 0.5 - pres_surface) / 0.09985; 1455 temp_depth_limit = (temp_deco + 0.5 - pres_surface) / 0.09985;
1367 check_gas_switch(); 1456 deepest_gas_switch();
1368 if( sim_gas_delay > sim_dive_mins ) 1457 if( sim_gas_delay > sim_dive_mins )
1369 break; 1458 break;
1370 1459
1371 sim_dive_mins++; // Advance simulated time by 1 minute. 1460 sim_dive_mins++; // Advance simulated time by 1 minute.
1372 sim_alveolar_presures(); // Still uses temp_deco. 1461 sim_alveolar_presures(); // Still uses temp_deco.