Mercurial > public > ostc4
comparison Discovery/Src/check_warning.c @ 981:c6c781a2e85b default
Merge into default
| author | heinrichsweikamp |
|---|---|
| date | Tue, 11 Feb 2025 18:12:00 +0100 |
| parents | 33e24b77cc6c |
| children | 8507a87f6401 |
comparison
equal
deleted
inserted
replaced
| 871:f7318457df4d | 981:c6c781a2e85b |
|---|---|
| 41 #include "tCCR.h" | 41 #include "tCCR.h" |
| 42 #include "tHome.h" | 42 #include "tHome.h" |
| 43 | 43 |
| 44 | 44 |
| 45 #define DEBOUNCE_FALLBACK_TIME_MS (5000u) /* set warning after 5 seconds of pending error condition */ | 45 #define DEBOUNCE_FALLBACK_TIME_MS (5000u) /* set warning after 5 seconds of pending error condition */ |
| 46 #define GUI_BUZZER_TIMEOUT_MS (200u) /* the buzzer should be active while Warning string is shown, but diver may be in a menu... */ | |
| 46 | 47 |
| 47 #define SETPOINT_DECO_START_RANGE_M 3.0 | 48 #define SETPOINT_DECO_START_RANGE_M 3.0 |
| 48 #define SWITCH_DEPTH_LOW_MINIMUM_M 1.0 | 49 #define SWITCH_DEPTH_LOW_MINIMUM_M 1.0 |
| 49 | 50 |
| 50 /* Private variables with access ----------------------------------------------*/ | 51 /* Private variables with access ----------------------------------------------*/ |
| 51 static uint8_t betterGasId = 0; | 52 static uint8_t betterGasId = 0; |
| 52 static uint8_t betterBailoutGasId = 0; | 53 static uint8_t betterBailoutGasId = 0; |
| 53 static uint8_t betterSetpointId = 1; | 54 static uint8_t betterSetpointId = 1; |
| 54 static int8_t fallback = 0; | 55 static int8_t fallback = 0; |
| 55 static uint16_t debounceFallbackTimeMS = 0; | 56 static uint16_t debounceFallbackTimeMS = 0; |
| 57 static uint8_t buzzerRequestActive = 0; | |
| 56 | 58 |
| 57 /* Private function prototypes -----------------------------------------------*/ | 59 /* Private function prototypes -----------------------------------------------*/ |
| 58 static int8_t check_fallback(SDiveState * pDiveState); | 60 static int8_t check_fallback(SDiveState * pDiveState); |
| 59 static int8_t check_ppO2(SDiveState * pDiveState); | 61 static int8_t check_ppO2(SDiveState * pDiveState); |
| 60 static int8_t check_O2_sensors(SDiveState * pDiveState); | 62 static int8_t check_O2_sensors(SDiveState * pDiveState); |
| 70 #endif | 72 #endif |
| 71 #ifdef ENABLE_CO2_SUPPORT | 73 #ifdef ENABLE_CO2_SUPPORT |
| 72 static int8_t check_co2(SDiveState * pDiveState); | 74 static int8_t check_co2(SDiveState * pDiveState); |
| 73 #endif | 75 #endif |
| 74 static int8_t check_helper_same_oxygen_and_helium_content(SGasLine * gas1, SGasLine * gas2); | 76 static int8_t check_helper_same_oxygen_and_helium_content(SGasLine * gas1, SGasLine * gas2); |
| 75 | 77 #ifdef HAVE_DEBUG_WARNINGS |
| 78 static int8_t check_debug(SDiveState * pDiveState); | |
| 79 #endif | |
| 80 static uint8_t buzzerOn = 0; /* current state of the buzzer */ | |
| 81 | |
| 82 static void setBuzzer(int8_t warningActive); | |
| 76 /* Exported functions --------------------------------------------------------*/ | 83 /* Exported functions --------------------------------------------------------*/ |
| 77 | 84 |
| 85 void requestBuzzerActivation(uint8_t active) | |
| 86 { | |
| 87 buzzerRequestActive = active; | |
| 88 } | |
| 89 | |
| 90 uint8_t getBuzzerActivationState() | |
| 91 { | |
| 92 return buzzerOn; | |
| 93 } | |
| 94 | |
| 95 static void setBuzzer(int8_t warningActive) | |
| 96 { | |
| 97 static uint32_t guiTimeoutCnt = 0; /* max delay till buzzer will be activated independend from gui request */ | |
| 98 static uint32_t stateTick = 0; /* activation tick of current state */ | |
| 99 static uint8_t lastWarningState = 0; /* the parameter value of the last call*/ | |
| 100 | |
| 101 uint32_t tick = HAL_GetTick(); | |
| 102 | |
| 103 if(warningActive) | |
| 104 { | |
| 105 if(!lastWarningState) /* init structures */ | |
| 106 { | |
| 107 guiTimeoutCnt = tick; | |
| 108 stateTick = tick; | |
| 109 } | |
| 110 if(buzzerOn) | |
| 111 { | |
| 112 if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS) /* buzzer has to be on for a certain time */ | |
| 113 { | |
| 114 if((!buzzerRequestActive) || (time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS)) | |
| 115 { | |
| 116 buzzerOn = 0; | |
| 117 stateTick = tick; | |
| 118 guiTimeoutCnt = tick; | |
| 119 } | |
| 120 } | |
| 121 } | |
| 122 else | |
| 123 { | |
| 124 if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS) /* buzzer has to be off for a certain time */ | |
| 125 { | |
| 126 if((buzzerRequestActive) || (time_elapsed_ms(guiTimeoutCnt, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS + GUI_BUZZER_TIMEOUT_MS)) | |
| 127 { | |
| 128 buzzerOn = 1; | |
| 129 stateTick = tick; | |
| 130 } | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 else | |
| 135 { | |
| 136 buzzerOn = 0; | |
| 137 } | |
| 138 lastWarningState = warningActive; | |
| 139 } | |
| 140 | |
| 78 void check_warning(void) | 141 void check_warning(void) |
| 79 { | 142 { |
| 80 check_warning2(stateUsedWrite); | 143 check_warning2(stateUsedWrite); |
| 81 } | 144 } |
| 82 | 145 |
| 83 | 146 |
| 84 void check_warning2(SDiveState * pDiveState) | 147 void check_warning2(SDiveState * pDiveState) |
| 85 { | 148 { |
| 86 pDiveState->warnings.numWarnings = 0; | 149 pDiveState->warnings.numWarnings = 0; |
| 87 | 150 |
| 88 pDiveState->warnings.numWarnings += check_aGF(pDiveState); | 151 /* Warnings checked before the SetBuzzer call will activate the buzzer */ |
| 89 pDiveState->warnings.numWarnings += check_AscentRate(pDiveState); | 152 pDiveState->warnings.numWarnings += check_AscentRate(pDiveState); |
| 90 pDiveState->warnings.numWarnings += check_CNS(pDiveState); | |
| 91 pDiveState->warnings.numWarnings += check_Deco(pDiveState); | 153 pDiveState->warnings.numWarnings += check_Deco(pDiveState); |
| 92 pDiveState->warnings.numWarnings += check_ppO2(pDiveState); | 154 pDiveState->warnings.numWarnings += check_ppO2(pDiveState); |
| 93 pDiveState->warnings.numWarnings += check_O2_sensors(pDiveState); | 155 pDiveState->warnings.numWarnings += check_O2_sensors(pDiveState); |
| 156 pDiveState->warnings.numWarnings += check_fallback(pDiveState); | |
| 157 #ifdef ENABLE_CO2_SUPPORT | |
| 158 pDiveState->warnings.numWarnings += check_co2(pDiveState); | |
| 159 #endif | |
| 160 | |
| 161 if(settingsGetPointer()->warningBuzzer) | |
| 162 { | |
| 163 setBuzzer(pDiveState->warnings.numWarnings); | |
| 164 } | |
| 165 | |
| 166 /* Warnings checked after this line will not cause activation of the buzzer */ | |
| 167 pDiveState->warnings.numWarnings += check_aGF(pDiveState); | |
| 168 pDiveState->warnings.numWarnings += check_CNS(pDiveState); | |
| 94 pDiveState->warnings.numWarnings += check_BetterGas(pDiveState); | 169 pDiveState->warnings.numWarnings += check_BetterGas(pDiveState); |
| 95 pDiveState->warnings.numWarnings += check_BetterSetpoint(pDiveState); | 170 pDiveState->warnings.numWarnings += check_BetterSetpoint(pDiveState); |
| 96 pDiveState->warnings.numWarnings += check_Battery(pDiveState); | 171 pDiveState->warnings.numWarnings += check_Battery(pDiveState); |
| 97 pDiveState->warnings.numWarnings += check_fallback(pDiveState); | |
| 98 #ifdef ENABLE_BOTTLE_SENSOR | 172 #ifdef ENABLE_BOTTLE_SENSOR |
| 99 pDiveState->warnings.numWarnings += check_pressureSensor(pDiveState); | 173 pDiveState->warnings.numWarnings += check_pressureSensor(pDiveState); |
| 100 #endif | 174 #endif |
| 101 #ifdef ENABLE_CO2_SUPPORT | 175 |
| 102 pDiveState->warnings.numWarnings += check_co2(pDiveState); | 176 #ifdef HAVE_DEBUG_WARNINGS |
| 177 pDiveState->warnings.numWarnings += check_debug(pDiveState); | |
| 103 #endif | 178 #endif |
| 104 } | 179 } |
| 105 | 180 |
| 106 | 181 |
| 107 void set_warning_fallback(void) | 182 void set_warning_fallback(void) |
| 155 } | 230 } |
| 156 | 231 |
| 157 | 232 |
| 158 static int8_t check_ppO2(SDiveState * pDiveState) | 233 static int8_t check_ppO2(SDiveState * pDiveState) |
| 159 { | 234 { |
| 160 if((pDiveState->mode != MODE_DIVE) || (pDiveState->warnings.fallback)) | 235 if((pDiveState->mode != MODE_DIVE) || ((isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->warnings.fallback)))) |
| 161 { | 236 { |
| 162 pDiveState->warnings.ppO2Low = 0; | 237 pDiveState->warnings.ppO2Low = 0; |
| 163 pDiveState->warnings.ppO2High = 0; | 238 pDiveState->warnings.ppO2High = 0; |
| 164 return 0; | 239 return 0; |
| 165 } | 240 } |
| 199 pDiveState->warnings.sensorOutOfBounds[0] = 0; | 274 pDiveState->warnings.sensorOutOfBounds[0] = 0; |
| 200 pDiveState->warnings.sensorOutOfBounds[1] = 0; | 275 pDiveState->warnings.sensorOutOfBounds[1] = 0; |
| 201 pDiveState->warnings.sensorOutOfBounds[2] = 0; | 276 pDiveState->warnings.sensorOutOfBounds[2] = 0; |
| 202 | 277 |
| 203 if(isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors)) | 278 if(isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors)) |
| 204 | 279 { |
| 205 if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_OPTIC) | 280 if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_OPTIC) |
| 206 { | 281 { |
| 207 { | 282 { |
| 208 if(!get_HUD_battery_voltage_V()) | 283 if(!get_HUD_battery_voltage_V()) |
| 209 pDiveState->warnings.sensorLinkLost = 1; | 284 pDiveState->warnings.sensorLinkLost = 1; |
| 210 } | 285 } |
| 211 } | 286 } |
| 212 test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]); | 287 test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]); |
| 288 } | |
| 213 return pDiveState->warnings.sensorLinkLost | 289 return pDiveState->warnings.sensorLinkLost |
| 214 + pDiveState->warnings.sensorOutOfBounds[0] | 290 + pDiveState->warnings.sensorOutOfBounds[0] |
| 215 + pDiveState->warnings.sensorOutOfBounds[1] | 291 + pDiveState->warnings.sensorOutOfBounds[1] |
| 216 + pDiveState->warnings.sensorOutOfBounds[2]; | 292 + pDiveState->warnings.sensorOutOfBounds[2]; |
| 217 } | 293 } |
| 218 | 294 |
| 219 | 295 |
| 220 static uint8_t getBetterGasId(bool getDiluent, uint8_t startingGasId, SDiveState *diveState) | 296 static uint8_t getBetterGasId(bool getDiluent, uint8_t startingGasId, SDiveState *diveState) |
| 221 { | 297 { |
| 222 SDiveSettings diveSettings = diveState->diveSettings; | 298 SDiveSettings diveSettings = diveState->diveSettings; |
| 223 | 299 SGasLine localGas; |
| 224 uint8_t betterGasIdLocal = startingGasId; | 300 uint8_t betterGasIdLocal = startingGasId; |
| 225 uint8_t bestGasDepth = 255; | 301 uint8_t bestGasDepth = 255; |
| 302 uint8_t i; | |
| 226 | 303 |
| 227 uint8_t gasIdOffset; | 304 uint8_t gasIdOffset; |
| 228 if (getDiluent) { | 305 if (getDiluent) { |
| 229 gasIdOffset = NUM_OFFSET_DILUENT; | 306 gasIdOffset = NUM_OFFSET_DILUENT; |
| 230 } else { | 307 } else { |
| 231 gasIdOffset = 0; | 308 gasIdOffset = 0; |
| 232 } | 309 } |
| 233 | 310 |
| 234 if (betterGasIdLocal == NO_GAS_ID) { | |
| 235 for (unsigned i = gasIdOffset + 1; i <= gasIdOffset + 5; i++) { | |
| 236 if (diveSettings.gas[i].note.ub.active && diveSettings.gas[i].note.ub.first) { | |
| 237 betterGasIdLocal = i; | |
| 238 } | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 /* life data is float, gas data is uint8 */ | 311 /* life data is float, gas data is uint8 */ |
| 243 if (actualLeftMaxDepth(diveState)) { /* deco gases */ | 312 if (actualLeftMaxDepth(diveState)) { /* deco gases */ |
| 244 for (int i=1+gasIdOffset; i<= 5+gasIdOffset; i++) { | 313 for (i=1+gasIdOffset; i<= 5+gasIdOffset; i++) { |
| 245 if ((diveSettings.gas[i].note.ub.active) | 314 memcpy(&localGas,&diveSettings.gas[i],sizeof(SGasLine)); |
| 246 && (diveSettings.gas[i].note.ub.deco) | 315 if((localGas.note.ub.first) && (diveSettings.diveMode == DIVEMODE_PSCR)) /* handle first gas as if it would be a deco gas set to MOD */ |
| 247 && (diveSettings.gas[i].depth_meter) | 316 { |
| 248 && (diveSettings.gas[i].depth_meter >= (diveState->lifeData.depth_meter - 0.01f )) | 317 localGas.note.ub.active = 1; |
| 249 && (diveSettings.gas[i].depth_meter <= bestGasDepth)) { | 318 localGas.note.ub.deco = 1; |
| 319 localGas.depth_meter = calc_MOD(i); | |
| 320 } | |
| 321 if ((localGas.note.ub.active) | |
| 322 && (localGas.note.ub.deco) | |
| 323 && (localGas.depth_meter) | |
| 324 && (localGas.depth_meter >= (diveState->lifeData.depth_meter - 0.9f )) | |
| 325 && (localGas.depth_meter <= bestGasDepth)) { | |
| 250 betterGasIdLocal = i; | 326 betterGasIdLocal = i; |
| 251 bestGasDepth = diveSettings.gas[i].depth_meter; | 327 bestGasDepth = diveSettings.gas[i].depth_meter; |
| 252 } | 328 } |
| 253 } | 329 } |
| 254 } else { /* travel gases */ | 330 } else { /* travel gases */ |
| 255 bestGasDepth = 0; | 331 bestGasDepth = 0; |
| 256 //check for travelgas | 332 //check for travalgas |
| 257 for (int i = 1 + gasIdOffset; i <= 5 + gasIdOffset; i++) { | 333 for (i = 1 + gasIdOffset; i <= 5 + gasIdOffset; i++) { |
| 258 if ((diveSettings.gas[i].note.ub.active) | 334 if ((diveSettings.gas[i].note.ub.active) |
| 259 && (diveSettings.gas[i].note.ub.travel) | 335 && (diveSettings.gas[i].note.ub.travel) |
| 260 && (diveSettings.gas[i].depth_meter_travel) | 336 && (diveSettings.gas[i].depth_meter_travel) |
| 261 && (diveSettings.gas[i].depth_meter_travel <= (diveState->lifeData.depth_meter + 0.01f )) | 337 && (diveSettings.gas[i].depth_meter_travel <= (diveState->lifeData.depth_meter + 0.01f )) |
| 262 && (diveSettings.gas[i].depth_meter_travel >= bestGasDepth)) { | 338 && (diveSettings.gas[i].depth_meter_travel >= bestGasDepth)) { |
| 263 betterGasIdLocal = i; | 339 betterGasIdLocal = i; |
| 264 bestGasDepth = diveSettings.gas[i].depth_meter; | 340 bestGasDepth = diveSettings.gas[i].depth_meter; |
| 265 } | 341 } |
| 266 } | 342 } |
| 267 } | 343 } |
| 344 if((!getDiluent) && (betterGasIdLocal > NUM_OFFSET_DILUENT)) /* an OC gas was requested but Id is pointing to a diluent => return first OC */ | |
| 345 { | |
| 346 for (i = 1 ; i <= NUM_OFFSET_DILUENT; i++) | |
| 347 { | |
| 348 if(diveSettings.gas[i].note.ub.first) | |
| 349 { | |
| 350 betterGasIdLocal = i; | |
| 351 break; | |
| 352 } | |
| 353 } | |
| 354 } | |
| 355 | |
| 268 | 356 |
| 269 return betterGasIdLocal; | 357 return betterGasIdLocal; |
| 270 } | 358 } |
| 271 | 359 |
| 272 | 360 |
| 283 SDiveSettings diveSettings = diveState->diveSettings; | 371 SDiveSettings diveSettings = diveState->diveSettings; |
| 284 SLifeData lifeData = diveState->lifeData; | 372 SLifeData lifeData = diveState->lifeData; |
| 285 | 373 |
| 286 if (isLoopMode(diveSettings.diveMode)) { | 374 if (isLoopMode(diveSettings.diveMode)) { |
| 287 betterGasId = getBetterGasId(true, lifeData.actualGas.GasIdInSettings, diveState); | 375 betterGasId = getBetterGasId(true, lifeData.actualGas.GasIdInSettings, diveState); |
| 288 betterBailoutGasId = getBetterGasId(false, NO_GAS_ID, diveState); | 376 betterBailoutGasId = getBetterGasId(false, lifeData.lastDiluent_GasIdInSettings, diveState); |
| 289 } else { | 377 } else { |
| 290 betterGasId = getBetterGasId(false, lifeData.actualGas.GasIdInSettings, diveState); | 378 betterGasId = getBetterGasId(false, lifeData.actualGas.GasIdInSettings, diveState); |
| 291 } | 379 } |
| 292 | 380 |
| 293 if (betterGasId != lifeData.actualGas.GasIdInSettings && !check_helper_same_oxygen_and_helium_content(&diveSettings.gas[betterGasId], &diveSettings.gas[lifeData.actualGas.GasIdInSettings])) { | 381 if (betterGasId != lifeData.actualGas.GasIdInSettings && !check_helper_same_oxygen_and_helium_content(&diveSettings.gas[betterGasId], &diveSettings.gas[lifeData.actualGas.GasIdInSettings])) { |
| 564 #endif | 652 #endif |
| 565 | 653 |
| 566 #ifdef ENABLE_CO2_SUPPORT | 654 #ifdef ENABLE_CO2_SUPPORT |
| 567 static int8_t check_co2(SDiveState * pDiveState) | 655 static int8_t check_co2(SDiveState * pDiveState) |
| 568 { | 656 { |
| 569 if(pDiveState->mode != MODE_DIVE) | 657 if((pDiveState->mode != MODE_DIVE) || (settingsGetPointer()->co2_sensor_active == 0)) |
| 570 { | 658 { |
| 571 pDiveState->warnings.co2High = 0; | 659 pDiveState->warnings.co2High = 0; |
| 572 } | 660 } |
| 573 else | 661 else |
| 574 { | 662 { |
| 583 } | 671 } |
| 584 return pDiveState->warnings.co2High; | 672 return pDiveState->warnings.co2High; |
| 585 } | 673 } |
| 586 #endif | 674 #endif |
| 587 | 675 |
| 676 #ifdef HAVE_DEBUG_WARNINGS | |
| 677 static int8_t check_debug(SDiveState * pDiveState) | |
| 678 { | |
| 679 uint8_t index = 0; | |
| 680 | |
| 681 pDiveState->warnings.debug = 0; | |
| 682 | |
| 683 if((settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_DIGITAL) || (settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_ANADIG)) | |
| 684 { | |
| 685 for(index=0; index<3; index++) | |
| 686 { | |
| 687 if(((pDiveState->lifeData.extIf_sensor_map[index] == SENSOR_DIGO2M) && (((SSensorDataDiveO2*)(stateUsed->lifeData.extIf_sensor_data[index]))->status & DVO2_FATAL_ERROR))) | |
| 688 { | |
| 689 pDiveState->warnings.debug = 1; | |
| 690 } | |
| 691 } | |
| 692 } | |
| 693 return pDiveState->warnings.debug; | |
| 694 } | |
| 695 #endif | |
| 696 | |
| 588 uint8_t debounce_warning_fallback(uint16_t debounceStepms) | 697 uint8_t debounce_warning_fallback(uint16_t debounceStepms) |
| 589 { | 698 { |
| 590 uint8_t retVal = 0; | 699 uint8_t retVal = 0; |
| 591 | 700 |
| 592 debounceFallbackTimeMS += debounceStepms; | 701 debounceFallbackTimeMS += debounceStepms; |
