comparison Discovery/Src/vpm.c @ 902:d4622533271d Evo_2_23 tip

VPM table mode: Because of the model maths, usage of float data type and so on it may happen that the TTS decreases during ascent and continues calculation of the vpm. To keep the values stable the vpm table mode has been introduces. Instead of continously calculation of the stops the stop time is decreased if the diver is close to a deco stop. If the table is violated (e.g. by not doing gas change) the table will be updated to the new, longer runtime. The table will not be switch back to a shorter version in case e.g. the missed gas change is performed
author Ideenmodellierer
date Wed, 02 Oct 2024 22:18:19 +0200
parents a0900e4df15c
children
comparison
equal deleted inserted replaced
901:e4e9acfde839 902:d4622533271d
130 static float rate_change[11]; 130 static float rate_change[11];
131 static short mix_change[11]; 131 static short mix_change[11];
132 132
133 static const _Bool vpm_b = true; 133 static const _Bool vpm_b = true;
134 134
135 static SDecoinfo vpmTable;
136
135 extern const float float_buehlmann_N2_factor_expositon_20_seconds[]; 137 extern const float float_buehlmann_N2_factor_expositon_20_seconds[];
136 extern const float float_buehlmann_He_factor_expositon_20_seconds[]; 138 extern const float float_buehlmann_He_factor_expositon_20_seconds[];
137 extern const float float_buehlmann_N2_factor_expositon_one_minute[]; 139 extern const float float_buehlmann_N2_factor_expositon_one_minute[];
138 extern const float float_buehlmann_He_factor_expositon_one_minute[]; 140 extern const float float_buehlmann_He_factor_expositon_one_minute[];
139 extern const float float_buehlmann_N2_factor_expositon_five_minutes[]; 141 extern const float float_buehlmann_N2_factor_expositon_five_minutes[];
217 float vpm_get_CNS(void) 219 float vpm_get_CNS(void)
218 { 220 {
219 return gCNS_VPM; 221 return gCNS_VPM;
220 } 222 }
221 223
224
225 void vpm_maintainTable(SLifeData* pLifeData,SDecoinfo* pDecoInfo)
226 {
227 static uint32_t lastDiveSecond = 0;
228 uint8_t actual_deco_stop = 0;
229 int8_t index = 0;
230 uint8_t decreaseStopTime = 1;
231
232 if(lastDiveSecond < pLifeData->dive_time_seconds)
233 {
234 lastDiveSecond = pLifeData->dive_time_seconds;
235 actual_deco_stop = decom_get_actual_deco_stop((SDiveState*)stateUsed);
236
237 pDecoInfo->output_time_to_surface_seconds = 0;
238 for(index = DECOINFO_STRUCT_MAX_STOPS -1 ;index >= 0; index--)
239 {
240 if(pDecoInfo->output_stop_length_seconds[index] > 0)
241 {
242 if(decreaseStopTime)
243 {
244 if((pLifeData->depth_meter > (float)(actual_deco_stop - 0.5))
245 && (pLifeData->depth_meter < (float)actual_deco_stop + 1.5))
246 {
247 pDecoInfo->output_stop_length_seconds[index]--;
248 decreaseStopTime = 0;
249 }
250 }
251 pDecoInfo->output_time_to_surface_seconds += pDecoInfo->output_stop_length_seconds[index];
252 }
253 }
254 pDecoInfo->output_time_to_surface_seconds += pLifeData->depth_meter / 10.0 * 60.0;
255 }
256 else if(lastDiveSecond > pLifeData->dive_time_seconds)
257 {
258 lastDiveSecond = pLifeData->dive_time_seconds;
259 }
260 }
261
222 int vpm_calc(SLifeData* pINPUT, 262 int vpm_calc(SLifeData* pINPUT,
223 SDiveSettings* pSettings, 263 SDiveSettings* pSettings,
224 SVpm* pVPM, 264 SVpm* pVPM,
225 SDecoinfo* 265 SDecoinfo*
226 pDECOINFO, 266 pDECOINFO,
227 int calc_what) 267 int calc_what)
228 { 268 {
269 static uint8_t vpmTableActive = 0;
270
229 vpm_init_1(); 271 vpm_init_1();
230 //decom_CreateGasChangeList(pSettings, pINPUT); 272 //decom_CreateGasChangeList(pSettings, pINPUT);
231 vpm_calc_what = calc_what; 273 vpm_calc_what = calc_what;
232 /**clear decoInfo*/ 274 /**clear decoInfo*/
275
276 if((vpmTableActive) && (vpm_calc_what == DECOSTOPS))
277 {
278 memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo)); /* save changes done by e.g. the simulator */
279 }
233 pDECOINFO->output_time_to_surface_seconds = 0; 280 pDECOINFO->output_time_to_surface_seconds = 0;
234 pDECOINFO->output_ndl_seconds = 0; 281 pDECOINFO->output_ndl_seconds = 0;
235 pDECOINFO->output_ceiling_meter = 0; 282 pDECOINFO->output_ceiling_meter = 0;
236 pDECOINFO->super_saturation = 0; 283 pDECOINFO->super_saturation = 0;
237 uint8_t tmp_calc_status; 284 uint8_t tmp_calc_status;
278 } 325 }
279 } 326 }
280 327
281 //Only Decostops not futute stops 328 //Only Decostops not futute stops
282 if(vpm_calc_what == DECOSTOPS) 329 if(vpm_calc_what == DECOSTOPS)
330 {
283 vpm_calc_status = tmp_calc_status; 331 vpm_calc_status = tmp_calc_status;
332 if(pSettings->vpm_tableMode) /* store the most conservative deco plan and stick to it. */
333 {
334 if((int16_t)(pDECOINFO->output_time_to_surface_seconds - vpmTable.output_time_to_surface_seconds) > 60)
335 {
336 memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo));
337 vpmTableActive = 1;
338 }
339 else
340 {
341 if(vpmTable.output_time_to_surface_seconds > 0)
342 {
343 vpm_maintainTable(pINPUT, &vpmTable);
344 vpmTable.output_ceiling_meter = pDECOINFO->output_ceiling_meter;
345 memcpy(pDECOINFO, &vpmTable, sizeof(SDecoinfo));
346 }
347 }
348 }
349 }
284 return vpm_calc_status; 350 return vpm_calc_status;
285 } 351 }
286 352
287 void vpm_saturation_after_ascent(SLifeData* input) 353 void vpm_saturation_after_ascent(SLifeData* input)
288 { 354 {
1003 float stop_time; 1069 float stop_time;
1004 int count = 0; 1070 int count = 0;
1005 static int dp_max; 1071 static int dp_max;
1006 static float surfacetime; 1072 static float surfacetime;
1007 _Bool first_stop = false; 1073 _Bool first_stop = false;
1008 1074 float roundingValue = 0.0;
1009 short stop_time_seconds; 1075
1076 uint16_t stop_time_seconds;
1010 1077
1011 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); 1078 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth);
1012 if(begin) 1079 if(begin)
1013 { 1080 {
1014 gCNS_VPM = 0; 1081 gCNS_VPM = 0;
1104 { 1171 {
1105 dp = 0; 1172 dp = 0;
1106 } 1173 }
1107 else 1174 else
1108 { 1175 {
1109 dp = 1 + (short)((deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10.0)) / step_size); 1176 roundingValue = (deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10.0)) / step_size;
1177 dp = 1 + r_nint(&roundingValue);
1110 } 1178 }
1111 1179
1112 //dp_max = (int)fmaxf(dp_max,dp); 1180 //dp_max = (int)fmaxf(dp_max,dp);
1113 if(dp > dp_max) 1181 if(dp > dp_max)
1114 { 1182 {
1115 dp_max = dp; 1183 dp_max = dp;
1116 } 1184 }
1117 if(dp < DECOINFO_STRUCT_MAX_STOPS) 1185 if(dp < DECOINFO_STRUCT_MAX_STOPS)
1118 { 1186 {
1119 stop_time_seconds = (short) fminf((999.9 * 60.0), (stop_time *60.0)); 1187 stop_time_seconds = (uint16_t)(fminf((999.9 * 60.0), (stop_time *60.0)));
1120 // 1188 //
1121 1189
1122 //if(vpm_calc_what == DECOSTOPS) 1190 //if(vpm_calc_what == DECOSTOPS)
1123 pDecoInfo->output_stop_length_seconds[dp] = stop_time_seconds; 1191 pDecoInfo->output_stop_length_seconds[dp] = stop_time_seconds;
1124 //else 1192 //else
2415 if(temp_segment_time > 1) 2483 if(temp_segment_time > 1)
2416 return CALC_NDL; 2484 return CALC_NDL;
2417 else 2485 else
2418 return CALC_BEGIN; 2486 return CALC_BEGIN;
2419 } 2487 }
2488
2489 void vpm_table_init()
2490 {
2491 vpmTable.output_time_to_surface_seconds = 0;
2492 }
2493