Mercurial > public > mk2
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. |