Mercurial > public > ostc4
annotate Discovery/Src/simulation.c @ 307:b6436edfb2c0 cleanup-4
cleanup: factor out unused stopwatch code
Visually, this looks a bit of a dangerous cleanup, but its not :-)
To explain this cleanup: stopwatch_seconds is never used, so assign
to it is useless, and the variable can be removed. Now,
stopwatch_start_at_this_dive_time_seconds is not used any more, so
remove it as well. Now, look at the boolResetStopwatch code. It
is used but only to reset itself. This makes the whole stopwatch
block in data_exchange_main.c a useless thing. All the other
cleanup is trivial.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Wed, 22 May 2019 22:22:15 +0200 |
parents | 43b44f8d4fb0 |
children | 1203255481e4 |
rev | line source |
---|---|
38 | 1 /////////////////////////////////////////////////////////////////////////////// |
2 /// -*- coding: UTF-8 -*- | |
3 /// | |
4 /// \file Discovery/Src/simulation.c | |
5 /// \brief Contains dive simulation functionality | |
6 /// \author Heinrichs Weikamp gmbh | |
7 /// \date 13-Oct-2014 | |
8 /// | |
9 /// \details | |
10 /// The simulation uses "extern SDiveState stateSim" defined in dataCentral.h" | |
11 /// | |
12 /// simulation_start(void) sets stateUsed to stateSim and initializes simulation | |
13 /// simulation_UpdateLifeData should be called at least once per second | |
14 /// simulation_end() sets stateUsed back to stateReal | |
15 /// | |
16 /// $Id$ | |
17 /////////////////////////////////////////////////////////////////////////////// | |
18 /// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh | |
19 /// | |
20 /// This program is free software: you can redistribute it and/or modify | |
21 /// it under the terms of the GNU General Public License as published by | |
22 /// the Free Software Foundation, either version 3 of the License, or | |
23 /// (at your option) any later version. | |
24 /// | |
25 /// This program is distributed in the hope that it will be useful, | |
26 /// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 /// GNU General Public License for more details. | |
29 /// | |
30 /// You should have received a copy of the GNU General Public License | |
31 /// along with this program. If not, see <http://www.gnu.org/licenses/>. | |
32 ////////////////////////////////////////////////////////////////////////////// | |
33 | |
34 #include <string.h> | |
35 #include "simulation.h" | |
36 | |
37 #include "decom.h" | |
38 #include "calc_crush.h" | |
39 #include "data_exchange.h" | |
40 #include "timer.h" | |
41 #include "check_warning.h" | |
42 #include "vpm.h" | |
43 #include "buehlmann.h" | |
44 #include "logbook_miniLive.h" | |
45 | |
46 //Private state variables | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
47 static float sim_aim_depth_meter; |
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
48 static _Bool sim_heed_decostops = 1; |
38 | 49 |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
50 static const float sim_descent_rate_meter_per_min = 20; |
38 | 51 |
52 | |
53 //Private functions | |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
54 static float sim_get_ambient_pressure(SDiveState * pDiveState); |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
55 static void sim_reduce_deco_time_one_second(SDiveState* pDiveState); |
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
56 static void simulation_set_aim_depth(int depth_meter); |
38 | 57 |
58 /** | |
59 ****************************************************************************** | |
60 * @brief sets heed_decostops_while_ascending | |
61 ****************************************************************************** | |
62 * @param heed_decostops_while_ascending : true -> deco_stops are considered while ascending | |
63 * @return void | |
64 */ | |
65 void simulation_set_heed_decostops(_Bool heed_decostops_while_ascending) | |
66 { | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
67 sim_heed_decostops = heed_decostops_while_ascending; |
38 | 68 } |
69 | |
70 /** | |
71 ****************************************************************************** | |
72 * @brief start of simulation | |
73 ****************************************************************************** | |
74 * @return void | |
75 */ | |
76 void simulation_start(int aim_depth) | |
77 { | |
78 copyDiveSettingsToSim(); | |
79 copyVpmRepetetiveDataToSim(); | |
80 //vpm_init(&stateSimGetPointerWrite()->vpm, stateSimGetPointerWrite()->diveSettings.vpm_conservatism, 0, 0); | |
81 stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth = 0; | |
82 stateSimGetPointerWrite()->mode = MODE_DIVE; | |
83 if(aim_depth <= 0) | |
84 aim_depth = 20; | |
85 simulation_set_aim_depth(aim_depth); | |
86 timer_init(); | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
87 set_stateUsedToSim(); |
38 | 88 stateSim.lifeData.boolResetAverageDepth = 1; |
89 decoLock = DECO_CALC_init_as_is_start_of_dive; | |
90 | |
91 stateSim.lifeData.apnea_total_max_depth_meter = 0; | |
92 } | |
93 | |
94 /** | |
95 ****************************************************************************** | |
96 * @brief end of simulation | |
97 ****************************************************************************** | |
98 * | |
99 * @return void | |
100 */ | |
101 void simulation_exit(void) | |
102 { | |
103 timer_Stopwatch_Stop(); | |
104 set_stateUsedToReal(); | |
105 } | |
106 | |
107 /** | |
108 ****************************************************************************** | |
109 * @brief simulates change of Lifedata (saturation, depth change, etc.) within one second | |
110 ****************************************************************************** | |
111 * | |
112 * @param checkOncePerSecond : true -> simulation in real time (function is evaluated only once per second) | |
113 * and copy of parts of LifeData from SmallCPU with each call from HAL_TIM_PeriodElapsedCallback() | |
114 * : false -> fast simulation (many simulation cycles per second are possible) | |
115 * @return void | |
116 */ | |
117 void simulation_UpdateLifeData( _Bool checkOncePerSecond) | |
118 { | |
119 SDiveState * pDiveState = &stateSim; | |
120 | |
121 static int last_second = -1; | |
122 static _Bool two_second = 0; | |
123 static float lastPressure_bar = 0; | |
124 | |
125 if(checkOncePerSecond) | |
126 { | |
127 pDiveState->lifeData.temperature_celsius = stateRealGetPointer()->lifeData.temperature_celsius; | |
128 pDiveState->lifeData.compass_heading = stateRealGetPointer()->lifeData.compass_heading; | |
129 pDiveState->lifeData.battery_charge = stateRealGetPointer()->lifeData.battery_charge; | |
130 | |
131 int now = current_second(); | |
132 if( last_second == now) | |
133 return; | |
134 last_second = now; | |
135 | |
136 if(!two_second) | |
137 two_second = 1; | |
138 else | |
139 { | |
140 two_second = 0; | |
141 if(lastPressure_bar >= 0) | |
142 { | |
143 //2 seconds * 30 == 1 minute, bar * 10 = meter | |
144 pDiveState->lifeData.ascent_rate_meter_per_min = (lastPressure_bar - pDiveState->lifeData.pressure_ambient_bar) * 30 * 10; | |
145 } | |
146 lastPressure_bar = pDiveState->lifeData.pressure_ambient_bar; | |
147 } | |
148 } | |
149 else if(pDiveState->lifeData.depth_meter <= (float)(decom_get_actual_deco_stop(pDiveState) + 0.001)) | |
150 sim_reduce_deco_time_one_second(pDiveState); | |
151 | |
152 pDiveState->lifeData.ppO2Sensor_bar[0] = stateRealGetPointer()->lifeData.ppO2Sensor_bar[0]; | |
153 pDiveState->lifeData.ppO2Sensor_bar[1] = stateRealGetPointer()->lifeData.ppO2Sensor_bar[1]; | |
154 pDiveState->lifeData.ppO2Sensor_bar[2] = stateRealGetPointer()->lifeData.ppO2Sensor_bar[2]; | |
155 pDiveState->lifeData.sensorVoltage_mV[0] = stateRealGetPointer()->lifeData.sensorVoltage_mV[0]; | |
156 pDiveState->lifeData.sensorVoltage_mV[1] = stateRealGetPointer()->lifeData.sensorVoltage_mV[1]; | |
157 pDiveState->lifeData.sensorVoltage_mV[2] = stateRealGetPointer()->lifeData.sensorVoltage_mV[2]; | |
158 | |
159 pDiveState->lifeData.dive_time_seconds += 1; | |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
160 pDiveState->lifeData.pressure_ambient_bar = sim_get_ambient_pressure(pDiveState); |
38 | 161 |
162 if(is_ambient_pressure_close_to_surface(&pDiveState->lifeData)) // new hw 170214 | |
163 { | |
164 if(!(stateSimGetPointer()->lifeData.counterSecondsShallowDepth)) | |
165 { | |
166 if(pDiveState->diveSettings.diveMode != DIVEMODE_Apnea) | |
167 pDiveState->lifeData.counterSecondsShallowDepth = settingsGetPointer()->timeoutDiveReachedZeroDepth - 15; | |
168 else | |
169 { | |
170 pDiveState->lifeData.apnea_last_dive_time_seconds = pDiveState->lifeData.dive_time_seconds; | |
171 if(pDiveState->lifeData.apnea_last_dive_time_seconds > pDiveState->lifeData.dive_time_seconds_without_surface_time) | |
172 pDiveState->lifeData.apnea_last_dive_time_seconds = pDiveState->lifeData.dive_time_seconds_without_surface_time; | |
173 pDiveState->lifeData.apnea_last_max_depth_meter = pDiveState->lifeData.max_depth_meter; | |
174 pDiveState->lifeData.counterSecondsShallowDepth = 1; | |
175 } | |
176 } | |
177 } | |
178 else | |
179 { | |
180 pDiveState->lifeData.counterSecondsShallowDepth = 0; | |
181 } | |
182 | |
304
43b44f8d4fb0
bugfix, simulator: fix the 1 sec difference between stopwatch and divetime
Jan Mulder <jlmulder@xs4all.nl>
parents:
300
diff
changeset
|
183 if(!is_ambient_pressure_close_to_surface(&pDiveState->lifeData) && !(stateSimGetPointer()->lifeData.counterSecondsShallowDepth) ) |
43b44f8d4fb0
bugfix, simulator: fix the 1 sec difference between stopwatch and divetime
Jan Mulder <jlmulder@xs4all.nl>
parents:
300
diff
changeset
|
184 { |
43b44f8d4fb0
bugfix, simulator: fix the 1 sec difference between stopwatch and divetime
Jan Mulder <jlmulder@xs4all.nl>
parents:
300
diff
changeset
|
185 pDiveState->lifeData.dive_time_seconds_without_surface_time += 1; |
43b44f8d4fb0
bugfix, simulator: fix the 1 sec difference between stopwatch and divetime
Jan Mulder <jlmulder@xs4all.nl>
parents:
300
diff
changeset
|
186 } |
43b44f8d4fb0
bugfix, simulator: fix the 1 sec difference between stopwatch and divetime
Jan Mulder <jlmulder@xs4all.nl>
parents:
300
diff
changeset
|
187 |
38 | 188 pDiveState->lifeData.depth_meter = (pDiveState->lifeData.pressure_ambient_bar - pDiveState->lifeData.pressure_surface_bar) * 10.0f; |
189 if(pDiveState->lifeData.max_depth_meter < pDiveState->lifeData.depth_meter) | |
190 pDiveState->lifeData.max_depth_meter = pDiveState->lifeData.depth_meter; | |
191 | |
192 /* apnoe specials | |
193 */ | |
194 if(pDiveState->diveSettings.diveMode == DIVEMODE_Apnea) | |
195 { | |
196 if(pDiveState->lifeData.max_depth_meter > pDiveState->lifeData.apnea_total_max_depth_meter) | |
197 pDiveState->lifeData.apnea_total_max_depth_meter = pDiveState->lifeData.max_depth_meter; | |
198 | |
199 if(pDiveState->lifeData.counterSecondsShallowDepth) | |
200 { | |
201 pDiveState->lifeData.dive_time_seconds = 0; | |
202 pDiveState->lifeData.max_depth_meter = 0; | |
203 pDiveState->lifeData.boolResetAverageDepth = 1; | |
204 } | |
205 } | |
206 | |
207 /* average depth | |
208 */ | |
209 float *AvgDepthValue = &pDiveState->lifeData.average_depth_meter; | |
210 float DepthNow = pDiveState->lifeData.depth_meter; | |
211 uint32_t *AvgDepthCount = &pDiveState->lifeData.internal.average_depth_meter_Count; | |
212 uint32_t *AvgDepthTimer = &pDiveState->lifeData.internal.average_depth_last_update_dive_time_seconds_without_surface_time; | |
213 uint32_t AvgSecondsSinceLast; | |
214 uint32_t DiveTime = pDiveState->lifeData.dive_time_seconds_without_surface_time; | |
215 | |
216 if(pDiveState->lifeData.boolResetAverageDepth) | |
217 { | |
218 *AvgDepthValue = DepthNow; | |
219 *AvgDepthCount = 1; | |
220 *AvgDepthTimer = DiveTime; | |
221 pDiveState->lifeData.boolResetAverageDepth = 0; | |
222 } | |
223 else if (DiveTime > *AvgDepthTimer) | |
224 { | |
225 AvgSecondsSinceLast = DiveTime - *AvgDepthTimer; | |
226 for(int i=0;i<AvgSecondsSinceLast;i++) | |
227 { | |
228 *AvgDepthValue = (*AvgDepthValue * *AvgDepthCount + DepthNow) / (*AvgDepthCount + 1); | |
229 *AvgDepthCount += 1; | |
230 } | |
231 *AvgDepthTimer = DiveTime; | |
232 } | |
233 if(*AvgDepthCount == 0) | |
234 *AvgDepthValue = 0; | |
235 | |
236 /* Exposure Tissues | |
237 */ | |
238 decom_tissues_exposure(1, &pDiveState->lifeData); | |
239 decom_oxygen_calculate_cns_exposure(1, &pDiveState->lifeData.actualGas, pDiveState->lifeData.pressure_ambient_bar, &pDiveState->lifeData.cns); | |
233
9f0efc4df01e
cleanup, bugfix: do not exit simulator on 5h dive time
Jan Mulder <jlmulder@xs4all.nl>
parents:
225
diff
changeset
|
240 |
38 | 241 if(stateSimGetPointer()->lifeData.counterSecondsShallowDepth) |
242 { | |
243 stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth += 1; | |
244 if(stateSimGetPointer()->lifeData.counterSecondsShallowDepth >= settingsGetPointer()->timeoutDiveReachedZeroDepth) | |
245 simulation_exit(); | |
246 } | |
247 vpm_crush(pDiveState); | |
248 } | |
249 | |
250 /** | |
251 ****************************************************************************** | |
252 * @brief adds extra time for fast simulation | |
253 ****************************************************************************** | |
254 *@param minutes | |
255 * @return float : new pressure | |
256 */ | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
257 static void simulation_add_time(int minutes) |
38 | 258 { |
259 for(int i = 0; i < 60 * minutes; i++) | |
260 { | |
261 simulation_UpdateLifeData(0); | |
262 updateMiniLiveLogbook(0); | |
263 timer_UpdateSecond(0); | |
264 } | |
265 } | |
266 | |
267 /** | |
268 ****************************************************************************** | |
269 * @brief get aim_depth | |
270 ****************************************************************************** | |
271 * @return sim_aim_depth_meter; | |
272 */ | |
273 | |
274 uint16_t simulation_get_aim_depth(void) | |
275 { | |
276 return (uint16_t)sim_aim_depth_meter; | |
277 } | |
278 | |
279 /** | |
280 ****************************************************************************** | |
281 * @brief get heed decostops | |
282 ****************************************************************************** | |
283 * @return true if ascend follows decostops; | |
284 */ | |
285 | |
286 _Bool simulation_get_heed_decostops(void) | |
287 { | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
288 return sim_heed_decostops; |
38 | 289 } |
290 | |
291 /** | |
292 ****************************************************************************** | |
293 * @brief sets aim_depth | |
294 ****************************************************************************** | |
295 *@param depth_meter | |
296 * @return float : new pressure | |
297 */ | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
298 static void simulation_set_aim_depth(int depth_meter) |
38 | 299 { |
300 sim_aim_depth_meter = depth_meter; | |
301 } | |
302 | |
303 /** | |
304 ****************************************************************************** | |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
305 * @brief simulates ambient pressure depending on aim depth |
38 | 306 ****************************************************************************** |
307 * @note if aim_depth != actual depth, the depth change within one second | |
308 * (depending on descent or ascent) rate is calculated | |
309 * @param SDiveState* pDiveState: | |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
310 * @return float : new ambient pressure |
38 | 311 */ |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
312 static float sim_get_ambient_pressure(SDiveState * pDiveState) |
38 | 313 { |
314 //Calc next depth | |
315 uint8_t actual_deco_stop = decom_get_actual_deco_stop(pDiveState); | |
316 float depth_meter = pDiveState->lifeData.depth_meter; | |
317 float surface_pressure_bar = pDiveState->lifeData.pressure_surface_bar; | |
318 if(depth_meter < sim_aim_depth_meter) | |
319 { | |
320 depth_meter = depth_meter + sim_descent_rate_meter_per_min / 60; | |
321 if(depth_meter > sim_aim_depth_meter) | |
322 depth_meter = sim_aim_depth_meter; | |
323 } | |
324 else if(depth_meter > sim_aim_depth_meter) | |
325 { | |
326 | |
327 depth_meter -= pDiveState->diveSettings.ascentRate_meterperminute / 60; | |
328 if(depth_meter < sim_aim_depth_meter) | |
329 depth_meter = sim_aim_depth_meter; | |
330 | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
331 if(sim_heed_decostops && depth_meter < actual_deco_stop) |
38 | 332 { |
333 if(actual_deco_stop < (depth_meter + pDiveState->diveSettings.ascentRate_meterperminute / 60)) | |
334 depth_meter = actual_deco_stop; | |
335 else | |
336 depth_meter += pDiveState->diveSettings.ascentRate_meterperminute / 60; | |
337 } | |
338 | |
339 } | |
340 | |
341 return surface_pressure_bar + depth_meter / 10; | |
342 } | |
343 | |
344 | |
345 /** | |
346 ****************************************************************************** | |
347 * @brief Reduces deco time of deepest stop by one second | |
348 ****************************************************************************** | |
349 * @note called during fast simulation | |
350 * @param SDiveState* pDiveState: | |
351 * @return void | |
352 */ | |
300
5ca177d2df5d
cleanup: remove commented/unused code, make static
Jan Mulder <jlmulder@xs4all.nl>
parents:
233
diff
changeset
|
353 static void sim_reduce_deco_time_one_second(SDiveState* pDiveState) |
38 | 354 { |
355 SDecoinfo* pDecoinfo; | |
356 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
357 pDecoinfo = &pDiveState->decolistBuehlmann; | |
358 else | |
359 pDecoinfo = &pDiveState->decolistVPM; | |
360 | |
361 //Reduce deco time of deepest stop by one second | |
362 for(int i = DECOINFO_STRUCT_MAX_STOPS -1 ;i >= 0; i--) | |
363 { | |
364 if(pDecoinfo->output_stop_length_seconds[i] > 0) | |
365 { | |
366 pDecoinfo->output_stop_length_seconds[i]--; | |
367 break; | |
368 } | |
369 } | |
370 } | |
371 | |
372 SDecoinfo* simulation_decoplaner(uint16_t depth_meter, uint16_t intervall_time_minutes, uint16_t dive_time_minutes, uint8_t *gasChangeListDepthGas20x2) | |
373 { | |
374 uint8_t ptrGasChangeList = 0; // new hw 160704 | |
375 | |
376 SDiveState * pDiveState = &stateSim; | |
377 copyDiveSettingsToSim(); | |
378 vpm_init(&pDiveState->vpm, pDiveState->diveSettings.vpm_conservatism, 0, 0); | |
379 //buehlmann_init(); | |
380 //timer_init(); | |
381 memset(&pDiveState->events,0, sizeof(SEvents)); | |
382 pDiveState->diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = 0; | |
383 //Calc desaturation during intervall (with Air) | |
384 setActualGasAir(&pDiveState->lifeData); | |
385 if(intervall_time_minutes > 0) | |
386 { | |
387 decom_tissues_exposure(intervall_time_minutes * 60, &pDiveState->lifeData); | |
388 decom_oxygen_calculate_cns_degrade(&pDiveState->lifeData.cns, intervall_time_minutes * 60); | |
389 } | |
390 | |
391 //Switch to first Gas | |
392 setActualGasFirst(&pDiveState->lifeData); | |
393 | |
394 // new hw 160704 | |
395 if(gasChangeListDepthGas20x2) | |
396 { | |
397 gasChangeListDepthGas20x2[ptrGasChangeList++] = 0; | |
398 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->lifeData.actualGas.GasIdInSettings; | |
399 gasChangeListDepthGas20x2[0] =0; // depth zero | |
400 } | |
401 | |
402 //Going down / descent | |
403 simulation_set_aim_depth(depth_meter); | |
404 for(int i = 0; i < 60 * dive_time_minutes; i++) | |
405 { | |
406 simulation_UpdateLifeData(0); | |
407 check_warning2(pDiveState); | |
408 if(pDiveState->warnings.betterGas) | |
409 { | |
410 setActualGas(&pDiveState->lifeData,actualBetterGasId(),pDiveState->lifeData.actualGas.setPoint_cbar); | |
411 if(gasChangeListDepthGas20x2 && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) | |
412 { | |
413 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->lifeData.depth_meter; | |
414 gasChangeListDepthGas20x2[ptrGasChangeList++] = actualBetterGasId(); | |
415 } | |
416 } | |
417 } | |
418 | |
419 decom_CreateGasChangeList(&pDiveState->diveSettings, &pDiveState->lifeData); // was there before and needed for buehlmann_calc_deco and vpm_calc | |
420 | |
421 // new hw 160704 | |
422 if(gasChangeListDepthGas20x2 && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) | |
423 { | |
424 // change direction from better gas to deco gas | |
425 gasChangeListDepthGas20x2[ptrGasChangeList++] = 255; | |
426 gasChangeListDepthGas20x2[ptrGasChangeList++] = 255; | |
427 | |
428 // ascend (deco) gases | |
429 for(int i=1; i<=5;i++) | |
430 { | |
431 if(pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
432 break; | |
433 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero; | |
434 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].GasIdInSettings; | |
435 } | |
436 gasChangeListDepthGas20x2[0] = 0; | |
437 } | |
438 | |
439 // deco and ascend calc | |
440 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
441 { | |
442 /* this does modify the cns now 11.06.2015 */ | |
443 buehlmann_calc_deco(&pDiveState->lifeData,&pDiveState->diveSettings,&pDiveState->decolistBuehlmann); | |
444 pDiveState->lifeData.cns += buehlmann_get_gCNS(); | |
445 return &pDiveState->decolistBuehlmann; | |
446 } | |
447 else | |
448 { | |
449 /* this does modify the cns now 11.06.2015 */ | |
450 vpm_calc(&pDiveState->lifeData,&pDiveState->diveSettings,&pDiveState->vpm,&pDiveState->decolistVPM, DECOSTOPS); | |
451 pDiveState->lifeData.cns += vpm_get_CNS(); | |
452 return &pDiveState->decolistVPM; | |
453 } | |
454 } | |
455 | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
176
diff
changeset
|
456 static float sGChelper_bar(uint16_t depth_meter) |
38 | 457 { |
458 SDiveState * pDiveState = &stateSim; | |
459 float ambient, surface, density, meter; | |
460 | |
461 surface = pDiveState->lifeData.pressure_surface_bar; | |
462 | |
463 if(!depth_meter) | |
464 return surface; | |
465 | |
466 density = ((float)( 100 + settingsGetPointer()->salinity)) / 100.0f; | |
467 meter = depth_meter * (0.09807f * density); | |
468 ambient = (meter + surface); | |
469 | |
470 return ambient; | |
471 } | |
472 | |
473 | |
474 /** | |
475 ****************************************************************************** | |
476 * @brief simulation_helper_change_points | |
477 ****************************************************************************** | |
478 * @param | |
479 * @return void | |
480 */ | |
481 void simulation_helper_change_points(SSimDataSummary *outputSummary, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, const uint8_t *gasChangeListDepthGas20x2) | |
482 { | |
483 uint8_t ptrDecoInfo = 0; | |
484 uint16_t actualDepthPoint = 0; | |
485 uint16_t nextDepthPoint = 0; | |
486 uint8_t actualConsumGasId = 0; | |
487 uint8_t nextGasChangeMeter = 0; | |
488 uint8_t ptrChangeList = 0; | |
489 | |
490 float timeThis = 0; | |
491 float timeSummary = 0; | |
492 float sim_descent_rate_meter_per_min_local = 10; | |
493 float sim_ascent_rate_meter_per_min_local = 10; | |
494 | |
495 SDiveState * pDiveState = &stateSim; | |
496 | |
497 uint8_t depthDecoNext, depthLast, depthSecond, depthInc; | |
498 | |
499 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
500 { | |
501 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
502 sim_ascent_rate_meter_per_min_local = pDiveState->diveSettings.ascentRate_meterperminute; | |
503 } | |
504 else | |
505 { | |
506 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
507 sim_ascent_rate_meter_per_min_local = 10;// fix in vpm_calc_deco(); | |
508 } | |
509 | |
510 outputSummary->descentRateMeterPerMinute = sim_descent_rate_meter_per_min_local; | |
511 outputSummary->ascentRateMeterPerMinute = sim_ascent_rate_meter_per_min_local; | |
512 | |
513 // bottom gas ppO2 | |
514 if(gasChangeListDepthGas20x2) | |
515 { | |
516 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
517 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
518 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
519 | |
520 while(actualDepthPoint < depth_meter) | |
521 { | |
522 if(nextGasChangeMeter && (nextGasChangeMeter < depth_meter) && (gasChangeListDepthGas20x2[ptrChangeList] != 255)) // list has 255,255 for turn from travel to deco | |
523 { | |
524 nextDepthPoint = nextGasChangeMeter; | |
525 } | |
526 else | |
527 { | |
528 nextDepthPoint = depth_meter; | |
529 } | |
530 | |
531 if(actualConsumGasId > 5) // safety first | |
532 actualConsumGasId = 0; | |
533 | |
534 actualDepthPoint = nextDepthPoint; | |
535 | |
536 if(actualDepthPoint != depth_meter) | |
537 { | |
538 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
539 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
540 } | |
541 } | |
542 } | |
543 else | |
544 { | |
545 actualConsumGasId = pDiveState->lifeData.actualGas.GasIdInSettings; | |
546 nextGasChangeMeter = 0; | |
547 } | |
548 outputSummary->ppO2AtBottom = (sGChelper_bar(depth_meter) - WATER_VAPOUR_PRESSURE) * pDiveState->diveSettings.gas[actualConsumGasId].oxygen_percentage / 100.0f; | |
549 | |
550 | |
551 // going down | |
552 actualDepthPoint = 0; | |
553 nextDepthPoint = depth_meter; | |
554 | |
555 timeThis = ((float)(nextDepthPoint - actualDepthPoint)) / sim_descent_rate_meter_per_min_local; | |
556 timeSummary += timeThis; | |
557 outputSummary->timeToBottom = (uint16_t)timeThis; | |
558 | |
559 // bottom time | |
560 timeThis = ((float)dive_time_minutes) - timeSummary; | |
561 timeSummary += timeThis; | |
562 outputSummary->timeAtBottom = (uint16_t)timeSummary; | |
563 | |
564 | |
565 // ascend to first deco stop | |
566 actualDepthPoint = depth_meter; // that is where we are | |
567 timeThis = 0; | |
568 | |
569 if(!decoInfoInput->output_stop_length_seconds[0]) // NDL dive | |
570 { | |
571 depthLast = 0; | |
572 ptrDecoInfo = 0; | |
573 depthDecoNext = 0; | |
574 } | |
575 else | |
576 { | |
577 // prepare deco stop list | |
578 depthLast = (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10); | |
579 depthSecond = (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10); | |
580 depthInc = (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10); | |
581 | |
582 for(ptrDecoInfo=DECOINFO_STRUCT_MAX_STOPS-1; ptrDecoInfo>0; ptrDecoInfo--) | |
583 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; | |
584 | |
585 if(ptrDecoInfo == 0) | |
586 { | |
587 depthDecoNext = depthLast; | |
588 } | |
589 else | |
590 depthDecoNext = depthSecond + (( ptrDecoInfo - 1 )* depthInc); | |
591 } | |
592 | |
593 nextDepthPoint = depthDecoNext; | |
594 if(actualDepthPoint > nextDepthPoint) | |
595 { | |
596 // flip signs! It's going up | |
597 timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; | |
598 actualDepthPoint = nextDepthPoint; // that is where we are | |
599 } | |
600 timeSummary += timeThis; | |
601 outputSummary->timeToFirstStop = (uint16_t)timeSummary; | |
602 outputSummary->depthMeterFirstStop = actualDepthPoint; | |
603 | |
604 //ascent | |
605 nextDepthPoint = 0; | |
606 timeThis = 0; | |
607 if(actualDepthPoint > nextDepthPoint) // only if deco | |
608 { | |
609 // ascent time | |
610 timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; | |
611 | |
612 // deco stop time | |
613 for(ptrDecoInfo=0;ptrDecoInfo < DECOINFO_STRUCT_MAX_STOPS; ptrDecoInfo++) | |
614 { | |
615 timeThis += decoInfoInput->output_stop_length_seconds[ptrDecoInfo] / 60; | |
616 if(!decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; | |
617 } | |
618 } | |
619 timeSummary += timeThis; | |
620 outputSummary->timeToSurface = (uint16_t)timeSummary; | |
621 | |
622 } | |
623 | |
624 | |
625 /** | |
626 ****************************************************************************** | |
627 * @brief simulation_gas_consumption | |
628 ****************************************************************************** | |
629 * @note called by openEdit_PlanResult() in tMenuEditPlanner.c | |
630 * @note the ascend and descend time is taken from pDiveState->lifeData.ascent_rate_meter_per_min and const float sim_descent_rate_meter_per_min | |
631 * @param outputConsumptionList list from 1 to 5 for gas 1 to 5 | |
632 * @param depth_meter for descend | |
633 * @param dive_time_minutes for descend and bottom time | |
634 * @param the calculated deco list | |
635 * @param gasConsumTravelInput: how many l/min for all but deco stops | |
636 * @param gasConsumDecoInput: how many l/min for deco stops only | |
637 * @return void | |
638 */ | |
639 | |
640 void simulation_gas_consumption(uint16_t *outputConsumptionList, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, uint8_t gasConsumTravelInput, uint8_t gasConsumDecoInput, const uint8_t *gasChangeListDepthGas20x2) | |
641 { | |
642 uint8_t ptrDecoInfo = 0; | |
643 uint8_t ptrChangeList = 0; | |
644 uint8_t actualConsumGasId = 0; | |
645 uint8_t nextGasChangeMeter = 0; | |
646 uint16_t actualDepthPoint = 0; | |
647 uint16_t nextDepthPoint = 0; | |
648 uint16_t inBetweenDepthPoint = 0; | |
649 float timeThis = 0; | |
650 float consumThis = 0; | |
651 float timeSummary = 0; | |
652 float outputConsumptionTempFloat[6]; | |
653 float sim_descent_rate_meter_per_min_local = 10; | |
654 float sim_ascent_rate_meter_per_min_local = 10; | |
655 | |
656 SDiveState * pDiveState = &stateSim; | |
657 | |
51
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
658 uint8_t depthDecoNext = 0; |
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
659 uint8_t depthLast = 0; |
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
660 uint8_t depthSecond = 0; |
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
661 uint8_t depthInc = 0; |
38 | 662 |
663 for(int i = 1; i < 6; i++) | |
664 outputConsumptionTempFloat[i] = 0; | |
665 | |
666 if(gasChangeListDepthGas20x2) | |
667 { | |
668 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
669 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
670 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
671 } | |
672 else | |
673 { | |
674 actualConsumGasId = pDiveState->lifeData.actualGas.GasIdInSettings; | |
675 nextGasChangeMeter = 0; | |
676 } | |
677 | |
678 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
679 { | |
680 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
681 sim_ascent_rate_meter_per_min_local = pDiveState->diveSettings.ascentRate_meterperminute; | |
682 } | |
683 else | |
684 { | |
685 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
686 sim_ascent_rate_meter_per_min_local = 10;// fix in vpm_calc_deco(); | |
687 } | |
688 | |
689 // while((nextGasChangeMeter < depth_meter) && (actualDepthPoint < depth_meter)) | |
690 while(actualDepthPoint < depth_meter) | |
691 { | |
692 if(nextGasChangeMeter && (nextGasChangeMeter < depth_meter) && (gasChangeListDepthGas20x2[ptrChangeList] != 255)) // list has 255,255 for turn from travel to deco | |
693 { | |
694 nextDepthPoint = nextGasChangeMeter; | |
695 } | |
696 else | |
697 { | |
698 nextDepthPoint = depth_meter; | |
699 } | |
700 | |
701 if(actualConsumGasId > 5) // safety first | |
702 actualConsumGasId = 0; | |
703 | |
704 timeThis = ((float)(nextDepthPoint - actualDepthPoint)) / sim_descent_rate_meter_per_min_local; | |
705 if(actualDepthPoint) // not if on surface | |
706 { | |
707 consumThis = ((float)gasConsumTravelInput) * sGChelper_bar(actualDepthPoint) * timeThis; | |
708 } | |
709 consumThis += ((float)gasConsumTravelInput) * sGChelper_bar(nextDepthPoint -actualDepthPoint) * timeThis / 2; | |
710 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
711 timeSummary += timeThis; | |
712 | |
713 actualDepthPoint = nextDepthPoint; | |
714 | |
715 if(actualDepthPoint != depth_meter) | |
716 { | |
717 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
718 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
719 } | |
720 } | |
721 | |
722 // bottom Time | |
723 timeThis = ((float)dive_time_minutes) - timeSummary; | |
724 | |
725 if(timeThis > 0) | |
726 { | |
727 consumThis = ((float)gasConsumTravelInput) * sGChelper_bar(depth_meter) * timeThis; | |
728 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
729 } | |
730 | |
731 // ascend with deco stops prepare | |
732 if(gasChangeListDepthGas20x2) | |
733 { | |
734 ptrChangeList++;// gasChangeListDepthGas20x2[ptrChangeList++]; // should be the 255 | |
735 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
736 } | |
737 else | |
738 { | |
739 nextGasChangeMeter = 0; | |
740 } | |
741 | |
742 | |
743 if(!decoInfoInput->output_stop_length_seconds[0]) // NDL dive | |
744 { | |
745 depthLast = 0; | |
746 ptrDecoInfo = 0; | |
747 } | |
748 else | |
749 { | |
750 // prepare deco stop list | |
751 depthLast = (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10); | |
752 depthSecond = (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10); | |
753 depthInc = (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10); | |
754 | |
755 for(ptrDecoInfo=DECOINFO_STRUCT_MAX_STOPS-1; ptrDecoInfo>0; ptrDecoInfo--) | |
756 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; | |
757 } | |
758 | |
759 actualDepthPoint = depth_meter; // that is where we are | |
760 | |
761 // ascend with deco stops | |
762 while(actualDepthPoint) | |
763 { | |
764 if(ptrDecoInfo == 0) | |
765 { | |
766 depthDecoNext = depthLast; | |
767 } | |
768 else | |
769 depthDecoNext = depthSecond + (( ptrDecoInfo - 1 )* depthInc); | |
770 | |
771 if(nextGasChangeMeter && (nextGasChangeMeter > depthDecoNext)) | |
772 { | |
773 nextDepthPoint = nextGasChangeMeter; | |
774 } | |
775 else | |
776 { | |
777 nextDepthPoint = depthDecoNext; | |
778 } | |
779 | |
780 if(actualConsumGasId > 5) // safety first | |
781 actualConsumGasId = 0; | |
782 | |
783 if(actualDepthPoint > nextDepthPoint) | |
784 { | |
785 // flip signs! It's going up | |
786 timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; | |
787 inBetweenDepthPoint = nextDepthPoint + ((actualDepthPoint - nextDepthPoint)/2); | |
788 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(inBetweenDepthPoint) * timeThis; | |
789 /* | |
790 if(nextDepthPoint) | |
791 { | |
792 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(nextDepthPoint) * timeThis; | |
793 } | |
794 else | |
795 { | |
796 consumThis = 0; | |
797 } | |
798 consumThis += ((float)gasConsumDecoInput) * sGChelper_bar(actualDepthPoint - nextDepthPoint) * timeThis / 2; | |
799 */ | |
800 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
801 } | |
802 | |
803 if(nextGasChangeMeter && (nextDepthPoint == nextGasChangeMeter)) | |
804 { | |
805 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
806 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
807 } | |
808 | |
809 if(actualConsumGasId > 5) // safety first | |
810 actualConsumGasId = 0; | |
811 | |
812 if(nextDepthPoint && (nextDepthPoint == depthDecoNext)) | |
813 { | |
814 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) | |
815 { | |
816 timeThis = ((float)(decoInfoInput->output_stop_length_seconds[ptrDecoInfo])) / 60.0f; | |
817 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(nextDepthPoint) * timeThis; | |
818 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
819 } | |
820 if(ptrDecoInfo != 0) | |
821 { | |
822 ptrDecoInfo--; | |
823 } | |
824 else | |
825 { | |
826 depthLast = 0; | |
827 } | |
828 } | |
829 actualDepthPoint = nextDepthPoint; | |
830 } | |
831 | |
832 // copy and return | |
833 for(int i = 1; i < 6; i++) | |
834 outputConsumptionList[i] = (uint16_t)(outputConsumptionTempFloat[i]); | |
835 } | |
836 | |
837 /** | |
838 ****************************************************************************** | |
839 * @brief Simulator control during simulated dive | |
840 ****************************************************************************** | |
841 * @note called by user via tHomeDiveMenuControl() | |
842 * @param void | |
843 * @return void | |
844 */ | |
845 | |
846 | |
847 void Sim_Descend (void) | |
848 { | |
849 stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth = 0; | |
850 if(simulation_get_aim_depth() < 200) | |
851 simulation_set_aim_depth(simulation_get_aim_depth() + 1); | |
852 } | |
853 | |
854 | |
855 void Sim_Ascend (void) | |
856 { | |
857 if(simulation_get_aim_depth() > 0) | |
858 simulation_set_aim_depth(simulation_get_aim_depth() - 1); | |
859 } | |
860 | |
861 | |
862 void Sim_Divetime (void) | |
863 { | |
864 simulation_add_time(5); | |
865 } | |
866 | |
867 | |
868 void Sim_Quit (void) | |
869 { | |
870 if(stateSimGetPointer()->lifeData.counterSecondsShallowDepth) | |
871 { | |
872 simulation_exit(); | |
873 return; | |
874 } | |
875 | |
876 if(simulation_get_aim_depth() > 0) | |
877 { | |
878 simulation_set_aim_depth(0); | |
879 } | |
880 else | |
881 { | |
882 stateSimGetPointerWrite()->lifeData.depth_meter = 0; | |
883 if(stateSimGetPointer()->diveSettings.diveMode == DIVEMODE_Apnea) | |
884 { | |
885 stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth = 1; | |
886 } | |
887 else | |
888 { | |
889 stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth = settingsGetPointer()->timeoutDiveReachedZeroDepth - 15; | |
890 } | |
891 } | |
892 } |