software:firmware
MakAir Firmware
screen.cpp
Go to the documentation of this file.
1 
11 #pragma once
12 
13 // INCLUDES ===================================================================
14 
15 // Associated header
16 #include "../includes/screen.h"
17 
18 // Internal
19 #include "../includes/parameters.h"
20 
21 // INITIALISATION =============================================================
22 
24 static const uint8_t MAX_ALARMS_DISPLAYED = 4;
25 
27 static const char* NO_ALARM_LINE = "PEAK PLAT PEEP ";
28 
31 static const char* ALARM_LINE = "Alarm: ";
32 
34 static const int ALARMS_CODE_POS = 6;
35 
37 LiquidCrystal
39 
40 // FUNCTIONS ==================================================================
41 
42 void startScreen() {
44  screen.setCursor(0, 0);
45  screen.print("Initialization ");
46  screen.setCursor(0, 1);
47  screen.print(VERSION);
48 }
49 
50 void resetScreen() { screen.clear(); }
51 
52 // cppcheck-suppress unusedFunction
53 void displayCurrentVolume(int32_t volumeMassFlow, uint16_t cyclesPerMinute) {
54  screen.setCursor(0, 0);
55 
56  char message[SCREEN_LINE_LENGTH + 1];
57 
58  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "Cpm:%2u %4dml", cyclesPerMinute,
59  volumeMassFlow);
60 
61  screen.print(message);
62 }
63 
64 // cppcheck-suppress unusedFunction
65 void displayCurrentPressure(uint16_t pressure, uint16_t cyclesPerMinute) {
66  screen.setCursor(0, 0);
67 
68  char message[SCREEN_LINE_LENGTH + 1];
69 
70  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "Pressure:%2u %2ucpm",
71  convertAndRound(pressure), cyclesPerMinute);
72 
73  screen.print(message);
74 }
75 
76 void displayCurrentSettings(uint16_t peakPressureMax,
77  uint16_t plateauPressureMax,
78  uint16_t peepMin) {
79  // cppcheck-suppress misra-c2012-12.3
80  screen.setCursor(0, 1);
81 
82  char message[SCREEN_LINE_LENGTH + 1];
83 
84  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "%2u %2u %2u set ",
85  convertAndRound(peakPressureMax), convertAndRound(plateauPressureMax),
86  convertAndRound(peepMin));
87 
88  screen.print(message);
89 }
90 
91 void displayCurrentInformation(uint16_t peakPressure, uint16_t plateauPressure, uint16_t peep) {
92  // cppcheck-suppress misra-c2012-12.3 ; call to unknown external: screen.setCursor
93  screen.setCursor(0, 3);
94  char message[SCREEN_LINE_LENGTH + 1];
95 
96  // If plateau was not detected
97  if (plateauPressure == UINT16_MAX) {
98  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "%2u ? %2u meas",
99  convertAndRound(peakPressure), convertAndRound(peep));
100  } else {
101  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "%2u %2u %2u meas",
102  convertAndRound(peakPressure), convertAndRound(plateauPressure),
103  convertAndRound(peep));
104  }
105 
106  screen.print(message);
107 }
108 
109 static uint8_t prevNbAlarmToPrint = 255;
110 static uint8_t prevAlarmCodes[MAX_ALARMS_DISPLAYED] = {0};
111 static bool clearCache = false;
112 
114 static bool hasAlarmInformationChanged(uint8_t p_alarmCodes[], uint8_t p_nbTriggeredAlarms) {
115  bool hasChanged = false;
116 
117  if (clearCache == true) {
118  clearCache = false;
119  hasChanged = true;
120  } else {
121  uint8_t nbAlarmToPrint = min(MAX_ALARMS_DISPLAYED, p_nbTriggeredAlarms);
122 
123  if (nbAlarmToPrint != prevNbAlarmToPrint) {
124  hasChanged = true;
125  } else {
126  for (uint8_t i = 0; i < nbAlarmToPrint; ++i) {
127  if (p_alarmCodes[i] != prevAlarmCodes[i]) {
128  hasChanged = true;
129  break;
130  }
131  }
132  }
133 
134  if (hasChanged) {
135  prevNbAlarmToPrint = nbAlarmToPrint;
136  for (uint8_t i = 0; i < nbAlarmToPrint; ++i) {
137  prevAlarmCodes[i] = p_alarmCodes[i];
138  }
139  }
140  }
141  return hasChanged;
142 }
143 
145 
146 void displayAlarmInformation(uint8_t p_alarmCodes[], uint8_t p_nbTriggeredAlarms) {
147  // WARNING There is a risk of data not being displayed as expected
148  // if the line is overwritten somewhere else in the code.
149  if (hasAlarmInformationChanged(p_alarmCodes, p_nbTriggeredAlarms)) {
150  if (p_nbTriggeredAlarms == 0u) {
151  screen.setCursor(0, 2);
152  screen.print(NO_ALARM_LINE);
153  } else {
154  uint8_t nbAlarmToPrint = min(MAX_ALARMS_DISPLAYED, p_nbTriggeredAlarms);
155 
156  // +1 for trailing NULL char
157  char buf[SCREEN_LINE_LENGTH + 1];
158 
159  // Write beginning of line
160  (void)strncpy(buf, ALARM_LINE, ALARMS_CODE_POS);
161 
162  // Write alarm codes
163  int pos = ALARMS_CODE_POS;
164  for (uint8_t i = 0; i < nbAlarmToPrint; i++) {
165  int spaceLeft = SCREEN_LINE_LENGTH - pos;
166  // + 1 for the trailing NULL char
167  int n = snprintf(&buf[pos], spaceLeft + 1, " %u", p_alarmCodes[i]);
168  if ((n < 0) || (n > spaceLeft)) {
169  break; // Error or no space left in buffer
170  }
171  pos += n;
172  }
173 
174  // Fill the end of the line with spaces
175  (void)strncpy(&buf[pos], &ALARM_LINE[pos], SCREEN_LINE_LENGTH - pos);
176 
177  // Make sure string is NULL terminated
178  buf[SCREEN_LINE_LENGTH] = '\0';
179 
180  screen.setCursor(0, 2);
181  screen.print(buf);
182  }
183  }
184 }
185 
186 void displayPressureOffset(int32_t p_inspiratoryPressureSensorOffset) {
187  screen.setCursor(0, 3);
188  char message[SCREEN_LINE_LENGTH + 1];
189  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "P offset: %3d mmH2O",
190  p_inspiratoryPressureSensorOffset);
191  screen.print(message);
192 }
193 
194 void displayFlowMeterFail(int32_t p_flowMeterFlowAtStarting, int32_t p_flowMeterFlowWithBlowerOn) {
195  resetScreen();
196  screen.setCursor(0, 0);
197  char line1[SCREEN_LINE_LENGTH + 1];
198  (void)snprintf(line1, SCREEN_LINE_LENGTH + 1, "Flow offset: %3d SLM",
199  p_flowMeterFlowAtStarting / 1000);
200  screen.print(line1);
201  screen.setCursor(0, 1);
202  char line2[SCREEN_LINE_LENGTH + 1];
203  (void)snprintf(line2, SCREEN_LINE_LENGTH + 1, "Max flow: %-3d SLM",
204  p_flowMeterFlowWithBlowerOn / 1000);
205  screen.print(line2);
206  screen.setCursor(0, 2);
207  screen.print("Flow meter fail");
208  screen.setCursor(0, 3);
209  screen.print("Press start to retry");
210 }
211 
212 void displayFlowMeterOffset(int32_t p_flowMeterFlowOffset) {
213  screen.setCursor(0, 3);
214  char message[SCREEN_LINE_LENGTH + 1];
215  (void)snprintf(message, SCREEN_LINE_LENGTH + 1, "Flow offset: %3d SLM", p_flowMeterFlowOffset);
216  screen.print(message);
217 }
218 
219 void displayPressureOffsetUnstable(uint32_t p_minOffsetValue, uint32_t p_maxOffsetValue) {
220  resetScreen();
221  screen.setCursor(0, 0);
222  char line1[SCREEN_LINE_LENGTH + 1];
223  (void)snprintf(line1, SCREEN_LINE_LENGTH + 1, "P offset is unstable");
224  screen.print(line1);
225  screen.setCursor(0, 1);
226  char line2[SCREEN_LINE_LENGTH + 1];
227  (void)snprintf(line2, SCREEN_LINE_LENGTH + 1, "Max-Min: %3u mmH2O",
228  p_maxOffsetValue - p_minOffsetValue);
229  screen.print(line2);
230  screen.setCursor(0, 2);
231  screen.print("Unplug patient and");
232  screen.setCursor(0, 3);
233  screen.print("press start");
234 }
235 
237  screen.setCursor(0, 0);
238  screen.print("Calibration");
239  screen.setCursor(0, 2);
240  screen.print("Patient must be");
241  screen.setCursor(0, 3);
242  screen.print("unplugged");
243 }
244 
246  screen.clear();
247  screen.print("EOL Test Mode");
248 }
249 
251  screen.clear();
252  screen.setCursor(0, 0);
253  screen.print("An error has occured");
254  screen.setCursor(0, 2);
255  screen.print("Check the machine");
256  screen.setCursor(0, 3);
257  screen.print("before re-using");
258 }
259 
261  screen.clear();
262  screen.setCursor(0, 0);
263  screen.print("Battery very low");
264  screen.setCursor(0, 2);
265  screen.print("Please charge");
266  screen.setCursor(0, 3);
267  screen.print("before running.");
268 }
269 
271  screen.setCursor(0, 3);
272  screen.print("Press start to begin");
273 }
274 
275 uint16_t convertAndRound(uint16_t pressure) {
276  uint16_t result;
277  uint16_t lastDigit = pressure % 10u;
278 
279  if (lastDigit < 5u) {
280  result = (pressure / 10u);
281  } else {
282  result = (pressure / 10u) + 1u;
283  }
284 
285  return result;
286 }
uint16_t i
#define PIN_LCD_D5
Definition: parameters.h:207
#define VERSION
Current version of the software.
Definition: parameters.h:20
#define PIN_LCD_D7
Definition: parameters.h:209
#define PIN_LCD_D4
Definition: parameters.h:206
#define PIN_LCD_RS
Definition: parameters.h:203
#define SCREEN_LINE_LENGTH
Number of characters per line.
Definition: parameters.h:215
#define PIN_LCD_EN
Definition: parameters.h:205
#define SCREEN_LINE_NUMBER
Number of lines.
Definition: parameters.h:212
#define PIN_LCD_D6
Definition: parameters.h:208
#define PIN_LCD_RW
Definition: parameters.h:204
void displayAlarmInformation(uint8_t p_alarmCodes[], uint8_t p_nbTriggeredAlarms)
Display triggered alarm codes.
Definition: screen.cpp:146
void displayBatteryDeepDischarge()
Display error when battery level is too discharged.
Definition: screen.cpp:260
void displayMachineStopped()
Display a message when the machine is stopped.
Definition: screen.cpp:270
void displayWatchdogError()
Display error when machine was restarted by watchdog.
Definition: screen.cpp:250
static const int ALARMS_CODE_POS
Position of the first alarm code in the third line of the screen.
Definition: screen.cpp:34
uint16_t convertAndRound(uint16_t pressure)
Convert and round a pressure value.
Definition: screen.cpp:275
void displayPressureOffsetUnstable(uint32_t p_minOffsetValue, uint32_t p_maxOffsetValue)
Display error when pressure offset is unstable.
Definition: screen.cpp:219
void displayCurrentSettings(uint16_t peakPressureMax, uint16_t plateauPressureMax, uint16_t peepMin)
Display the current settings.
Definition: screen.cpp:76
void displayFlowMeterOffset(int32_t p_flowMeterFlowOffset)
Display flow meter offset.
Definition: screen.cpp:212
static uint8_t prevAlarmCodes[MAX_ALARMS_DISPLAYED]
Definition: screen.cpp:110
static const char * ALARM_LINE
Static label to display at the begining of the third line of the screen when at least one alarm is tr...
Definition: screen.cpp:31
void clearAlarmDisplayCache()
Force clear the alarm display cache.
Definition: screen.cpp:144
void displayEndOfLineTestMode()
Show that EOL mode was triggered.
Definition: screen.cpp:245
static bool clearCache
Definition: screen.cpp:111
LiquidCrystal screen(PIN_LCD_RS, PIN_LCD_RW, PIN_LCD_EN, PIN_LCD_D4, PIN_LCD_D5, PIN_LCD_D6, PIN_LCD_D7)
Instance of the screen controller.
static const char * NO_ALARM_LINE
Text to display at the third line of the screen when no alarm is triggered.
Definition: screen.cpp:27
static const uint8_t MAX_ALARMS_DISPLAYED
Number of alarm codes to display on screen at most.
Definition: screen.cpp:24
void displayPressureOffset(int32_t p_inspiratoryPressureSensorOffset)
Display pressure offset.
Definition: screen.cpp:186
void displayPatientMustBeUnplugged()
Display the "calibration in progress" message.
Definition: screen.cpp:236
static uint8_t prevNbAlarmToPrint
Definition: screen.cpp:109
void displayCurrentPressure(uint16_t pressure, uint16_t cyclesPerMinute)
Display the current step of the breathing.
Definition: screen.cpp:65
static bool hasAlarmInformationChanged(uint8_t p_alarmCodes[], uint8_t p_nbTriggeredAlarms)
Check whether triggered alarms are already displayed on screen or not.
Definition: screen.cpp:114
void displayCurrentVolume(int32_t volumeMassFlow, uint16_t cyclesPerMinute)
Display the current injected air volume.
Definition: screen.cpp:53
void resetScreen()
Erase everything that is on the screen.
Definition: screen.cpp:50
void startScreen()
Start the screen.
Definition: screen.cpp:42
void displayFlowMeterFail(int32_t p_flowMeterFlowAtStarting, int32_t p_flowMeterFlowWithBlowerOn)
Display error when flow meter fails.
Definition: screen.cpp:194
void displayCurrentInformation(uint16_t peakPressure, uint16_t plateauPressure, uint16_t peep)
Display relevant values from the ongoing cycle.
Definition: screen.cpp:91