38
+ − 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>© 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