comparison Discovery/Src/check_warning.c @ 38:5f11787b4f42

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children 1b9847d40e81
comparison
equal deleted inserted replaced
37:ccc45c0e1ea2 38:5f11787b4f42
1 /**
2 ******************************************************************************
3 * @file check_warning.c
4 * @author heinrichs weikamp gmbh
5 * @date 17-Nov-2014
6 * @version V0.0.1
7 * @since 17-Nov-2014
8 * @brief check and set warnings for warnings
9 *
10 @verbatim
11 ==============================================================================
12 ##### How to use #####
13 ==============================================================================
14 OSTC3 Warnings:
15 niedriger Batteriezustand (
16 zu hoher oder zu niedriger Sauerstoffpartialdruck (ppO2) 0.2 - 1.6
17 zu hoher CNS (Gefahr der Sauerstoffvergiftung) 90%
18 zu hohe Gradientenfaktoren 90 - 90
19 Missachtung der Dekostopps (der �berschrittene Dekostopp wird rot angezeigt) 0 m
20 zu hohe Aufstiegsgeschwindigkeit 30 m/min
21 aGF-Warnung: die Berechnung der Dekompression wird �ber alternative GF-Werte durchgef�hrt
22 Fallback-Warnung bei ausgefallenem Sensor
23
24 @endverbatim
25 ******************************************************************************
26 * @attention
27 *
28 * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
29 *
30 ******************************************************************************
31 */
32
33 /* Includes ------------------------------------------------------------------*/
34
35 #include "data_exchange.h"
36 #include "check_warning.h"
37 #include "settings.h"
38 #include "decom.h"
39 #include "tCCR.h"
40
41 /* Private variables wit access ----------------------------------------------*/
42 uint8_t betterGasId = 0;
43 uint8_t betterSetpointId = 0;
44 int8_t fallback = 0;
45
46 /* Private function prototypes -----------------------------------------------*/
47 int8_t check_fallback(SDiveState * pDiveState);
48 int8_t check_ppO2(SDiveState * pDiveState);
49 int8_t check_O2_sensors(SDiveState * pDiveState);
50 int8_t check_CNS(SDiveState * pDiveState);
51 int8_t check_Deco(SDiveState * pDiveState);
52 int8_t check_AscentRate(SDiveState * pDiveState);
53 int8_t check_aGF(SDiveState * pDiveState);
54 int8_t check_BetterGas(SDiveState * pDiveState);
55 int8_t check_BetterSetpoint(SDiveState * pDiveState);
56 int8_t check_Battery(SDiveState * pDiveState);
57
58 int8_t check_helper_same_oxygen_and_helium_content(SGasLine * gas1, SGasLine * gas2);
59
60 /* Exported functions --------------------------------------------------------*/
61
62 void check_warning(void)
63 {
64 SDiveState * pDiveState;
65
66 if(stateUsed == stateRealGetPointer())
67 pDiveState = stateRealGetPointerWrite();
68 else
69 pDiveState = stateSimGetPointerWrite();
70
71 check_warning2(pDiveState);
72 }
73
74
75 void check_warning2(SDiveState * pDiveState)
76 {
77 pDiveState->warnings.numWarnings = 0;
78
79 pDiveState->warnings.numWarnings += check_aGF(pDiveState);
80 pDiveState->warnings.numWarnings += check_AscentRate(pDiveState);
81 pDiveState->warnings.numWarnings += check_CNS(pDiveState);
82 pDiveState->warnings.numWarnings += check_Deco(pDiveState);
83 pDiveState->warnings.numWarnings += check_ppO2(pDiveState);
84 pDiveState->warnings.numWarnings += check_O2_sensors(pDiveState);
85 pDiveState->warnings.numWarnings += check_BetterGas(pDiveState);
86 pDiveState->warnings.numWarnings += check_BetterSetpoint(pDiveState);
87 pDiveState->warnings.numWarnings += check_Battery(pDiveState);
88 pDiveState->warnings.numWarnings += check_fallback(pDiveState);
89 }
90
91
92 void set_warning_fallback(void)
93 {
94 fallback = 1;
95 }
96
97
98 void clear_warning_fallback(void)
99 {
100 fallback = 0;
101 }
102
103
104 uint8_t actualBetterGasId(void)
105 {
106 return betterGasId;
107 }
108
109
110 uint8_t actualBetterSetpointId(void)
111 {
112 return betterSetpointId;
113 }
114
115
116 uint8_t actualLeftMaxDepth(const SDiveState * pDiveState)
117 {
118 if(pDiveState->lifeData.depth_meter > (pDiveState->lifeData.max_depth_meter - 3.0f))
119 return 0;
120 else
121 return 1;
122 }
123
124
125 /* Private functions ---------------------------------------------------------*/
126 int8_t check_fallback(SDiveState * pDiveState)
127 {
128 if(fallback && ((pDiveState->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR)))
129 fallback = 0;
130
131 pDiveState->warnings.fallback = fallback;
132 return pDiveState->warnings.fallback;
133 }
134
135
136 int8_t check_ppO2(SDiveState * pDiveState)
137 {
138 if(pDiveState->mode != MODE_DIVE)
139 {
140 pDiveState->warnings.ppO2Low = 0;
141 pDiveState->warnings.ppO2High = 0;
142 return 0;
143 }
144
145 uint8_t localPPO2, testPPO2high;
146
147 if(pDiveState->lifeData.ppO2 < 0)
148 localPPO2 = 0;
149 else
150 if(pDiveState->lifeData.ppO2 >= 2.5f)
151 localPPO2 = 255;
152 else
153 localPPO2 = (uint8_t)(pDiveState->lifeData.ppO2 * 100);
154
155 if((localPPO2 + 1) <= settingsGetPointer()->ppO2_min)
156 pDiveState->warnings.ppO2Low = 1;
157 else
158 pDiveState->warnings.ppO2Low = 0;
159
160 if(actualLeftMaxDepth(pDiveState))
161 testPPO2high = settingsGetPointer()->ppO2_max_deco;
162 else
163 testPPO2high = settingsGetPointer()->ppO2_max_std;
164
165 if(localPPO2 >= (testPPO2high + 1))
166 pDiveState->warnings.ppO2High = 1;
167 else
168 pDiveState->warnings.ppO2High = 0;
169
170 return pDiveState->warnings.ppO2Low + pDiveState->warnings.ppO2High;
171 }
172
173
174 int8_t check_O2_sensors(SDiveState * pDiveState)
175 {
176 pDiveState->warnings.sensorLinkLost = 0;
177 pDiveState->warnings.sensorOutOfBounds[0] = 0;
178 pDiveState->warnings.sensorOutOfBounds[1] = 0;
179 pDiveState->warnings.sensorOutOfBounds[2] = 0;
180
181 if((pDiveState->diveSettings.diveMode == DIVEMODE_CCR) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors))
182 {
183 if(!get_HUD_battery_voltage_V())
184 pDiveState->warnings.sensorLinkLost = 1;
185
186 test_HUD_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]);
187
188 }
189 return pDiveState->warnings.sensorLinkLost
190 + pDiveState->warnings.sensorOutOfBounds[0]
191 + pDiveState->warnings.sensorOutOfBounds[1]
192 + pDiveState->warnings.sensorOutOfBounds[2];
193 }
194
195
196 int8_t check_BetterGas(SDiveState * pDiveState)
197 {
198 if(stateUsed->mode != MODE_DIVE)
199 {
200 pDiveState->warnings.betterGas = 0;
201 betterGasId = 0;
202 return 0;
203 }
204
205 uint8_t gasIdOffset;
206 uint8_t bestGasDepth, betterGasIdLocal;
207
208 SLifeData* pLifeData = &pDiveState->lifeData;
209 SDiveSettings* pDiveSettings = &pDiveState->diveSettings;
210
211 pDiveState->warnings.betterGas = 0;
212 betterGasId = 0;
213 betterGasIdLocal = pLifeData->actualGas.GasIdInSettings;
214 bestGasDepth = 255;
215
216 if(pDiveSettings->diveMode == DIVEMODE_CCR)
217 gasIdOffset = NUM_OFFSET_DILUENT;
218 else
219 gasIdOffset = 0;
220
221 /* life data is float, gas data is uint8 */
222 if(actualLeftMaxDepth(pDiveState)) /* deco gases */
223 {
224 for(int i=1+gasIdOffset; i<= 5+gasIdOffset; i++)
225 {
226 if( (pDiveSettings->gas[i].note.ub.active)
227 && (pDiveSettings->gas[i].note.ub.deco)
228 && (pDiveSettings->gas[i].depth_meter)
229 && (pDiveSettings->gas[i].depth_meter >= (pLifeData->depth_meter - 0.01f ))
230 && (pDiveSettings->gas[i].depth_meter <= bestGasDepth)
231 )
232 {
233 betterGasIdLocal = i;
234 bestGasDepth = pDiveSettings->gas[i].depth_meter;
235 }
236 }
237
238 if(betterGasIdLocal != pLifeData->actualGas.GasIdInSettings)
239 {
240 if(!check_helper_same_oxygen_and_helium_content(&pDiveSettings->gas[betterGasIdLocal], &pDiveSettings->gas[pLifeData->actualGas.GasIdInSettings]))
241 {
242 betterGasId = betterGasIdLocal;
243 pDiveState->warnings.betterGas = 1;
244 }
245 }
246 }
247 else /* travel gases */
248 {
249 bestGasDepth = 0;
250 //check for travalgas
251 for(int i=1+gasIdOffset; i<= 5+gasIdOffset; i++)
252 {
253 if( (pDiveSettings->gas[i].note.ub.active)
254 && (pDiveSettings->gas[i].note.ub.travel)
255 && (pDiveSettings->gas[i].depth_meter_travel)
256 && (pDiveSettings->gas[i].depth_meter_travel <= (pLifeData->depth_meter + 0.01f ))
257 && (pDiveSettings->gas[i].depth_meter_travel >= bestGasDepth)
258 )
259 {
260 betterGasIdLocal = i;
261 bestGasDepth = pDiveSettings->gas[i].depth_meter;
262 }
263 }
264
265 if(betterGasIdLocal != pLifeData->actualGas.GasIdInSettings)
266 {
267 if(!check_helper_same_oxygen_and_helium_content(&pDiveSettings->gas[betterGasIdLocal], &pDiveSettings->gas[pLifeData->actualGas.GasIdInSettings]))
268 {
269 betterGasId = betterGasIdLocal;
270 pDiveState->warnings.betterGas = 1;
271 }
272 }
273 }
274 return pDiveState->warnings.betterGas;
275 }
276
277 /* check for better travel!!! setpoint hw 151210
278 */
279 int8_t check_BetterSetpoint(SDiveState * pDiveState)
280 {
281 pDiveState->warnings.betterSetpoint = 0;
282 betterSetpointId = 0;
283
284 if((stateUsed->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR) || (pDiveState->diveSettings.CCR_Mode != CCRMODE_FixedSetpoint))
285 {
286 return 0;
287 }
288
289 uint8_t bestSetpointDepth = 0; // travel the deeper, the better
290 uint8_t betterSetpointIdLocal = 0; // nothing better
291
292 if(!actualLeftMaxDepth(pDiveState)) /* travel gases */
293 {
294 for(int i=1; i<=NUM_GASES; i++)
295 {
296 if( (pDiveState->diveSettings.setpoint[i].note.ub.active)
297 && (pDiveState->diveSettings.setpoint[i].depth_meter)
298 && (pDiveState->diveSettings.setpoint[i].depth_meter <= ( pDiveState->lifeData.depth_meter + 0.01f ))
299 && (pDiveState->diveSettings.setpoint[i].depth_meter >= bestSetpointDepth)
300 )
301 {
302 betterSetpointIdLocal = i;
303 bestSetpointDepth = pDiveState->diveSettings.setpoint[i].depth_meter;
304 }
305 }
306 if((betterSetpointIdLocal) && (pDiveState->diveSettings.setpoint[betterSetpointIdLocal].setpoint_cbar != pDiveState->lifeData.actualGas.setPoint_cbar))
307 {
308 betterSetpointId = betterSetpointIdLocal;
309 pDiveState->warnings.betterSetpoint = 1;
310 }
311 }
312 return pDiveState->warnings.betterSetpoint;
313 }
314
315
316 /* hw 151030
317 */
318 int8_t check_helper_same_oxygen_and_helium_content(SGasLine * gas1, SGasLine * gas2)
319 {
320 if(gas1->helium_percentage != gas2->helium_percentage)
321 return 0;
322 else
323 if(gas1->oxygen_percentage != gas2->oxygen_percentage)
324 return 0;
325 else
326 return 1;
327 }
328
329
330 int8_t check_CNS(SDiveState * pDiveState)
331 {
332 if(stateUsed->mode != MODE_DIVE)
333 {
334 pDiveState->warnings.cnsHigh = 0;
335 return 0;
336 }
337
338 if(pDiveState->lifeData.cns >= (float)(settingsGetPointer()->CNS_max))
339 pDiveState->warnings.cnsHigh = 1;
340 else
341 pDiveState->warnings.cnsHigh = 0;
342 return pDiveState->warnings.cnsHigh;
343 }
344
345
346 int8_t check_Battery(SDiveState * pDiveState)
347 {
348 if(pDiveState->lifeData.battery_charge < 10)
349 pDiveState->warnings.lowBattery = 1;
350 else
351 pDiveState->warnings.lowBattery = 0;
352
353 return pDiveState->warnings.lowBattery;
354 }
355
356
357 int8_t check_Deco(SDiveState * pDiveState)
358 {
359 if(stateUsed->mode != MODE_DIVE)
360 {
361 pDiveState->warnings.decoMissed = 0;
362 return 0;
363 }
364
365 uint8_t depthNext = decom_get_actual_deco_stop(pDiveState);
366
367 if(!depthNext)
368 pDiveState->warnings.decoMissed = 0;
369 else
370 if(pDiveState->lifeData.depth_meter + 0.1f < (float)depthNext)
371 pDiveState->warnings.decoMissed = 1;
372 else
373 pDiveState->warnings.decoMissed = 0;
374
375 return pDiveState->warnings.decoMissed;
376 }
377
378
379 int8_t check_AscentRate(SDiveState * pDiveState)
380 {
381 if(stateUsed->mode != MODE_DIVE)
382 {
383 pDiveState->warnings.ascentRateHigh = 0;
384 return 0;
385 }
386
387 float warnAscentRateFloat;
388
389 warnAscentRateFloat = (float)(settingsGetPointer()->ascent_MeterPerMinute_max);
390
391 if(pDiveState->lifeData.ascent_rate_meter_per_min >= warnAscentRateFloat)
392 pDiveState->warnings.ascentRateHigh = 1;
393 else
394 pDiveState->warnings.ascentRateHigh = 0;
395 return pDiveState->warnings.ascentRateHigh;
396 }
397
398
399 int8_t check_aGF(SDiveState * pDiveState)
400 {
401 if(stateUsed->mode != MODE_DIVE)
402 {
403 pDiveState->warnings.aGf = 0;
404 return 0;
405 }
406
407 pDiveState->warnings.aGf = 0;
408 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE)
409 {
410 if((pDiveState->diveSettings.gf_high != settingsGetPointer()->GF_high) || (pDiveState->diveSettings.gf_low != settingsGetPointer()->GF_low))
411 pDiveState->warnings.aGf = 1;
412 }
413 return pDiveState->warnings.aGf;
414 }
415
416 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
417