comparison code_part1/OSTC_code_c_part2/p2_deco.c @ 197:f15e804ff67f

Gas switch delay + New CF#55 for additional delay in decoplan for gas switch. + BUGFIX compute integration at full ascent, not half (or the formula is wrong). + BUGFIX minor typo in 2sec exposition factors.
author JeanDo
date Sun, 13 Feb 2011 17:27:43 +0100
parents 652e17b6267a
children 0a3ca358c684
comparison
equal deleted inserted replaced
196:e185b3b028af 197:f15e804ff67f
67 // 2011/01/23: [jDG] Added read_custom_function(). 67 // 2011/01/23: [jDG] Added read_custom_function().
68 // 2011/01/24: [jDG] Make ascenttime an int. No more overflow! 68 // 2011/01/24: [jDG] Make ascenttime an int. 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 // 73 //
73 // TODO: 74 // TODO:
74 // + Allow (CF) delay for gas switch while predicting ascent.
75 // + Allow to abort MD2 calculation (have to restart next time). 75 // + Allow to abort MD2 calculation (have to restart next time).
76 // 76 //
77 // Literature: 77 // Literature:
78 // B"uhlmann, Albert: Tauchmedizin; 4. Auflage; 78 // B"uhlmann, Albert: Tauchmedizin; 4. Auflage;
79 // Schr"oder, Kai & Reith, Steffen; 2000; S"attigungsvorg"ange beim Tauchen, das Modell ZH-L16, Funktionsweise von Tauchcomputern; http://www.achim-und-kai.de/kai/tausim/saett_faq 79 // Schr"oder, Kai & Reith, Steffen; 2000; S"attigungsvorg"ange beim Tauchen, das Modell ZH-L16, Funktionsweise von Tauchcomputern; http://www.achim-und-kai.de/kai/tausim/saett_faq
158 158
159 static unsigned char ci; 159 static unsigned char ci;
160 static float pres_respiration; 160 static float pres_respiration;
161 static float pres_surface; 161 static float pres_surface;
162 static float temp1; 162 static float temp1;
163 static float temp2;
164 static float temp3;
165 static float temp4;
166 static float temp_deco; 163 static float temp_deco;
167 static float temp_atem; 164 static float temp_atem;
168 static float temp2_atem; 165 static float temp2_atem;
169 static float temp_tissue; 166 static float temp_tissue;
170 static float N2_ratio; 167 static float N2_ratio;
182 static float deco_diluent; // new in v.101 179 static float deco_diluent; // new in v.101
183 static float const_ppO2; // new in v.101 180 static float const_ppO2; // new in v.101
184 static float deco_ppO2_change; // new in v.101 181 static float deco_ppO2_change; // new in v.101
185 static float deco_ppO2; // new in v.101 182 static float deco_ppO2; // new in v.101
186 183
187 static unsigned char calc_gas_switch; // Detected a gas switch. 184 static unsigned char sim_gas_last_used; // Last used gas, to detected a gas switch.
185 static unsigned char sim_gas_delay; // Delay added for gas switch (count down) [min].
188 static float calc_N2_ratio; // new in v.101 186 static float calc_N2_ratio; // new in v.101
189 static float calc_He_ratio; // new in v.101 187 static float calc_He_ratio; // new in v.101
190 static float CNS_fraction; // new in v.101 188 static float CNS_fraction; // new in v.101
191 static float float_saturation_multiplier; // new in v.101 189 static float float_saturation_multiplier; // new in v.101
192 static float float_desaturation_multiplier; // new in v.101 190 static float float_desaturation_multiplier; // new in v.101
199 static float deco_gas_change4; // new in v.109 197 static float deco_gas_change4; // new in v.109
200 static float deco_gas_change5; // new in v.109 198 static float deco_gas_change5; // new in v.109
201 199
202 static float deco_N2_ratio1; // new in v.101 200 static float deco_N2_ratio1; // new in v.101
203 static float deco_He_ratio1; // new in v.101 201 static float deco_He_ratio1; // new in v.101
204 static float deco_N2_ratio2; // new in v.109
205 static float deco_N2_ratio3; // new in v.109
206 static float deco_N2_ratio4; // new in v.109
207 static float deco_N2_ratio5; // new in v.109
208 static float deco_He_ratio2; // new in v.109
209 static float deco_He_ratio3; // new in v.109
210 static float deco_He_ratio4; // new in v.109
211 static float deco_He_ratio5; // new in v.109
212 202
213 203
214 //---- Bank 6 parameters ----------------------------------------------------- 204 //---- Bank 6 parameters -----------------------------------------------------
215 #pragma udata bank6=0x600 205 #pragma udata bank6=0x600
216 206
217 static float pres_tissue[32]; 207 float pres_tissue[32];
218 static float pres_tissue_limit[16]; 208 float pres_tissue_limit[16];
219 static float sim_pres_tissue_limit[16]; 209 float sim_pres_tissue_limit[16];
220 210
221 //---- Bank 7 parameters ----------------------------------------------------- 211 //---- Bank 7 parameters -----------------------------------------------------
222 #pragma udata bank7=0x700 212 #pragma udata bank7=0x700
223 213
224 static float sim_pres_tissue[32]; // 32 floats = 128 bytes. 214 float sim_pres_tissue[32]; // 32 floats = 128 bytes.
225 static float sim_pres_tissue_backup[32]; 215 static float sim_pres_tissue_backup[32];
226 216
227 //---- Bank 8 parameters ----------------------------------------------------- 217 //---- Bank 8 parameters -----------------------------------------------------
228 #pragma udata bank8=0x800 218 #pragma udata bank8=0x800
229 219
516 _asm 506 _asm
517 movlw 1 507 movlw 1
518 movwf TBLPTRU,0 508 movwf TBLPTRU,0
519 _endasm 509 _endasm
520 #endif 510 #endif
511 assert( 0 <= ci && ci < 16 );
521 512
522 var_N2_a = buhlmann_a[ci]; 513 var_N2_a = buhlmann_a[ci];
523 var_N2_b = buhlmann_b[ci]; 514 var_N2_b = buhlmann_b[ci];
524 var_He_a = (buhlmann_a+16)[ci]; 515 var_He_a = (buhlmann_a+16)[ci];
525 var_He_b = (buhlmann_b+16)[ci]; 516 var_He_b = (buhlmann_b+16)[ci];
582 || (var_He_e > 0.98986) 573 || (var_He_e > 0.98986)
583 ) 574 )
584 int_O_DBG_pre_bitfield |= DBG_ZH16ERR; 575 int_O_DBG_pre_bitfield |= DBG_ZH16ERR;
585 576
586 break; 577 break;
578
579 default:
580 assert(0); // Never go there...
587 } 581 }
588 } 582 }
589 583
590 ////////////////////////////////////////////////////////////////////////////// 584 //////////////////////////////////////////////////////////////////////////////
591 // calc_next_decodepth_GF 585 // calc_next_decodepth_GF
776 // 770 //
777 // Apply safety factors for brand ZH-L16 model. 771 // Apply safety factors for brand ZH-L16 model.
778 // 772 //
779 static void temp_tissue_safety(void) 773 static void temp_tissue_safety(void)
780 { 774 {
775 assert( 0.0 < float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 );
776 assert( 1.0 <= float_saturation_multiplier && float_saturation_multiplier <= 2.0 );
777
781 if( char_I_deco_model == 0 ) 778 if( char_I_deco_model == 0 )
782 { 779 {
783 if (temp_tissue < 0.0) 780 if (temp_tissue < 0.0)
784 temp_tissue *= float_desaturation_multiplier; 781 temp_tissue *= float_desaturation_multiplier;
785 else 782 else
902 N2_ratio = 0.7902; 899 N2_ratio = 0.7902;
903 pres_respiration = (float)int_I_pres_respiration / 1000.0; 900 pres_respiration = (float)int_I_pres_respiration / 1000.0;
904 901
905 for(ci=0; ci<16; ci++) 902 for(ci=0; ci<16; ci++)
906 { 903 {
907 // cycle through the 16 b"uhlmann tissues 904 // cycle through the 16 Bühlmann tissues
908 overlay float p = N2_ratio * (pres_respiration - 0.0627); 905 overlay float p = N2_ratio * (pres_respiration - 0.0627);
909 pres_tissue[ci] = p; 906 pres_tissue[ci] = p;
910 907
911 read_buhlmann_coefficients(-1); 908 read_buhlmann_coefficients(-1);
912 909
913 p = (p - var_N2_a) * var_N2_b ; 910 p = (p - var_N2_a) * var_N2_b ;
914 if( p < 0.0 ) 911 if( p < 0.0 )
915 p = 0.0; 912 p = 0.0;
916 pres_tissue_limit[ci] = p; 913 pres_tissue_limit[ci] = p;
917 914
918 // cycle through the 16 b"uhlmann tissues for Helium 915 // cycle through the 16 Bühlmann tissues for Helium
919 (pres_tissue+16)[ci] = 0.0; 916 (pres_tissue+16)[ci] = 0.0;
920 } // for 0 to 16 917 } // for 0 to 16
921 918
922 clear_deco_table(); 919 clear_deco_table();
923 char_O_deco_status = 0; 920 char_O_deco_status = 0;
924 char_O_nullzeit = 0; 921 char_O_nullzeit = 0;
925 int_O_ascenttime = 0; 922 int_O_ascenttime = 0;
926 char_O_gradient_factor = 0; 923 char_O_gradient_factor = 0;
927 char_O_relative_gradient_GF = 0; 924 char_O_relative_gradient_GF = 0;
928 char_I_depth_last_deco = 0; // for compatibility with v.101pre_no_last_deco 925 char_I_depth_last_deco = 0; // for compatibility with v.101pre_no_last_deco
929 } 926 }
930 927
931 ////////////////////////////////////////////////////////////////////////////// 928 //////////////////////////////////////////////////////////////////////////////
932 // calc_wo_deco_step_2s 929 // calc_wo_deco_step_2s
933 // 930 //
940 N2_ratio = 0.7902; // Sum as stated in b"uhlmann 937 N2_ratio = 0.7902; // Sum as stated in b"uhlmann
941 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system 938 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system
942 pres_surface = (float)int_I_pres_surface / 1000.0; // the b"uhlmann formula using pres_surface does apply to the pressure without any inert ratio 939 pres_surface = (float)int_I_pres_surface / 1000.0; // the b"uhlmann formula using pres_surface does apply to the pressure without any inert ratio
943 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body 940 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body
944 temp2_atem = 0.0; 941 temp2_atem = 0.0;
945 float_desaturation_multiplier = char_I_desaturation_multiplier / 100.0; 942 float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01;
946 float_saturation_multiplier = char_I_saturation_multiplier / 100.0; 943 float_saturation_multiplier = char_I_saturation_multiplier * 0.01;
947 944
948 calc_tissue(0); // update the pressure in the 32 tissues in accordance with the new ambient pressure for 2 seconds. 945 calc_tissue(0); // update the pressure in the 32 tissues in accordance with the new ambient pressure for 2 seconds.
949 946
950 clear_deco_table(); 947 clear_deco_table();
951 char_O_deco_status = 0; 948 char_O_deco_status = 0;
1045 // 1042 //
1046 void calc_hauptroutine_data_input(void) 1043 void calc_hauptroutine_data_input(void)
1047 { 1044 {
1048 overlay int int_temp; 1045 overlay int int_temp;
1049 1046
1050 pres_respiration = int_I_pres_respiration / 1000.0; 1047 pres_respiration = int_I_pres_respiration * 0.001;
1051 pres_surface = int_I_pres_surface / 1000.0; 1048 pres_surface = int_I_pres_surface * 0.001;
1052 N2_ratio = char_I_N2_ratio / 100.0; 1049 N2_ratio = char_I_N2_ratio * 0.01;
1053 He_ratio = char_I_He_ratio / 100.0; 1050 He_ratio = char_I_He_ratio * 0.01;
1054 deco_N2_ratio1 = char_I_deco_N2_ratio1 / 100.0; 1051 deco_N2_ratio1 = char_I_deco_N2_ratio1 * 0.01;
1055 deco_He_ratio1 = char_I_deco_He_ratio1 / 100.0; 1052 deco_He_ratio1 = char_I_deco_He_ratio1 * 0.01;
1056 deco_N2_ratio2 = char_I_deco_N2_ratio2 / 100.0; 1053 float_deco_distance = char_I_deco_distance * 0.01; // Get offset is in mbar.
1057 deco_He_ratio2 = char_I_deco_He_ratio2 / 100.0;
1058 deco_N2_ratio3 = char_I_deco_N2_ratio3 / 100.0;
1059 deco_He_ratio3 = char_I_deco_He_ratio3 / 100.0;
1060 deco_N2_ratio4 = char_I_deco_N2_ratio4 / 100.0;
1061 deco_He_ratio4 = char_I_deco_He_ratio4 / 100.0;
1062 deco_N2_ratio5 = char_I_deco_N2_ratio5 / 100.0;
1063 deco_He_ratio5 = char_I_deco_He_ratio5 / 100.0;
1064 float_deco_distance = char_I_deco_distance / 100.0; // Get offset is in mbar.
1065 1054
1066 // ____________________________________________________ 1055 // ____________________________________________________
1067 // 1056 //
1068 // _____________ G A S _ C H A N G E S ________________ 1057 // _____________ G A S _ C H A N G E S ________________
1069 // ____________________________________________________ 1058 // ____________________________________________________
1120 deco_gas_change5 = (float)char_I_deco_gas_change5 / 9.995 + pres_surface; 1109 deco_gas_change5 = (float)char_I_deco_gas_change5 / 9.995 + pres_surface;
1121 deco_gas_change5 += float_deco_distance; 1110 deco_gas_change5 += float_deco_distance;
1122 } 1111 }
1123 } 1112 }
1124 1113
1125 const_ppO2 = (float)char_I_const_ppO2 / 100.0; 1114 const_ppO2 = char_I_const_ppO2 * 0.01;
1126 deco_ppO2_change = (float)char_I_deco_ppO2_change / 99.95 + pres_surface; 1115 deco_ppO2_change = char_I_deco_ppO2_change / 99.95
1127 deco_ppO2_change += float_deco_distance; 1116 + pres_surface
1128 deco_ppO2 = (float)char_I_deco_ppO2 / 100.0; 1117 + float_deco_distance;
1129 float_desaturation_multiplier = char_I_desaturation_multiplier / 100.0; 1118 deco_ppO2 = char_I_deco_ppO2 * 0.01;
1130 float_saturation_multiplier = char_I_saturation_multiplier / 100.0; 1119 float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01;
1131 GF_low = (float)char_I_GF_Low_percentage / 100.0; 1120 float_saturation_multiplier = char_I_saturation_multiplier * 0.01;
1132 GF_high = (float)char_I_GF_High_percentage / 100.0; 1121 GF_low = char_I_GF_Low_percentage * 0.01;
1122 GF_high = char_I_GF_High_percentage * 0.01;
1133 GF_delta = GF_high - GF_low; 1123 GF_delta = GF_high - GF_low;
1134 } 1124 }
1135 1125
1136 ////////////////////////////////////////////////////////////////////////////// 1126 //////////////////////////////////////////////////////////////////////////////
1137 // 1127 //
1138 // 1128 //
1139 void calc_hauptroutine_update_tissues(void) 1129 void calc_hauptroutine_update_tissues(void)
1140 { 1130 {
1141 if (char_I_const_ppO2 == 0) // new in v.101 1131 assert( 0.00 <= N2_ratio && N2_ratio <= 1.00 );
1132 assert( 0.00 <= He_ratio && He_ratio <= 1.00 );
1133 assert( (N2_ratio + He_ratio) <= 0.95 );
1134
1135 if (char_I_const_ppO2 == 0) // new in v.101
1142 pres_diluent = pres_respiration; // new in v.101 1136 pres_diluent = pres_respiration; // new in v.101
1143 else 1137 else
1144 { 1138 {
1145 pres_diluent = ((pres_respiration - const_ppO2)/(N2_ratio + He_ratio)); // new in v.101 1139 pres_diluent = ((pres_respiration - const_ppO2)/(N2_ratio + He_ratio)); // new in v.101
1146 if (pres_diluent > pres_respiration) // new in v.101 1140 if (pres_diluent > pres_respiration) // new in v.101
1182 // Calculate gas switches 1176 // Calculate gas switches
1183 // 1177 //
1184 // 1178 //
1185 void check_gas_switch(void) 1179 void check_gas_switch(void)
1186 { 1180 {
1181 overlay unsigned char temp_gas_switch = sim_gas_last_used;
1182
1187 calc_N2_ratio = N2_ratio; 1183 calc_N2_ratio = N2_ratio;
1188 calc_He_ratio = He_ratio; 1184 calc_He_ratio = He_ratio;
1189 1185
1190 if (char_I_const_ppO2 == 0) 1186 if (char_I_const_ppO2 == 0)
1191 { 1187 {
1192 deco_diluent = temp_deco; 1188 deco_diluent = temp_deco;
1193 calc_gas_switch = 0; 1189
1194 1190 if( deco_gas_change1 && (temp_deco < deco_gas_change1) )
1195 if(deco_gas_change1 && (temp_deco < deco_gas_change1))
1196 { 1191 {
1197 calc_N2_ratio = deco_N2_ratio1; 1192 calc_N2_ratio = deco_N2_ratio1;
1198 calc_He_ratio = deco_He_ratio1; 1193 calc_He_ratio = deco_He_ratio1;
1199 calc_gas_switch = 1; 1194 temp_gas_switch = 1;
1200 } 1195 }
1201 if(deco_gas_change2 && (temp_deco < deco_gas_change2)) 1196 if(deco_gas_change2 && (temp_deco < deco_gas_change2) )
1202 { 1197 {
1203 calc_N2_ratio = deco_N2_ratio2; 1198 calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01;
1204 calc_He_ratio = deco_He_ratio2; 1199 calc_He_ratio = char_I_deco_He_ratio2 * 0.01;
1205 calc_gas_switch = 2; 1200 temp_gas_switch = 2;
1206 } 1201 }
1207 if(deco_gas_change3 && (temp_deco < deco_gas_change3)) 1202 if(deco_gas_change3 && (temp_deco < deco_gas_change3))
1208 { 1203 {
1209 calc_N2_ratio = deco_N2_ratio3; 1204 calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01;
1210 calc_He_ratio = deco_He_ratio3; 1205 calc_He_ratio = char_I_deco_He_ratio3 * 0.01;
1211 calc_gas_switch = 3; 1206 temp_gas_switch = 3;
1212 } 1207 }
1213 if(deco_gas_change4 && (temp_deco < deco_gas_change4)) 1208 if(deco_gas_change4 && (temp_deco < deco_gas_change4))
1214 { 1209 {
1215 calc_N2_ratio = deco_N2_ratio4; 1210 calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01;
1216 calc_He_ratio = deco_He_ratio4; 1211 calc_He_ratio = char_I_deco_He_ratio4 * 0.01;
1217 calc_gas_switch = 4; 1212 temp_gas_switch = 4;
1218 } 1213 }
1219 if(deco_gas_change5 && (temp_deco < deco_gas_change5)) 1214 if(deco_gas_change5 && (temp_deco < deco_gas_change5))
1220 { 1215 {
1221 calc_N2_ratio = deco_N2_ratio5; 1216 calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01;
1222 calc_He_ratio = deco_He_ratio5; 1217 calc_He_ratio = char_I_deco_He_ratio5 * 0.01;
1223 calc_gas_switch = 4; 1218 temp_gas_switch = 5;
1224 } 1219 }
1225 } 1220 }
1226 else 1221
1222 // Should detect gas switch just once.
1223 if( temp_gas_switch != sim_gas_last_used )
1224 {
1225 sim_gas_last_used = temp_gas_switch;
1226 sim_gas_delay = read_custom_function(55);
1227 }
1228
1229 assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 );
1230 assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 );
1231 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 );
1232 }
1233
1234 //////////////////////////////////////////////////////////////////////////////
1235
1236 static void alveolar_presures(void)
1237 {
1238 if (char_I_const_ppO2 != 0)
1227 { 1239 {
1228 if (temp_deco > deco_ppO2_change) 1240 if (temp_deco > deco_ppO2_change)
1229 { 1241 {
1230 deco_diluent = ((temp_deco - const_ppO2)/(N2_ratio + He_ratio)); 1242 deco_diluent = ((temp_deco - const_ppO2)/(N2_ratio + He_ratio));
1231 } 1243 }
1235 } 1247 }
1236 } 1248 }
1237 1249
1238 if (deco_diluent > temp_deco) 1250 if (deco_diluent > temp_deco)
1239 deco_diluent = temp_deco; 1251 deco_diluent = temp_deco;
1240
1241 if (deco_diluent > 0.0627) 1252 if (deco_diluent > 0.0627)
1242 { 1253 {
1243 temp_atem = calc_N2_ratio * (deco_diluent - 0.0627); 1254 temp_atem = calc_N2_ratio * (deco_diluent - 0.0627);
1244 temp2_atem = calc_He_ratio * (deco_diluent - 0.0627); 1255 temp2_atem = calc_He_ratio * (deco_diluent - 0.0627);
1245 } 1256 }
1246 else 1257 else
1247 { 1258 {
1248 temp_atem = 0.0; 1259 temp_atem = 0.0;
1249 temp2_atem = 0.0; 1260 temp2_atem = 0.0;
1250 } 1261 }
1262 assert( 0.0 <= temp_atem && temp_atem < 14.0 );
1263 assert( 0.0 <= temp2_atem && temp2_atem < 14.0 );
1251 } 1264 }
1252 1265
1253 ////////////////////////////////////////////////////////////////////////////// 1266 //////////////////////////////////////////////////////////////////////////////
1254 // Compute stops. 1267 // Compute stops.
1255 // 1268 //
1260 { 1273 {
1261 overlay unsigned char loop; 1274 overlay unsigned char loop;
1262 1275
1263 for(loop = 0; loop < 16; ++loop) 1276 for(loop = 0; loop < 16; ++loop)
1264 { 1277 {
1265 calc_nextdecodepth(); 1278 // Do not ascent while doing a gas switch.
1279 if( sim_gas_delay == 0 )
1280 calc_nextdecodepth();
1266 1281
1267 //---- Finish computations once surface is reached ------------------- 1282 //---- Finish computations once surface is reached -------------------
1268 if( temp_depth_limit <= 0 ) 1283 if( temp_depth_limit <= 0 )
1269 { 1284 {
1270 copy_deco_table(); 1285 copy_deco_table();
1272 char_O_deco_status = 0; // calc nullzeit next time. 1287 char_O_deco_status = 0; // calc nullzeit next time.
1273 return; 1288 return;
1274 } 1289 }
1275 1290
1276 //---- Else, continue simulating the stops --------------------------- 1291 //---- Else, continue simulating the stops ---------------------------
1277 check_gas_switch(); // Also updates ppN2 and ppHe. 1292 if( sim_gas_delay == 0 )
1293 check_gas_switch(); // Calculate N2_ratio and He_ratio.
1294 else
1295 sim_gas_delay--;
1296
1297 alveolar_presures(); // Updates ppN2 and ppHe.
1278 1298
1279 sim_tissue(1); // Simulate compartiments for 1 minute. 1299 sim_tissue(1); // Simulate compartiments for 1 minute.
1280 update_deco_table(); // Add one minute stops. 1300 update_deco_table(); // Add one minute stops.
1281 } 1301 }
1282 1302
1299 temp_deco = pres_respiration; 1319 temp_deco = pres_respiration;
1300 1320
1301 // Loop until first top or surface is reached. 1321 // Loop until first top or surface is reached.
1302 for(;;) 1322 for(;;)
1303 { 1323 {
1304 temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min. 1324 // Do not ascent while doing a gas switch.
1325 if( sim_gas_delay == 0 )
1326 temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min.
1305 1327
1306 // Compute sim_lead_tissue_limit at GF_low (deepest stop). 1328 // Compute sim_lead_tissue_limit at GF_low (deepest stop).
1307 sim_limit(GF_low); 1329 sim_limit(GF_low);
1308 1330
1309 // Did we reach first stop ? 1331 // Did we reach first stop ?
1310 if( temp_deco <= sim_lead_tissue_limit ) 1332 if( temp_deco <= sim_lead_tissue_limit )
1311 break; //Yes: finished ! 1333 break; // Yes: finished !
1312 1334
1313 // Next stop is surface ? 1335 // Next stop is surface ?
1314 if( temp_deco <= pres_surface ) 1336 if( temp_deco <= pres_surface )
1315 break; // Yes: finished too. 1337 break; // Yes: finished too.
1316 1338
1317 //---- Simulat gas switches, and compute ppN2/ppHe at half the ascent: 1339 //---- Simulat gas switches
1318 temp_deco += 0.5; // Check gas change 5 meter below new depth. 1340 if( sim_gas_delay > 0 )
1341 {
1342 sim_gas_delay--; // Decrement switch delay
1343 temp_depth_limit = (temp_deco - pres_surface) / 0.09985;
1344 update_deco_table(); // And mark stop in table
1345 }
1346 else
1347 {
1348 temp_deco += 0.5; // Check gas change 5 meter below new depth.
1319 check_gas_switch(); 1349 check_gas_switch();
1320 temp_deco -= 0.5; // Back to new depth. 1350 temp_deco -= 0.5; // Back to new depth.
1351 }
1321 1352
1322 // Then simulate with the new gas pressures... (1min) 1353 // Then simulate with the new gas pressures... (1min)
1354 alveolar_presures(); // Calculated at true depth !
1323 sim_tissue(1); 1355 sim_tissue(1);
1324 } 1356 }
1325 temp_deco += 1.0; // Restore last correct depth. 1357 temp_deco += 1.0; // Restore last correct depth.
1326 } 1358 }
1327 1359
1387 { 1419 {
1388 char_O_gtissue_no = ci; 1420 char_O_gtissue_no = ci;
1389 calc_lead_tissue_limit = p; 1421 calc_lead_tissue_limit = p;
1390 } 1422 }
1391 } 1423 }
1424
1425 assert( char_O_gtissue_no < 16 );
1426 assert( 0.0 <= calc_lead_tissue_limit && calc_lead_tissue_limit <= 14.0);
1392 } 1427 }
1393 1428
1394 ////////////////////////////////////////////////////////////////////////////// 1429 //////////////////////////////////////////////////////////////////////////////
1395 // calc_nullzeit 1430 // calc_nullzeit
1396 // 1431 //
1404 1439
1405 char_O_nullzeit = 0; 1440 char_O_nullzeit = 0;
1406 for(loop = 1; loop <= 17; loop++) 1441 for(loop = 1; loop <= 17; loop++)
1407 { 1442 {
1408 backup_sim_pres_tissue(); 1443 backup_sim_pres_tissue();
1409 sim_tissue(2); 1444 sim_tissue(2); // 10 min.
1410 sim_limit(GF_high); 1445 sim_limit(GF_high);
1411 1446
1412 if( sim_lead_tissue_limit > pres_surface ) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately 1447 if( sim_lead_tissue_limit > pres_surface ) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately
1413 { 1448 {
1414 restore_sim_pres_tissue(); 1449 restore_sim_pres_tissue();
1420 1455
1421 if (char_O_nullzeit < 60) 1456 if (char_O_nullzeit < 60)
1422 { 1457 {
1423 for(loop=1; loop <= 10; loop++) 1458 for(loop=1; loop <= 10; loop++)
1424 { 1459 {
1425 sim_tissue(1); 1460 sim_tissue(1); // 1 min
1426 sim_limit(GF_high); 1461 sim_limit(GF_high);
1427 1462
1428 if( sim_lead_tissue_limit > pres_surface) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately 1463 if( sim_lead_tissue_limit > pres_surface) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately
1429 break; 1464 break;
1430 char_O_nullzeit++; 1465 char_O_nullzeit++;
1489 { 1524 {
1490 sim_pres_tissue[x] = pres_tissue[x]; 1525 sim_pres_tissue[x] = pres_tissue[x];
1491 (sim_pres_tissue+16)[x] = (pres_tissue+16)[x]; 1526 (sim_pres_tissue+16)[x] = (pres_tissue+16)[x];
1492 sim_pres_tissue_limit[x] = pres_tissue_limit[x]; 1527 sim_pres_tissue_limit[x] = pres_tissue_limit[x];
1493 } 1528 }
1529
1530 sim_gas_last_used = -1; // No switch yet.
1531 sim_lead_tissue_limit = 0.0;
1532 sim_lead_tissue_no = 255;
1494 } 1533 }
1495 1534
1496 ////////////////////////////////////////////////////////////////////////////// 1535 //////////////////////////////////////////////////////////////////////////////
1497 // sim_tissue 1536 // sim_tissue
1498 // 1537 //
1560 { 1599 {
1561 sim_lead_tissue_no = ci; 1600 sim_lead_tissue_no = ci;
1562 sim_lead_tissue_limit = p; 1601 sim_lead_tissue_limit = p;
1563 } 1602 }
1564 } // for ci 1603 } // for ci
1604
1605 assert( sim_lead_tissue_no < 16 );
1606 assert( 0.0 <= sim_lead_tissue_limit && sim_lead_tissue_limit <= 14.0);
1565 } 1607 }
1566 1608
1567 ////////////////////////////////////////////////////////////////////////////// 1609 //////////////////////////////////////////////////////////////////////////////
1568 // clear_deco_table 1610 // clear_deco_table
1569 // 1611 //
1627 // optimized in v.101 (var_N2_a) 1669 // optimized in v.101 (var_N2_a)
1628 // new code in v.102 1670 // new code in v.102
1629 // 1671 //
1630 static void calc_gradient_factor(void) 1672 static void calc_gradient_factor(void)
1631 { 1673 {
1674 overlay float gf;
1675 assert( char_O_gtissue_no < 16 );
1676
1632 // tissue > respiration (entsaettigungsvorgang) 1677 // tissue > respiration (entsaettigungsvorgang)
1633 // gradient ist wieviel prozent an limit mit basis tissue 1678 // gradient ist wieviel prozent an limit mit basis tissue
1634 // dh. 0% = respiration == tissue 1679 // dh. 0% = respiration == tissue
1635 // dh. 100% = respiration == limit 1680 // dh. 100% = respiration == limit
1636 temp_tissue = pres_tissue[char_O_gtissue_no] + pres_tissue[char_O_gtissue_no+16]; 1681 temp_tissue = pres_tissue[char_O_gtissue_no] + (pres_tissue+16)[char_O_gtissue_no];
1637 temp1 = temp_tissue - pres_respiration; 1682 if( temp_tissue < pres_respiration )
1638 temp2 = temp_tissue - pres_tissue_limit[char_O_gtissue_no]; // changed in v.102 1683 gf = 0.0;
1639 temp2 = temp1/temp2; 1684 else
1640 temp2 = temp2 * 100; // displayed in percent 1685 {
1641 if (temp2 < 0) 1686 gf = (temp_tissue - pres_respiration)
1642 temp2 = 0; 1687 / (temp_tissue - pres_tissue_limit[char_O_gtissue_no])
1643 if (temp2 > 255) 1688 * 100.0;
1644 temp2 = 255; 1689 if( gf > 255.0 ) gf = 255.0;
1645 if (temp1 < 0) 1690 if( gf < 0.0 ) gf = 0.0;
1646 char_O_gradient_factor = 0; 1691 }
1647 else 1692 char_O_gradient_factor = (unsigned char)gf;
1648 char_O_gradient_factor = (char)temp2;
1649
1650 temp3 = temp2;
1651 1693
1652 if (char_I_deco_model == 1) // calculate relative gradient factor 1694 if (char_I_deco_model == 1) // calculate relative gradient factor
1653 { 1695 {
1654 temp1 = (float)low_depth * 0.09995; 1696 overlay float rgf;
1655 temp2 = pres_respiration - pres_surface; 1697
1656 if (temp2 <= 0) 1698 if( low_depth == 0 )
1657 temp1 = GF_high; 1699 rgf = GF_high;
1658 else if (temp2 >= temp1) 1700 else
1659 temp1 = GF_low; 1701 {
1660 else 1702 overlay float temp1 = low_depth * 0.09995;
1661 temp1 = GF_low + (temp1 - temp2)/temp1*GF_delta; 1703 overlay float temp2 = pres_respiration - pres_surface;
1662 1704
1663 if (low_depth == 0) 1705 if (temp2 <= 0)
1664 temp1 = GF_high; 1706 rgf = GF_high;
1665 1707 else if (temp2 >= temp1)
1666 temp2 = temp3 / temp1; // temp3 is already in percent 1708 rgf = GF_low;
1667 if (temp2 < 0) 1709 else
1668 temp2 = 0; 1710 rgf = GF_low + (temp1 - temp2)/temp1*GF_delta;
1669 if (temp2 > 255) 1711 }
1670 temp2 = 255; 1712
1671 char_O_relative_gradient_GF = (char)temp2; 1713 rgf = gf / rgf; // gf is already in percent
1714 if( rgf < 0.0 ) rgf = 0.0;
1715 if( rgf > 255.0 ) rgf = 255.0;
1716 char_O_relative_gradient_GF = (unsigned char)rgf;
1672 } // calc relative gradient factor 1717 } // calc relative gradient factor
1673 else 1718 else
1674 { 1719 {
1675 char_O_relative_gradient_GF = char_O_gradient_factor; 1720 char_O_relative_gradient_GF = char_O_gradient_factor;
1676 } 1721 }
1683 // unchanged in v.101 1728 // unchanged in v.101
1684 // 1729 //
1685 void deco_calc_desaturation_time(void) 1730 void deco_calc_desaturation_time(void)
1686 { 1731 {
1687 overlay unsigned int desat_time; // For a particular compartiment, in min. 1732 overlay unsigned int desat_time; // For a particular compartiment, in min.
1688 1733 overlay float temp2;
1734 overlay float temp3;
1735 overlay float temp4;
1689 RESET_C_STACK 1736 RESET_C_STACK
1690 1737
1691 N2_ratio = 0.7902; // FIXED sum as stated in b"uhlmann 1738 N2_ratio = 0.7902; // FIXED sum as stated in b"uhlmann
1692 pres_surface = (float)int_I_pres_surface / 1000.0; 1739 pres_surface = (float)int_I_pres_surface / 1000.0;
1693 temp_atem = N2_ratio * (pres_surface - 0.0627); 1740 temp_atem = N2_ratio * (pres_surface - 0.0627);
1797 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system 1844 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system
1798 pres_surface = (float)int_I_pres_surface / 1000.0; // the b"uhlmann formula using pres_surface does not use the N2_ratio 1845 pres_surface = (float)int_I_pres_surface / 1000.0; // the b"uhlmann formula using pres_surface does not use the N2_ratio
1799 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body 1846 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body
1800 temp2_atem = 0.0; 1847 temp2_atem = 0.0;
1801 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142) 1848 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142)
1802 float_saturation_multiplier = char_I_saturation_multiplier / 100.0; 1849 float_saturation_multiplier = char_I_saturation_multiplier * 0.01;
1803 1850
1804 calc_tissue(1); // update the pressure in the 32 tissues in accordance with the new ambient pressure 1851 calc_tissue(1); // update the pressure in the 32 tissues in accordance with the new ambient pressure
1805 1852
1806 clear_deco_table(); 1853 clear_deco_table();
1807 char_O_deco_status = 0; 1854 char_O_deco_status = 0;
2002 // output is int_I_temp 2049 // output is int_I_temp
2003 2050
2004 void deco_calc_percentage(void) 2051 void deco_calc_percentage(void)
2005 { 2052 {
2006 RESET_C_STACK 2053 RESET_C_STACK
2007 temp1 = (float)int_I_temp; 2054 int_I_temp = (int)(int_I_temp * (char_I_temp / 100.0));
2008 temp2 = (float)char_I_temp / 100.0;
2009 temp3 = temp1 * temp2;
2010 int_I_temp = (int)temp3;
2011 } 2055 }
2012 2056
2013 ////////////////////////////////////////////////////////////////////////////// 2057 //////////////////////////////////////////////////////////////////////////////
2014 2058
2015 void deco_push_tissues_to_vault(void) 2059 void deco_push_tissues_to_vault(void)