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;