software:firmware
MakAir Firmware
alarm_controller.cpp
Go to the documentation of this file.
1 
8 #pragma once
9 
10 // INCLUDES ===================================================================
11 
12 // Externals
13 
14 // Internals
15 #include "../includes/alarm_controller.h"
16 #include "../includes/buzzer.h"
17 #include "../includes/cycle.h"
18 #include "../includes/screen.h"
19 #include "../includes/telemetry.h"
20 
21 // INITIALISATION =============================================================
22 
24 
25 // FUNCTIONS ==================================================================
26 
28  : m_highestPriority(AlarmPriority::ALARM_NONE),
29  m_snoozeTime(0u),
30  m_alarms({
31 
38 
39  /* RCM-SW-1
40  * The device shall embed a high priority alarm 12 when the plateau pressure is not
41  * reached (absolute difference > 20% in absolute value) from the 3th respiratory cycle.
42  */
44 
51 
58 
65 
72 
79 
86 
93 
100 
106 
112 
119 
127 
134 
141 
148 
154 
160 
166 
172  }),
173 
174  m_tick(0u),
175  m_unsnooze(true),
176  m_pressure(0u),
177  m_phase(CyclePhases::INHALATION),
178  // cppcheck-suppress misra-c2012-5.2 ; false positive
179  m_cycle_number(0u) {
180  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
181  m_snoozedAlarms[i] = false;
182  }
183  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
184  m_triggeredAlarms[i] = 0u;
185  }
186 }
187 
189  if (m_unsnooze) {
190  m_unsnooze = false;
191  digitalWrite(PIN_LED_GREEN, LED_GREEN_ACTIVE);
192  m_snoozeTime = millis();
193  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
194  Alarm* current = &m_alarms[i];
195  if (current->isTriggered()) {
196  m_snoozedAlarms[i] = true;
197  } else {
198  m_snoozedAlarms[i] = false;
199  }
200  }
201 
202  Buzzer_Mute();
203  }
205 }
206 
207 void AlarmController::detectedAlarm(uint8_t p_alarmCode,
208  uint32_t p_cycleNumber,
209  uint32_t p_expected,
210  uint32_t p_measured) {
211  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
212  Alarm* current = &m_alarms[i];
213  bool wasTriggered = current->isTriggered();
214  if (current->isEnabled() && (current->getCode() == p_alarmCode)) {
215  current->detected(p_cycleNumber);
216 
217  if (current->isTriggered()) {
218  for (uint8_t j = 0; j < ALARMS_SIZE; j++) {
219  if (m_triggeredAlarms[j] == p_alarmCode) {
220  break;
221  }
222  if (m_triggeredAlarms[j] == 0u) {
223  m_triggeredAlarms[j] = p_alarmCode;
224  break;
225  }
226  }
227 
228  if (!wasTriggered) {
230  current->getPriority(), true, p_expected, p_measured,
231  current->getCyclesSinceTrigger());
232  }
233  }
234  break;
235  }
236  }
237 }
238 
239 bool compare(uint8_t a, uint8_t b) { return a > b; }
240 
241 void AlarmController::notDetectedAlarm(uint8_t p_alarmCode) {
242  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
243  Alarm* current = &m_alarms[i];
244  bool wasTriggered = current->isTriggered();
245  if (current->getCode() == p_alarmCode) {
246  current->notDetected();
247 
248  if (!current->isTriggered()) {
249  for (uint8_t j = 0; j < ALARMS_SIZE; j++) {
250  if (m_triggeredAlarms[j] == p_alarmCode) {
251  m_triggeredAlarms[j] = 0u;
253  break;
254  }
255  }
256 
257  if (wasTriggered) {
259  current->getPriority(), false, 0u, 0u,
260  current->getCyclesSinceTrigger());
261  }
262  }
263  break;
264  }
265  }
266 }
267 
268 void AlarmController::runAlarmEffects(uint32_t p_tick) {
269  AlarmPriority highestPriority = AlarmPriority::ALARM_NONE;
270  uint8_t triggeredAlarmCodes[ALARMS_SIZE];
271  uint8_t numberOfTriggeredAlarms = 0;
272  bool justUnsnoozed = false;
273 
274  //
275  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
276  Alarm* current = &m_alarms[i];
277  if (current->isTriggered()) {
278  if (numberOfTriggeredAlarms == 0u) {
279  highestPriority = current->getPriority();
280  }
281 
282  triggeredAlarmCodes[numberOfTriggeredAlarms] = current->getCode();
283  numberOfTriggeredAlarms++;
284 
285  if (!m_unsnooze && !m_snoozedAlarms[i]) {
286  unsnooze();
287  justUnsnoozed = true;
288  }
289  } else {
290  m_snoozedAlarms[i] = false;
291  }
292  }
293 
294  uint32_t millisSinceSnooze = millis() - m_snoozeTime;
295  if (!m_unsnooze && (m_snoozeTime > 0u) && (millisSinceSnooze >= 120000u)) {
296  unsnooze();
297  }
298 
300  displayAlarmInformation(triggeredAlarmCodes, numberOfTriggeredAlarms);
301  }
302 
303  if (highestPriority == AlarmPriority::ALARM_HIGH) {
304  if ((m_highestPriority != highestPriority) || justUnsnoozed) {
305  if (m_unsnooze) {
307  }
308  }
309 
310  if ((p_tick % 100u) == 50u) {
311  digitalWrite(PIN_LED_RED, LED_RED_ACTIVE);
312  } else if ((p_tick % 100u) == 0u) {
313  digitalWrite(PIN_LED_RED, LED_RED_INACTIVE);
314  } else {
315  }
316  digitalWrite(PIN_LED_YELLOW, LED_YELLOW_INACTIVE);
317  } else if (highestPriority == AlarmPriority::ALARM_MEDIUM) {
318  if ((m_highestPriority != highestPriority) || justUnsnoozed) {
319  if (m_unsnooze) {
321  }
322  }
323  digitalWrite(PIN_LED_RED, LED_RED_INACTIVE);
324  if ((p_tick % 100u) == 50u) {
325  digitalWrite(PIN_LED_YELLOW, LED_YELLOW_ACTIVE);
326  } else if ((p_tick % 100u) == 0u) {
327  digitalWrite(PIN_LED_YELLOW, LED_YELLOW_INACTIVE);
328  } else {
329  }
330  } else if (highestPriority == AlarmPriority::ALARM_LOW) {
331  if ((m_highestPriority != highestPriority) || justUnsnoozed) {
332  if (m_unsnooze) {
334  }
335  }
336 
337  digitalWrite(PIN_LED_RED, LED_RED_INACTIVE);
338  digitalWrite(PIN_LED_YELLOW, LED_YELLOW_ACTIVE);
339  } else {
340  Buzzer_Stop();
341 
342  digitalWrite(PIN_LED_RED, LED_RED_INACTIVE);
343  digitalWrite(PIN_LED_YELLOW, LED_YELLOW_INACTIVE);
344  }
345 
346  m_highestPriority = highestPriority;
347 }
348 
349 // cppcheck-suppress unusedFunction
351  digitalWrite(PIN_LED_GREEN, LED_GREEN_INACTIVE);
352  m_snoozeTime = 0u;
353  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
354  m_snoozedAlarms[i] = false;
355  }
356  m_unsnooze = true;
358 }
359 
360 // cppcheck-suppress unusedFunction
361 void AlarmController::updateCoreData(uint32_t p_tick,
362  uint16_t p_pressure,
363  CyclePhases p_phase,
364  uint32_t p_cycle_number) {
365  m_tick = p_tick;
366  m_pressure = p_pressure;
367  m_phase = p_phase;
368  m_cycle_number = p_cycle_number;
369 }
370 
372  // Untrigger every alarms
373  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
374  m_triggeredAlarms[i] = 0u;
375  }
376 
377  // First Disable every alarms
378  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
379  m_alarms[i].disable();
380  }
381 
382  // Then Enable provided alarms
383  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
384  if (enabledAlarms.alarms[i] != 0u) {
385  for (uint8_t j = 0; j < ALARMS_SIZE; j++) {
386  if (m_alarms[j].getCode() == enabledAlarms.alarms[i]) {
387  m_alarms[j].enable();
388  break;
389  }
390  }
391  }
392  }
393 }
AlarmPriority
Priority levels of an alarm.
Definition: alarm.h:18
@ ALARM_NONE
Definition: alarm.h:18
@ ALARM_HIGH
Definition: alarm.h:18
@ ALARM_LOW
Definition: alarm.h:18
@ ALARM_MEDIUM
Definition: alarm.h:18
AlarmController alarmController
Instance of the alarm controller.
bool compare(uint8_t a, uint8_t b)
#define RCM_SW_11
#define RCM_SW_20
#define RCM_SW_12
#define RCM_SW_15
#define RCM_SW_3
#define RCM_SW_5
#define RCM_SW_18
#define RCM_SW_23
#define RCM_SW_19
#define RCM_SW_6
#define RCM_SW_16
#define RCM_SW_1
#define RCM_SW_9
#define RCM_SW_14
#define RCM_SW_8
#define RCM_SW_4
#define RCM_SW_21
#define ALARMS_SIZE
#define RCM_SW_2
#define RCM_SW_22
#define RCM_SW_10
#define RCM_SW_7
void Buzzer_High_Prio_Start(void)
Activate the buzzer pattern for high priority alarms.
Definition: buzzer.cpp:186
void Buzzer_Low_Prio_Start(void)
Activate the buzzer pattern for low priority alarms.
Definition: buzzer.cpp:192
void Buzzer_Mute()
Mute the buzzer for 120s.
Definition: buzzer.cpp:156
void Buzzer_Stop(void)
Stop Buzzer.
Definition: buzzer.cpp:196
void Buzzer_Medium_Prio_Start(void)
Activate the buzzer pattern for medium priority alarms.
Definition: buzzer.cpp:188
Manage alarm features.
bool m_snoozedAlarms[ALARMS_SIZE]
Collections of snoozed alarms.
void updateCoreData(uint32_t p_tick, uint16_t p_pressure, CyclePhases p_phase, uint32_t p_cycle_number)
Update internal state of alarm controller with data from pressure controller.
AlarmController()
Default constructor.
uint32_t m_cycle_number
Current cycle number.
void detectedAlarm(uint8_t p_alarmCode, uint32_t p_cycleNumber, uint32_t p_expected, uint32_t p_measured)
Mark a specific alarm as detected.
uint32_t m_snoozeTime
Time when snoozed was triggered.
bool m_unsnooze
Is unsnoozed right now.
uint16_t m_tick
Current pressure.
void snooze()
Snooze alarm for 2 minutes.
Alarm m_alarms[ALARMS_SIZE]
Collections of available alarms.
CyclePhases m_phase
Current phase.
void updateEnabledAlarms(Alarms enabledAlarms)
Update the list of enabled alarms (alarms not provided here will have no effects)
void unsnooze()
Unsnooze alarms.
uint8_t m_triggeredAlarms[ALARMS_SIZE]
Alarms currently triggered.
void runAlarmEffects(uint32_t p_tick)
Run effects (buzzer, LCD message, LED) according to the currently triggered alarms.
AlarmPriority m_highestPriority
Highest priority of the currently triggered alarms.
void notDetectedAlarm(uint8_t p_alarmCode)
Reset detection of a specific alarm.
uint16_t m_pressure
Current pressure.
Describe an alarm and handle its dynamic state.
Definition: alarm.h:23
bool isTriggered() const
True if the number of detections is equal or above the detection threshold, false otherwise.
Definition: alarm.cpp:38
void disable()
Disable this alarm.
Definition: alarm.cpp:59
void detected(uint32_t p_cycleNumber)
If the alarm is detected, it increments the number of detection until the detection threshold.
Definition: alarm.cpp:40
void notDetected()
Reset to zero the number of detection.
Definition: alarm.cpp:51
AlarmPriority getPriority() const
Get the alarm priority.
Definition: alarm.cpp:31
void enable()
Enable this alarm.
Definition: alarm.cpp:57
uint8_t getCode() const
Get the alarm code.
Definition: alarm.cpp:33
uint32_t getCyclesSinceTrigger() const
Get the number of cycles since the alarm was triggered.
Definition: alarm.cpp:36
bool isEnabled()
True if this alarm is enabled.
Definition: alarm.cpp:61
CyclePhases
Defines the 2 main phases of the respiratory cycle.
Definition: cycle.h:14
@ INHALATION
Inspiration and inspiration holding.
Definition: cycle.h:16
uint16_t i
#define LCD_UPDATE_PERIOD_US
Period between screen updates in microsecond.
Definition: parameters.h:219
#define PIN_LED_GREEN
Definition: parameters.h:253
#define PIN_LED_RED
Definition: parameters.h:255
#define PIN_LED_YELLOW
Definition: parameters.h:254
#define LED_GREEN_ACTIVE
Definition: parameters.h:263
#define MAIN_CONTROLLER_COMPUTE_PERIOD_MICROSECONDS
Definition: parameters.h:30
#define LED_YELLOW_INACTIVE
Definition: parameters.h:262
#define LED_GREEN_INACTIVE
Definition: parameters.h:264
#define LED_RED_INACTIVE
Definition: parameters.h:260
#define LED_RED_ACTIVE
Definition: parameters.h:259
#define LED_YELLOW_ACTIVE
Definition: parameters.h:261
void displayAlarmInformation(uint8_t p_alarmCodes[], uint8_t p_nbTriggeredAlarms)
Display triggered alarm codes.
Definition: screen.cpp:146
List of alarms (named by their code)
uint8_t alarms[ALARMS_SIZE]
void sendControlAck(uint8_t setting, uint16_t valueValue)
Send a "control ack" message.
Definition: telemetry.cpp:1109
void sendAlarmTrap(uint16_t centileValue, int16_t pressureValue, CyclePhases phase, uint32_t cycleValue, uint8_t alarmCode, AlarmPriority alarmPriority, bool triggered, uint32_t expectedValue, uint32_t measuredValue, uint32_t cyclesSinceTriggerValue)
Send a "alarm trap" message.
Definition: telemetry.cpp:969