software:firmware
MakAir Firmware
telemetry.cpp
Go to the documentation of this file.
1 
8 #pragma once
9 
10 // INCLUDES ===================================================================
11 
12 // Associated header
13 #include "../includes/telemetry.h"
14 
15 // Externals
16 #include "Arduino.h"
17 #include "CRC32.h"
18 #include "LL/stm32yyxx_ll_utils.h"
19 
21 #include "../includes/main_controller.h"
22 
23 // INITIALISATION =============================================================
24 
26 static byte deviceId[12]; // 3 * 32 bits = 96 bits
27 
28 #define FIRST_BYTE (uint8_t)0xFF
29 
30 #define HEADER_SIZE 2
31 static const uint8_t header[HEADER_SIZE] = {0x03, 0x0C};
32 #define FOOTER_SIZE 2
33 static const uint8_t footer[FOOTER_SIZE] = {0x30, 0xC0};
34 
35 // FUNCTIONS ==================================================================
36 
44 void toBytes16(byte bytes[], uint16_t data) {
45  bytes[0] = (data >> 8) & FIRST_BYTE;
46  bytes[1] = data & FIRST_BYTE;
47 }
48 
55 void toBytes32(byte bytes[], uint32_t data) {
56  bytes[0] = (data >> 24) & FIRST_BYTE;
57  bytes[1] = (data >> 16) & FIRST_BYTE;
58  bytes[2] = (data >> 8) & FIRST_BYTE;
59  bytes[3] = data & FIRST_BYTE;
60 }
61 
68 void toBytes64(byte bytes[], uint64_t data) {
69  bytes[0] = (data >> 56) & FIRST_BYTE;
70  bytes[1] = (data >> 48) & FIRST_BYTE;
71  bytes[2] = (data >> 40) & FIRST_BYTE;
72  bytes[3] = (data >> 32) & FIRST_BYTE;
73  bytes[4] = (data >> 24) & FIRST_BYTE;
74  bytes[5] = (data >> 16) & FIRST_BYTE;
75  bytes[6] = (data >> 8) & FIRST_BYTE;
76  bytes[7] = data & FIRST_BYTE;
77 }
78 
85 void computeDeviceId(void) {
86  deviceId[0] = (LL_GetUID_Word0() >> 24) & FIRST_BYTE;
87  deviceId[1] = (LL_GetUID_Word0() >> 16) & FIRST_BYTE;
88  deviceId[2] = (LL_GetUID_Word0() >> 8) & FIRST_BYTE;
89  deviceId[3] = LL_GetUID_Word0() & FIRST_BYTE;
90  deviceId[4] = (LL_GetUID_Word1() >> 24) & FIRST_BYTE;
91  deviceId[5] = (LL_GetUID_Word1() >> 16) & FIRST_BYTE;
92  deviceId[6] = (LL_GetUID_Word1() >> 8) & FIRST_BYTE;
93  deviceId[7] = LL_GetUID_Word1() & FIRST_BYTE;
94  deviceId[8] = (LL_GetUID_Word2() >> 24) & FIRST_BYTE;
95  deviceId[9] = (LL_GetUID_Word2() >> 16) & FIRST_BYTE;
96  deviceId[10] = (LL_GetUID_Word2() >> 8) & FIRST_BYTE;
97  deviceId[11] = LL_GetUID_Word2() & FIRST_BYTE;
98 }
99 
105 uint64_t computeSystick(void) {
106  return (static_cast<uint64_t>(millis()) * 1000u) + (micros() % 1000u);
107 }
108 
109 void initTelemetry(void) {
110  Serial6.begin(115200);
111  computeDeviceId();
112 }
113 
115  uint8_t value128 = 128u;
116 
117  Serial6.write(header, HEADER_SIZE);
118  CRC32 crc32;
119  Serial6.write("B:", 2);
120  crc32.update("B:", 2);
121  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
122  crc32.update((uint8_t)PROTOCOL_VERSION);
123 
124  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
125  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
126  Serial6.print(VERSION);
127  crc32.update(VERSION, strlen(VERSION));
128  Serial6.write(deviceId, 12);
129  crc32.update(deviceId, 12);
130 
131  Serial6.print("\t");
132  // cppcheck-suppress misra-c2012-12.3 ; false positive
133  crc32.update("\t", 1);
134 
135  byte systick[8]; // 64 bits
136  // cppcheck-suppress misra-c2012-12.3 ; false positive
137  toBytes64(systick, computeSystick());
138  Serial6.write(systick, 8);
139  crc32.update(systick, 8);
140 
141  Serial6.print("\t");
142  // cppcheck-suppress misra-c2012-12.3 ; false positive
143  crc32.update("\t", 1);
144 
145  Serial6.write(MODE);
146  crc32.update(static_cast<uint8_t>(MODE));
147 
148  Serial6.print("\t");
149  // cppcheck-suppress misra-c2012-12.3 ; false positive
150  crc32.update("\t", 1);
151 
152  Serial6.write(value128);
153  crc32.update(value128);
154 
155  Serial6.print("\n");
156  crc32.update("\n", 1);
157 
158  byte crc[4]; // 32 bits
159  toBytes32(crc, crc32.finalize());
160  Serial6.write(crc, 4);
161  Serial6.write(footer, FOOTER_SIZE);
162 }
163 
164 void sendStoppedMessage(uint8_t peakCommand,
165  uint8_t plateauCommand,
166  uint8_t peepCommand,
167  uint8_t cpmCommand,
168  uint8_t expiratoryTerm,
169  bool triggerEnabled,
170  uint8_t triggerOffset,
171  bool alarmSnoozed,
172  uint8_t cpuLoad,
173  VentilationModes ventilationMode,
174  uint8_t inspiratoryTriggerFlow,
175  uint8_t expiratoryTriggerFlow,
176  uint16_t tiMinValue,
177  uint16_t tiMaxValue,
178  uint8_t lowInspiratoryMinuteVolumeAlarmThreshold,
179  uint8_t highInspiratoryMinuteVolumeAlarmThreshold,
180  uint8_t lowExpiratoryMinuteVolumeAlarmThreshold,
181  uint8_t highExpiratoryMinuteVolumeAlarmThreshold,
182  uint8_t lowRespiratoryRateAlarmThreshold,
183  uint8_t highRespiratoryRateAlarmThreshold,
184  uint16_t targetTidalVolumeValue,
185  uint16_t lowTidalVolumeAlarmThresholdValue,
186  uint16_t highTidalVolumeAlarmThresholdValue,
187  uint16_t plateauDurationValue,
188  uint16_t leakAlarmThresholdValue,
189  uint8_t targetInspiratoryFlow,
190  uint16_t inspiratoryDurationCommandValue,
191  uint16_t batteryLevelValue,
192  uint8_t currentAlarmCodes[ALARMS_SIZE],
193  uint16_t localeValue,
194  uint8_t patientHeight,
195  uint8_t patientGender,
196  uint16_t peakPressureAlarmThresholdValue) {
197  uint8_t currentAlarmSize = 0;
198  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
199  if (currentAlarmCodes[i] != 0u) {
200  currentAlarmSize++;
201  } else {
202  break;
203  }
204  }
205 
206  uint8_t ventilationModeValue;
207  switch (ventilationMode) {
208  case PC_CMV:
209  ventilationModeValue = 1u;
210  break;
211  case PC_AC:
212  ventilationModeValue = 2u;
213  break;
214  case VC_CMV:
215  ventilationModeValue = 3u;
216  break;
217  case PC_VSAI:
218  ventilationModeValue = 4u;
219  break;
220  case VC_AC:
221  ventilationModeValue = 5u;
222  break;
223  default:
224  ventilationModeValue = 0u;
225  break;
226  }
227 
228  Serial6.write(header, HEADER_SIZE);
229  CRC32 crc32;
230  Serial6.write("O:", 2);
231  crc32.update("O:", 2);
232  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
233  crc32.update((uint8_t)PROTOCOL_VERSION);
234 
235  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
236  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
237  Serial6.print(VERSION);
238  crc32.update(VERSION, strlen(VERSION));
239  Serial6.write(deviceId, 12);
240  crc32.update(deviceId, 12);
241 
242  Serial6.print("\t");
243  crc32.update("\t", 1);
244 
245  byte systick[8]; // 64 bits
246  toBytes64(systick, computeSystick());
247  Serial6.write(systick, 8);
248  crc32.update(systick, 8);
249 
250  Serial6.print("\t");
251  crc32.update("\t", 1);
252 
253  Serial6.write(peakCommand);
254  crc32.update(peakCommand);
255 
256  Serial6.print("\t");
257  crc32.update("\t", 1);
258 
259  Serial6.write(plateauCommand);
260  crc32.update(plateauCommand);
261 
262  Serial6.print("\t");
263  crc32.update("\t", 1);
264 
265  Serial6.write(peepCommand);
266  crc32.update(peepCommand);
267 
268  Serial6.print("\t");
269  crc32.update("\t", 1);
270 
271  Serial6.write(cpmCommand);
272  crc32.update(cpmCommand);
273 
274  Serial6.print("\t");
275  crc32.update("\t", 1);
276 
277  Serial6.write(expiratoryTerm);
278  crc32.update(expiratoryTerm);
279 
280  Serial6.print("\t");
281  crc32.update("\t", 1);
282 
283  Serial6.write(triggerEnabled);
284  crc32.update(triggerEnabled);
285 
286  Serial6.print("\t");
287  crc32.update("\t", 1);
288 
289  Serial6.write(triggerOffset);
290  crc32.update(triggerOffset);
291 
292  Serial6.print("\t");
293  crc32.update("\t", 1);
294 
295  Serial6.write(alarmSnoozed);
296  crc32.update(alarmSnoozed);
297 
298  Serial6.print("\t");
299  crc32.update("\t", 1);
300 
301  Serial6.write(cpuLoad);
302  crc32.update(cpuLoad);
303 
304  Serial6.print("\t");
305  crc32.update("\t", 1);
306 
307  Serial6.write(ventilationModeValue);
308  crc32.update(ventilationModeValue);
309 
310  Serial6.print("\t");
311  crc32.update("\t", 1);
312 
313  Serial6.write(inspiratoryTriggerFlow);
314  crc32.update(inspiratoryTriggerFlow);
315 
316  Serial6.print("\t");
317  crc32.update("\t", 1);
318 
319  Serial6.write(expiratoryTriggerFlow);
320  crc32.update(expiratoryTriggerFlow);
321 
322  Serial6.print("\t");
323  crc32.update("\t", 1);
324 
325  byte tiMin[2]; // 16 bits
326  toBytes16(tiMin, tiMinValue);
327  Serial6.write(tiMin, 2);
328  crc32.update(tiMin, 2);
329 
330  Serial6.print("\t");
331  crc32.update("\t", 1);
332 
333  byte tiMax[2]; // 16 bits
334  toBytes16(tiMax, tiMaxValue);
335  Serial6.write(tiMax, 2);
336  crc32.update(tiMax, 2);
337 
338  Serial6.print("\t");
339  crc32.update("\t", 1);
340 
341  Serial6.write(lowInspiratoryMinuteVolumeAlarmThreshold);
342  crc32.update(lowInspiratoryMinuteVolumeAlarmThreshold);
343 
344  Serial6.print("\t");
345  crc32.update("\t", 1);
346 
347  Serial6.write(highInspiratoryMinuteVolumeAlarmThreshold);
348  crc32.update(highInspiratoryMinuteVolumeAlarmThreshold);
349 
350  Serial6.print("\t");
351  crc32.update("\t", 1);
352 
353  Serial6.write(lowExpiratoryMinuteVolumeAlarmThreshold);
354  crc32.update(lowExpiratoryMinuteVolumeAlarmThreshold);
355 
356  Serial6.print("\t");
357  crc32.update("\t", 1);
358 
359  Serial6.write(highExpiratoryMinuteVolumeAlarmThreshold);
360  crc32.update(highExpiratoryMinuteVolumeAlarmThreshold);
361 
362  Serial6.print("\t");
363  crc32.update("\t", 1);
364 
365  Serial6.write(lowRespiratoryRateAlarmThreshold);
366  crc32.update(lowRespiratoryRateAlarmThreshold);
367 
368  Serial6.print("\t");
369  crc32.update("\t", 1);
370 
371  Serial6.write(highRespiratoryRateAlarmThreshold);
372  crc32.update(highRespiratoryRateAlarmThreshold);
373 
374  Serial6.print("\t");
375  crc32.update("\t", 1);
376 
377  byte targetTidalVolume[2]; // 16 bits
378  toBytes16(targetTidalVolume, targetTidalVolumeValue);
379  Serial6.write(targetTidalVolume, 2);
380  crc32.update(targetTidalVolume, 2);
381 
382  Serial6.print("\t");
383  crc32.update("\t", 1);
384 
385  byte lowTidalVolumeAlarmThreshold[2]; // 16 bits
386  toBytes16(lowTidalVolumeAlarmThreshold, lowTidalVolumeAlarmThresholdValue);
387  Serial6.write(lowTidalVolumeAlarmThreshold, 2);
388  crc32.update(lowTidalVolumeAlarmThreshold, 2);
389 
390  Serial6.print("\t");
391  crc32.update("\t", 1);
392 
393  byte highTidalVolumeAlarmThreshold[2]; // 16 bits
394  toBytes16(highTidalVolumeAlarmThreshold, highTidalVolumeAlarmThresholdValue);
395  Serial6.write(highTidalVolumeAlarmThreshold, 2);
396  crc32.update(highTidalVolumeAlarmThreshold, 2);
397 
398  Serial6.print("\t");
399  crc32.update("\t", 1);
400 
401  byte plateauDuration[2]; // 16 bits
402  toBytes16(plateauDuration, plateauDurationValue);
403  Serial6.write(plateauDuration, 2);
404  crc32.update(plateauDuration, 2);
405 
406  Serial6.print("\t");
407  crc32.update("\t", 1);
408 
409  byte leakAlarmThreshold[2]; // 16 bits
410  toBytes16(leakAlarmThreshold, leakAlarmThresholdValue);
411  Serial6.write(leakAlarmThreshold, 2);
412  crc32.update(leakAlarmThreshold, 2);
413 
414  Serial6.print("\t");
415  crc32.update("\t", 1);
416 
417  Serial6.write(targetInspiratoryFlow);
418  crc32.update(targetInspiratoryFlow);
419 
420  Serial6.print("\t");
421  crc32.update("\t", 1);
422 
423  byte inspiratoryDurationCommand[2]; // 16 bits
424  toBytes16(inspiratoryDurationCommand, inspiratoryDurationCommandValue);
425  Serial6.write(inspiratoryDurationCommand, 2);
426  crc32.update(inspiratoryDurationCommand, 2);
427 
428  Serial6.print("\t");
429  crc32.update("\t", 1);
430 
431  byte batteryLevel[2]; // 16 bits
432  toBytes16(batteryLevel, batteryLevelValue);
433  Serial6.write(batteryLevel, 2);
434  crc32.update(batteryLevel, 2);
435 
436  Serial6.print("\t");
437  crc32.update("\t", 1);
438 
439  Serial6.write(currentAlarmSize);
440  crc32.update(currentAlarmSize);
441  Serial6.write(currentAlarmCodes, currentAlarmSize);
442  crc32.update(currentAlarmCodes, currentAlarmSize);
443 
444  Serial6.print("\t");
445  crc32.update("\t", 1);
446 
447  byte locale[2]; // 16 bits
448  toBytes16(locale, localeValue);
449  Serial6.write(locale, 2);
450  crc32.update(locale, 2);
451 
452  Serial6.print("\t");
453  crc32.update("\t", 1);
454 
455  Serial6.write(patientHeight);
456  crc32.update(patientHeight);
457 
458  Serial6.print("\t");
459  crc32.update("\t", 1);
460 
461  Serial6.write(patientGender);
462  crc32.update(patientGender);
463 
464  Serial6.print("\t");
465  crc32.update("\t", 1);
466 
467  byte peakPressureAlarmThreshold[2]; // 16 bits
468  toBytes16(peakPressureAlarmThreshold, peakPressureAlarmThresholdValue);
469  Serial6.write(peakPressureAlarmThreshold, 2);
470  crc32.update(peakPressureAlarmThreshold, 2);
471 
472  Serial6.print("\n");
473  crc32.update("\n", 1);
474 
475  byte crc[4]; // 32 bits
476  toBytes32(crc, crc32.finalize());
477  Serial6.write(crc, 4);
478  Serial6.write(footer, FOOTER_SIZE);
479 }
480 
481 void sendDataSnapshot(uint16_t centileValue,
482  int16_t pressureValue,
483  CyclePhases phase,
484  uint8_t blowerValvePosition,
485  uint8_t patientValvePosition,
486  uint8_t blowerRpm,
487  uint8_t batteryLevel,
488  int16_t inspiratoryFlowValue,
489  int16_t expiratoryFlowValue) {
490  uint8_t phaseValue;
491  if (phase == CyclePhases::INHALATION) {
492  phaseValue = 17u; // 00010001
493  } else if (phase == CyclePhases::EXHALATION) {
494  phaseValue = 68u; // 01000100
495  } else {
496  phaseValue = 0u;
497  }
498 
499  Serial6.write(header, HEADER_SIZE);
500  CRC32 crc32;
501  Serial6.write("D:", 2);
502  crc32.update("D:", 2);
503  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
504  crc32.update((uint8_t)PROTOCOL_VERSION);
505 
506  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
507  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
508  Serial6.print(VERSION);
509  crc32.update(VERSION, strlen(VERSION));
510  Serial6.write(deviceId, 12);
511  crc32.update(deviceId, 12);
512 
513  Serial6.print("\t");
514  crc32.update("\t", 1);
515 
516  byte systick[8]; // 64 bits
517  toBytes64(systick, computeSystick());
518  Serial6.write(systick, 8);
519  crc32.update(systick, 8);
520 
521  Serial6.print("\t");
522  crc32.update("\t", 1);
523 
524  byte centile[2]; // 16 bits
525  toBytes16(centile, centileValue);
526  Serial6.write(centile, 2);
527  crc32.update(centile, 2);
528 
529  Serial6.print("\t");
530  crc32.update("\t", 1);
531 
532  byte pressure[2]; // 16 bits
533  toBytes16(pressure, pressureValue);
534  Serial6.write(pressure, 2);
535  crc32.update(pressure, 2);
536 
537  Serial6.print("\t");
538  crc32.update("\t", 1);
539 
540  Serial6.write(phaseValue);
541  crc32.update(phaseValue);
542 
543  Serial6.print("\t");
544  crc32.update("\t", 1);
545 
546  Serial6.write(blowerValvePosition);
547  crc32.update(blowerValvePosition);
548 
549  Serial6.print("\t");
550  crc32.update("\t", 1);
551 
552  Serial6.write(patientValvePosition);
553  crc32.update(patientValvePosition);
554 
555  Serial6.print("\t");
556  crc32.update("\t", 1);
557 
558  Serial6.write(blowerRpm);
559  crc32.update(blowerRpm);
560 
561  Serial6.print("\t");
562  crc32.update("\t", 1);
563 
564  Serial6.write(batteryLevel);
565  crc32.update(batteryLevel);
566 
567  Serial6.print("\t");
568  crc32.update("\t", 1);
569 
570  byte inspiratoryFlow[2]; // 16 bits
571  toBytes16(inspiratoryFlow, inspiratoryFlowValue);
572  Serial6.write(inspiratoryFlow, 2);
573  crc32.update(inspiratoryFlow, 2);
574 
575  Serial6.print("\t");
576  crc32.update("\t", 1);
577 
578  byte expiratoryFlow[2]; // 16 bits
579  toBytes16(expiratoryFlow, expiratoryFlowValue);
580  Serial6.write(expiratoryFlow, 2);
581  crc32.update(expiratoryFlow, 2);
582 
583  Serial6.print("\n");
584  crc32.update("\n", 1);
585 
586  byte crc[4]; // 32 bits
587  toBytes32(crc, crc32.finalize());
588  Serial6.write(crc, 4);
589  Serial6.write(footer, FOOTER_SIZE);
590 }
591 
592 void sendMachineStateSnapshot(uint32_t cycleValue,
593  uint8_t peakCommand,
594  uint8_t plateauCommand,
595  uint8_t peepCommand,
596  uint8_t cpmCommand,
597  uint16_t previousPeakPressureValue,
598  uint16_t previousPlateauPressureValue,
599  uint16_t previousPeepPressureValue,
600  uint8_t currentAlarmCodes[ALARMS_SIZE],
601  uint16_t volumeValue,
602  uint8_t expiratoryTerm,
603  bool triggerEnabled,
604  uint8_t triggerOffset,
605  uint8_t previouscpmValue,
606  bool alarmSnoozed,
607  uint8_t cpuLoad,
608  VentilationModes ventilationMode,
609  uint8_t inspiratoryTriggerFlow,
610  uint8_t expiratoryTriggerFlow,
611  uint16_t tiMinValue,
612  uint16_t tiMaxValue,
613  uint8_t lowInspiratoryMinuteVolumeAlarmThreshold,
614  uint8_t highInspiratoryMinuteVolumeAlarmThreshold,
615  uint8_t lowExpiratoryMinuteVolumeAlarmThreshold,
616  uint8_t highExpiratoryMinuteVolumeAlarmThreshold,
617  uint8_t lowRespiratoryRateAlarmThreshold,
618  uint8_t highRespiratoryRateAlarmThreshold,
619  uint16_t targetTidalVolumeValue,
620  uint16_t lowTidalVolumeAlarmThresholdValue,
621  uint16_t highTidalVolumeAlarmThresholdValue,
622  uint16_t plateauDurationValue,
623  uint16_t leakAlarmThresholdValue,
624  uint8_t targetInspiratoryFlow,
625  uint16_t inspiratoryDurationCommandValue,
626  uint16_t previousInspiratoryDurationValue,
627  uint16_t batteryLevelValue,
628  uint16_t localeValue,
629  uint8_t patientHeight,
630  uint8_t patientGender,
631  uint16_t peakPressureAlarmThresholdValue) {
632  uint8_t currentAlarmSize = 0;
633  for (uint8_t i = 0; i < ALARMS_SIZE; i++) {
634  if (currentAlarmCodes[i] != 0u) {
635  currentAlarmSize++;
636  } else {
637  break;
638  }
639  }
640 
641  uint8_t ventilationModeValue;
642  switch (ventilationMode) {
643  case PC_CMV:
644  ventilationModeValue = 1u;
645  break;
646  case PC_AC:
647  ventilationModeValue = 2u;
648  break;
649  case VC_CMV:
650  ventilationModeValue = 3u;
651  break;
652  case PC_VSAI:
653  ventilationModeValue = 4u;
654  break;
655  case VC_AC:
656  ventilationModeValue = 5u;
657  break;
658  default:
659  ventilationModeValue = 0u;
660  break;
661  }
662  Serial6.write(header, HEADER_SIZE);
663  CRC32 crc32;
664  Serial6.write("S:", 2);
665  crc32.update("S:", 2);
666  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
667  crc32.update((uint8_t)PROTOCOL_VERSION);
668 
669  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
670  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
671  Serial6.print(VERSION);
672  crc32.update(VERSION, strlen(VERSION));
673  Serial6.write(deviceId, 12);
674  crc32.update(deviceId, 12);
675 
676  Serial6.print("\t");
677  crc32.update("\t", 1);
678 
679  byte systick[8]; // 64 bits
680  toBytes64(systick, computeSystick());
681  Serial6.write(systick, 8);
682  crc32.update(systick, 8);
683 
684  Serial6.print("\t");
685  crc32.update("\t", 1);
686 
687  byte cycle[4]; // 32 bits
688  toBytes32(cycle, cycleValue);
689  Serial6.write(cycle, 4);
690  crc32.update(cycle, 4);
691 
692  Serial6.print("\t");
693  crc32.update("\t", 1);
694 
695  Serial6.write(peakCommand);
696  crc32.update(peakCommand);
697 
698  Serial6.print("\t");
699  crc32.update("\t", 1);
700 
701  Serial6.write(plateauCommand);
702  crc32.update(plateauCommand);
703 
704  Serial6.print("\t");
705  crc32.update("\t", 1);
706 
707  Serial6.write(peepCommand);
708  crc32.update(peepCommand);
709 
710  Serial6.print("\t");
711  crc32.update("\t", 1);
712 
713  Serial6.write(cpmCommand);
714  crc32.update(cpmCommand);
715 
716  Serial6.print("\t");
717  crc32.update("\t", 1);
718 
719  byte previousPeakPressure[2]; // 16 bits
720  toBytes16(previousPeakPressure, previousPeakPressureValue);
721  Serial6.write(previousPeakPressure, 2);
722  crc32.update(previousPeakPressure, 2);
723 
724  Serial6.print("\t");
725  crc32.update("\t", 1);
726 
727  byte previousPlateauPressure[2]; // 16 bits
728  toBytes16(previousPlateauPressure, previousPlateauPressureValue);
729  Serial6.write(previousPlateauPressure, 2);
730  crc32.update(previousPlateauPressure, 2);
731 
732  Serial6.print("\t");
733  crc32.update("\t", 1);
734 
735  byte previousPeepPressure[2]; // 16 bits
736  toBytes16(previousPeepPressure, previousPeepPressureValue);
737  Serial6.write(previousPeepPressure, 2);
738  crc32.update(previousPeepPressure, 2);
739 
740  Serial6.print("\t");
741  crc32.update("\t", 1);
742 
743  Serial6.write(currentAlarmSize);
744  crc32.update(currentAlarmSize);
745  Serial6.write(currentAlarmCodes, currentAlarmSize);
746  crc32.update(currentAlarmCodes, currentAlarmSize);
747 
748  Serial6.print("\t");
749  crc32.update("\t", 1);
750 
751  byte volume[2]; // 16 bits
752  toBytes16(volume, volumeValue);
753  Serial6.write(volume, 2);
754  crc32.update(volume, 2);
755 
756  Serial6.print("\t");
757  crc32.update("\t", 1);
758 
759  Serial6.write(expiratoryTerm);
760  crc32.update(expiratoryTerm);
761 
762  Serial6.print("\t");
763  crc32.update("\t", 1);
764 
765  Serial6.write(triggerEnabled);
766  crc32.update(triggerEnabled);
767 
768  Serial6.print("\t");
769  crc32.update("\t", 1);
770 
771  Serial6.write(triggerOffset);
772  crc32.update(triggerOffset);
773 
774  Serial6.print("\t");
775  crc32.update("\t", 1);
776 
777  Serial6.write(previouscpmValue);
778  crc32.update(previouscpmValue);
779 
780  Serial6.print("\t");
781  crc32.update("\t", 1);
782 
783  Serial6.write(alarmSnoozed);
784  crc32.update(alarmSnoozed);
785 
786  Serial6.print("\t");
787  crc32.update("\t", 1);
788 
789  Serial6.write(cpuLoad);
790  crc32.update(cpuLoad);
791 
792  Serial6.print("\t");
793  crc32.update("\t", 1);
794 
795  Serial6.write(ventilationModeValue);
796  crc32.update(ventilationModeValue);
797 
798  Serial6.print("\t");
799  crc32.update("\t", 1);
800 
801  Serial6.write(inspiratoryTriggerFlow);
802  crc32.update(inspiratoryTriggerFlow);
803 
804  Serial6.print("\t");
805  crc32.update("\t", 1);
806 
807  Serial6.write(expiratoryTriggerFlow);
808  crc32.update(expiratoryTriggerFlow);
809 
810  Serial6.print("\t");
811  crc32.update("\t", 1);
812 
813  byte tiMin[2]; // 16 bits
814  toBytes16(tiMin, tiMinValue);
815  Serial6.write(tiMin, 2);
816  crc32.update(tiMin, 2);
817 
818  Serial6.print("\t");
819  crc32.update("\t", 1);
820 
821  byte tiMax[2]; // 16 bits
822  toBytes16(tiMax, tiMaxValue);
823  Serial6.write(tiMax, 2);
824  crc32.update(tiMax, 2);
825 
826  Serial6.print("\t");
827  crc32.update("\t", 1);
828 
829  Serial6.write(lowInspiratoryMinuteVolumeAlarmThreshold);
830  crc32.update(lowInspiratoryMinuteVolumeAlarmThreshold);
831 
832  Serial6.print("\t");
833  crc32.update("\t", 1);
834 
835  Serial6.write(highInspiratoryMinuteVolumeAlarmThreshold);
836  crc32.update(highInspiratoryMinuteVolumeAlarmThreshold);
837 
838  Serial6.print("\t");
839  crc32.update("\t", 1);
840 
841  Serial6.write(lowExpiratoryMinuteVolumeAlarmThreshold);
842  crc32.update(lowExpiratoryMinuteVolumeAlarmThreshold);
843 
844  Serial6.print("\t");
845  crc32.update("\t", 1);
846 
847  Serial6.write(highExpiratoryMinuteVolumeAlarmThreshold);
848  crc32.update(highExpiratoryMinuteVolumeAlarmThreshold);
849 
850  Serial6.print("\t");
851  crc32.update("\t", 1);
852 
853  Serial6.write(lowRespiratoryRateAlarmThreshold);
854  crc32.update(lowRespiratoryRateAlarmThreshold);
855 
856  Serial6.print("\t");
857  crc32.update("\t", 1);
858 
859  Serial6.write(highRespiratoryRateAlarmThreshold);
860  crc32.update(highRespiratoryRateAlarmThreshold);
861 
862  Serial6.print("\t");
863  crc32.update("\t", 1);
864 
865  byte targetTidalVolume[2]; // 16 bits
866  toBytes16(targetTidalVolume, targetTidalVolumeValue);
867  Serial6.write(targetTidalVolume, 2);
868  crc32.update(targetTidalVolume, 2);
869 
870  Serial6.print("\t");
871  crc32.update("\t", 1);
872 
873  byte lowTidalVolumeAlarmThreshold[2]; // 16 bits
874  toBytes16(lowTidalVolumeAlarmThreshold, lowTidalVolumeAlarmThresholdValue);
875  Serial6.write(lowTidalVolumeAlarmThreshold, 2);
876  crc32.update(lowTidalVolumeAlarmThreshold, 2);
877 
878  Serial6.print("\t");
879  crc32.update("\t", 1);
880 
881  byte highTidalVolumeAlarmThreshold[2]; // 16 bits
882  toBytes16(highTidalVolumeAlarmThreshold, highTidalVolumeAlarmThresholdValue);
883  Serial6.write(highTidalVolumeAlarmThreshold, 2);
884  crc32.update(highTidalVolumeAlarmThreshold, 2);
885 
886  Serial6.print("\t");
887  crc32.update("\t", 1);
888 
889  byte plateauDuration[2]; // 16 bits
890  toBytes16(plateauDuration, plateauDurationValue);
891  Serial6.write(plateauDuration, 2);
892  crc32.update(plateauDuration, 2);
893 
894  Serial6.print("\t");
895  crc32.update("\t", 1);
896 
897  byte leakAlarmThreshold[2]; // 16 bits
898  toBytes16(leakAlarmThreshold, leakAlarmThresholdValue);
899  Serial6.write(leakAlarmThreshold, 2);
900  crc32.update(leakAlarmThreshold, 2);
901 
902  Serial6.print("\t");
903  crc32.update("\t", 1);
904 
905  Serial6.write(targetInspiratoryFlow);
906  crc32.update(targetInspiratoryFlow);
907 
908  Serial6.print("\t");
909  crc32.update("\t", 1);
910 
911  byte inspiratoryDurationCommand[2]; // 16 bits
912  toBytes16(inspiratoryDurationCommand, inspiratoryDurationCommandValue);
913  Serial6.write(inspiratoryDurationCommand, 2);
914  crc32.update(inspiratoryDurationCommand, 2);
915 
916  Serial6.print("\t");
917  crc32.update("\t", 1);
918 
919  byte previousInspiratoryDuration[2]; // 16 bits
920  toBytes16(previousInspiratoryDuration, previousInspiratoryDurationValue);
921  Serial6.write(previousInspiratoryDuration, 2);
922  crc32.update(previousInspiratoryDuration, 2);
923 
924  Serial6.print("\t");
925  crc32.update("\t", 1);
926 
927  byte batteryLevel[2]; // 16 bits
928  toBytes16(batteryLevel, batteryLevelValue);
929  Serial6.write(batteryLevel, 2);
930  crc32.update(batteryLevel, 2);
931 
932  Serial6.print("\t");
933  crc32.update("\t", 1);
934 
935  byte locale[2]; // 16 bits
936  toBytes16(locale, localeValue);
937  Serial6.write(locale, 2);
938  crc32.update(locale, 2);
939 
940  Serial6.print("\t");
941  crc32.update("\t", 1);
942 
943  Serial6.write(patientHeight);
944  crc32.update(patientHeight);
945 
946  Serial6.print("\t");
947  crc32.update("\t", 1);
948 
949  Serial6.write(patientGender);
950  crc32.update(patientGender);
951 
952  Serial6.print("\t");
953  crc32.update("\t", 1);
954 
955  byte peakPressureAlarmThreshold[2]; // 16 bits
956  toBytes16(peakPressureAlarmThreshold, peakPressureAlarmThresholdValue);
957  Serial6.write(peakPressureAlarmThreshold, 2);
958  crc32.update(peakPressureAlarmThreshold, 2);
959 
960  Serial6.print("\n");
961  crc32.update("\n", 1);
962 
963  byte crc[4]; // 32 bits
964  toBytes32(crc, crc32.finalize());
965  Serial6.write(crc, 4);
966  Serial6.write(footer, FOOTER_SIZE);
967 }
968 
969 void sendAlarmTrap(uint16_t centileValue,
970  int16_t pressureValue,
971  CyclePhases phase,
972  uint32_t cycleValue,
973  uint8_t alarmCode,
974  AlarmPriority alarmPriority,
975  bool triggered,
976  uint32_t expectedValue,
977  uint32_t measuredValue,
978  uint32_t cyclesSinceTriggerValue) {
979  uint8_t phaseValue;
980  if (phase == CyclePhases::INHALATION) {
981  phaseValue = 17u; // 00010001
982  } else if (phase == CyclePhases::EXHALATION) {
983  phaseValue = 68u; // 01000100
984  } else {
985  phaseValue = 0u;
986  }
987 
988  uint8_t triggeredValue;
989  if (triggered) {
990  triggeredValue = 240u; // 11110000
991  } else {
992  triggeredValue = 15u; // 00001111
993  }
994 
995  uint8_t alarmPriorityValue;
996  if (alarmPriority == AlarmPriority::ALARM_HIGH) {
997  alarmPriorityValue = 4u; // 00000100
998  } else if (alarmPriority == AlarmPriority::ALARM_MEDIUM) {
999  alarmPriorityValue = 2u; // 00000010
1000  } else if (alarmPriority == AlarmPriority::ALARM_LOW) {
1001  alarmPriorityValue = 1u; // 00000001
1002  } else {
1003  alarmPriorityValue = 0u; // 00000000
1004  }
1005 
1006  Serial6.write(header, HEADER_SIZE);
1007  CRC32 crc32;
1008  Serial6.write("T:", 2);
1009  crc32.update("T:", 2);
1010  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1011  crc32.update((uint8_t)PROTOCOL_VERSION);
1012 
1013  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1014  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1015  Serial6.print(VERSION);
1016  crc32.update(VERSION, strlen(VERSION));
1017  Serial6.write(deviceId, 12);
1018  crc32.update(deviceId, 12);
1019 
1020  Serial6.print("\t");
1021  crc32.update("\t", 1);
1022 
1023  byte systick[8]; // 64 bits
1024  toBytes64(systick, computeSystick());
1025  Serial6.write(systick, 8);
1026  crc32.update(systick, 8);
1027 
1028  Serial6.print("\t");
1029  crc32.update("\t", 1);
1030 
1031  byte centile[2]; // 16 bits
1032  toBytes16(centile, centileValue);
1033  Serial6.write(centile, 2);
1034  crc32.update(centile, 2);
1035 
1036  Serial6.print("\t");
1037  crc32.update("\t", 1);
1038 
1039  byte pressure[2]; // 16 bits
1040  toBytes16(pressure, pressureValue);
1041  Serial6.write(pressure, 2);
1042  crc32.update(pressure, 2);
1043 
1044  Serial6.print("\t");
1045  crc32.update("\t", 1);
1046 
1047  Serial6.write(phaseValue);
1048  crc32.update(phaseValue);
1049 
1050  Serial6.print("\t");
1051  crc32.update("\t", 1);
1052 
1053  byte cycle[4]; // 32 bits
1054  toBytes32(cycle, cycleValue);
1055  Serial6.write(cycle, 4);
1056  crc32.update(cycle, 4);
1057 
1058  Serial6.print("\t");
1059  crc32.update("\t", 1);
1060 
1061  Serial6.write(alarmCode);
1062  crc32.update(alarmCode);
1063 
1064  Serial6.print("\t");
1065  crc32.update("\t", 1);
1066 
1067  Serial6.write(alarmPriorityValue);
1068  crc32.update(alarmPriorityValue);
1069 
1070  Serial6.print("\t");
1071  crc32.update("\t", 1);
1072 
1073  Serial6.write(triggeredValue);
1074  crc32.update(triggeredValue);
1075 
1076  Serial6.print("\t");
1077  crc32.update("\t", 1);
1078 
1079  byte expected[4]; // 32 bits
1080  toBytes32(expected, expectedValue);
1081  Serial6.write(expected, 4);
1082  crc32.update(expected, 4);
1083 
1084  Serial6.print("\t");
1085  crc32.update("\t", 1);
1086 
1087  byte measured[4]; // 32 bits
1088  toBytes32(measured, measuredValue);
1089  Serial6.write(measured, 4);
1090  crc32.update(measured, 4);
1091 
1092  Serial6.print("\t");
1093  crc32.update("\t", 1);
1094 
1095  byte cyclesSinceTrigger[4]; // 32 bits
1096  toBytes32(cyclesSinceTrigger, cyclesSinceTriggerValue);
1097  Serial6.write(cyclesSinceTrigger, 4);
1098  crc32.update(cyclesSinceTrigger, 4);
1099 
1100  Serial6.print("\n");
1101  crc32.update("\n", 1);
1102 
1103  byte crc[4]; // 32 bits
1104  toBytes32(crc, crc32.finalize());
1105  Serial6.write(crc, 4);
1106  Serial6.write(footer, FOOTER_SIZE);
1107 }
1108 
1109 void sendControlAck(uint8_t setting, uint16_t valueValue) {
1110  Serial6.write(header, HEADER_SIZE);
1111  CRC32 crc32;
1112  Serial6.write("A:", 2);
1113  crc32.update("A:", 2);
1114  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1115  crc32.update((uint8_t)PROTOCOL_VERSION);
1116 
1117  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1118  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1119  Serial6.print(VERSION);
1120  crc32.update(VERSION, strlen(VERSION));
1121  Serial6.write(deviceId, 12);
1122  crc32.update(deviceId, 12);
1123 
1124  Serial6.print("\t");
1125  crc32.update("\t", 1);
1126 
1127  byte systick[8]; // 64 bits
1128  toBytes64(systick, computeSystick());
1129  Serial6.write(systick, 8);
1130  crc32.update(systick, 8);
1131 
1132  Serial6.print("\t");
1133  crc32.update("\t", 1);
1134 
1135  Serial6.write(setting);
1136  crc32.update(setting);
1137 
1138  Serial6.print("\t");
1139  crc32.update("\t", 1);
1140 
1141  byte value[2]; // 16 bits
1142  toBytes16(value, valueValue);
1143  Serial6.write(value, 2);
1144  crc32.update(value, 2);
1145 
1146  Serial6.print("\n");
1147  crc32.update("\n", 1);
1148 
1149  byte crc[4]; // 32 bits
1150  toBytes32(crc, crc32.finalize());
1151  Serial6.write(crc, 4);
1152  Serial6.write(footer, FOOTER_SIZE);
1153 }
1154 
1156  Serial6.write(header, HEADER_SIZE);
1157  CRC32 crc32;
1158  Serial6.write("E:", 2);
1159  crc32.update("E:", 2);
1160  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1161  crc32.update((uint8_t)PROTOCOL_VERSION);
1162 
1163  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1164  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1165  Serial6.print(VERSION);
1166  crc32.update(VERSION, strlen(VERSION));
1167  Serial6.write(deviceId, 12);
1168  crc32.update(deviceId, 12);
1169 
1170  Serial6.print("\t");
1171  crc32.update("\t", 1);
1172 
1173  byte systick[8]; // 64 bits
1174  toBytes64(systick, computeSystick());
1175  Serial6.write(systick, 8);
1176  crc32.update(systick, 8);
1177 
1178  Serial6.print("\t");
1179  crc32.update("\t", 1);
1180 
1181  Serial6.write((uint8_t)1);
1182  crc32.update((uint8_t)1);
1183 
1184  Serial6.print("\n");
1185  crc32.update("\n", 1);
1186 
1187  byte crc[4]; // 32 bits
1188  toBytes32(crc, crc32.finalize());
1189  Serial6.write(crc, 4);
1190  Serial6.write(footer, FOOTER_SIZE);
1191 }
1192 
1193 void sendCalibrationFatalError(int16_t pressureOffsetValue,
1194  int16_t minPressureValue,
1195  int16_t maxPressureValue,
1196  int16_t flowAtStartingValue,
1197  int16_t flowWithBlowerOnValue) {
1198  Serial6.write(header, HEADER_SIZE);
1199  CRC32 crc32;
1200  Serial6.write("E:", 2);
1201  crc32.update("E:", 2);
1202  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1203  crc32.update((uint8_t)PROTOCOL_VERSION);
1204 
1205  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1206  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1207  Serial6.print(VERSION);
1208  crc32.update(VERSION, strlen(VERSION));
1209  Serial6.write(deviceId, 12);
1210  crc32.update(deviceId, 12);
1211 
1212  Serial6.print("\t");
1213  crc32.update("\t", 1);
1214 
1215  byte systick[8]; // 64 bits
1216  toBytes64(systick, computeSystick());
1217  Serial6.write(systick, 8);
1218  crc32.update(systick, 8);
1219 
1220  Serial6.print("\t");
1221  crc32.update("\t", 1);
1222 
1223  Serial6.write((uint8_t)2);
1224  crc32.update((uint8_t)2);
1225 
1226  Serial6.print("\t");
1227  crc32.update("\t", 1);
1228 
1229  byte pressureOffset[2]; // 16 bits
1230  toBytes16(pressureOffset, pressureOffsetValue);
1231  Serial6.write(pressureOffset, 2);
1232  crc32.update(pressureOffset, 2);
1233 
1234  Serial6.print("\t");
1235  crc32.update("\t", 1);
1236 
1237  byte minPressure[2]; // 16 bits
1238  toBytes16(minPressure, minPressureValue);
1239  Serial6.write(minPressure, 2);
1240  crc32.update(minPressure, 2);
1241 
1242  Serial6.print("\t");
1243  crc32.update("\t", 1);
1244 
1245  byte maxPressure[2]; // 16 bits
1246  toBytes16(maxPressure, maxPressureValue);
1247  Serial6.write(maxPressure, 2);
1248  crc32.update(maxPressure, 2);
1249 
1250  Serial6.print("\t");
1251  crc32.update("\t", 1);
1252 
1253  byte flowAtStarting[2]; // 16 bits
1254  toBytes16(flowAtStarting, flowAtStartingValue);
1255  Serial6.write(flowAtStarting, 2);
1256  crc32.update(flowAtStarting, 2);
1257 
1258  Serial6.print("\t");
1259  crc32.update("\t", 1);
1260 
1261  byte flowWithBlowerOn[2]; // 16 bits
1262  toBytes16(flowWithBlowerOn, flowWithBlowerOnValue);
1263  Serial6.write(flowWithBlowerOn, 2);
1264  crc32.update(flowWithBlowerOn, 2);
1265 
1266  Serial6.print("\n");
1267  crc32.update("\n", 1);
1268 
1269  byte crc[4]; // 32 bits
1270  toBytes32(crc, crc32.finalize());
1271  Serial6.write(crc, 4);
1272  Serial6.write(footer, FOOTER_SIZE);
1273 }
1274 
1275 void sendBatteryDeeplyDischargedFatalError(uint16_t batteryLevelValue) {
1276  Serial6.write(header, HEADER_SIZE);
1277  CRC32 crc32;
1278  Serial6.write("E:", 2);
1279  crc32.update("E:", 2);
1280  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1281  crc32.update((uint8_t)PROTOCOL_VERSION);
1282 
1283  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1284  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1285  Serial6.print(VERSION);
1286  crc32.update(VERSION, strlen(VERSION));
1287  Serial6.write(deviceId, 12);
1288  crc32.update(deviceId, 12);
1289 
1290  Serial6.print("\t");
1291  crc32.update("\t", 1);
1292 
1293  byte systick[8]; // 64 bits
1294  toBytes64(systick, computeSystick());
1295  Serial6.write(systick, 8);
1296  crc32.update(systick, 8);
1297 
1298  Serial6.print("\t");
1299  crc32.update("\t", 1);
1300 
1301  Serial6.write((uint8_t)3);
1302  crc32.update((uint8_t)3);
1303 
1304  Serial6.print("\t");
1305  crc32.update("\t", 1);
1306 
1307  byte batteryLevel[2]; // 16 bits
1308  toBytes16(batteryLevel, batteryLevelValue);
1309  Serial6.write(batteryLevel, 2);
1310  crc32.update(batteryLevel, 2);
1311 
1312  Serial6.print("\n");
1313  crc32.update("\n", 1);
1314 
1315  byte crc[4]; // 32 bits
1316  toBytes32(crc, crc32.finalize());
1317  Serial6.write(crc, 4);
1318  Serial6.write(footer, FOOTER_SIZE);
1319 }
1320 
1322  Serial6.write(header, HEADER_SIZE);
1323  CRC32 crc32;
1324  Serial6.write("E:", 2);
1325  crc32.update("E:", 2);
1326  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1327  crc32.update((uint8_t)PROTOCOL_VERSION);
1328 
1329  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1330  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1331  Serial6.print(VERSION);
1332  crc32.update(VERSION, strlen(VERSION));
1333  Serial6.write(deviceId, 12);
1334  crc32.update(deviceId, 12);
1335 
1336  Serial6.print("\t");
1337  crc32.update("\t", 1);
1338 
1339  byte systick[8]; // 64 bits
1340  toBytes64(systick, computeSystick());
1341  Serial6.write(systick, 8);
1342  crc32.update(systick, 8);
1343 
1344  Serial6.print("\t");
1345  crc32.update("\t", 1);
1346 
1347  Serial6.write((uint8_t)4);
1348  crc32.update((uint8_t)4);
1349 
1350  Serial6.print("\n");
1351  crc32.update("\n", 1);
1352 
1353  byte crc[4]; // 32 bits
1354  toBytes32(crc, crc32.finalize());
1355  Serial6.write(crc, 4);
1356  Serial6.write(footer, FOOTER_SIZE);
1357 }
1358 
1360  Serial6.write(header, HEADER_SIZE);
1361  CRC32 crc32;
1362  Serial6.write("E:", 2);
1363  crc32.update("E:", 2);
1364  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1365  crc32.update((uint8_t)PROTOCOL_VERSION);
1366 
1367  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1368  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1369  Serial6.print(VERSION);
1370  crc32.update(VERSION, strlen(VERSION));
1371  Serial6.write(deviceId, 12);
1372  crc32.update(deviceId, 12);
1373 
1374  Serial6.print("\t");
1375  crc32.update("\t", 1);
1376 
1377  byte systick[8]; // 64 bits
1378  toBytes64(systick, computeSystick());
1379  Serial6.write(systick, 8);
1380  crc32.update(systick, 8);
1381 
1382  Serial6.print("\t");
1383  crc32.update("\t", 1);
1384 
1385  Serial6.write((uint8_t)5);
1386  crc32.update((uint8_t)5);
1387 
1388  Serial6.print("\t");
1389  crc32.update("\t", 1);
1390 
1391  byte pressure[2]; // 16 bits
1392  toBytes16(pressure, pressureValue);
1393  Serial6.write(pressure, 2);
1394  crc32.update(pressure, 2);
1395 
1396  Serial6.print("\n");
1397  crc32.update("\n", 1);
1398 
1399  byte crc[4]; // 32 bits
1400  toBytes32(crc, crc32.finalize());
1401  Serial6.write(crc, 4);
1402  Serial6.write(footer, FOOTER_SIZE);
1403 }
1404 
1405 #ifndef SIMULATOR
1406 void sendEolTestSnapshot(TestStep step, TestState state, char message[]) {
1407  Serial6.write(header, HEADER_SIZE);
1408  CRC32 crc32;
1409  Serial6.write("L:", 2);
1410  crc32.update("L:", 2);
1411  Serial6.write((uint8_t)PROTOCOL_VERSION); // Communication protocol version
1412  crc32.update((uint8_t)PROTOCOL_VERSION);
1413 
1414  Serial6.write(static_cast<uint8_t>(strlen(VERSION)));
1415  crc32.update(static_cast<uint8_t>(strlen(VERSION)));
1416  Serial6.print(VERSION);
1417  crc32.update(VERSION, strlen(VERSION));
1418  Serial6.write(deviceId, 12);
1419  crc32.update(deviceId, 12);
1420 
1421  Serial6.print("\t");
1422  crc32.update("\t", 1);
1423 
1424  byte systick[8]; // 64 bits
1425  toBytes64(systick, computeSystick());
1426  Serial6.write(systick, 8);
1427  crc32.update(systick, 8);
1428 
1429  Serial6.print("\t");
1430  crc32.update("\t", 1);
1431 
1432  Serial6.write(step);
1433  crc32.update(step);
1434 
1435  Serial6.print("\t");
1436  crc32.update("\t", 1);
1437 
1438  Serial6.write(state);
1439  crc32.update(state);
1440 
1441  Serial6.print("\t");
1442  crc32.update("\t", 1);
1443 
1444  Serial6.write(static_cast<uint8_t>(strlen(message)));
1445  crc32.update(static_cast<uint8_t>(strlen(message)));
1446  Serial6.print(message);
1447  crc32.update(message, strlen(message));
1448 
1449  Serial6.print("\n");
1450  crc32.update("\n", 1);
1451 
1452  byte crc[4]; // 32 bits
1453  toBytes32(crc, crc32.finalize());
1454  Serial6.write(crc, 4);
1455  Serial6.write(footer, FOOTER_SIZE);
1456 }
1457 #endif
1458 
1459 uint8_t mmH2OtoCmH2O(uint16_t pressure) {
1460  uint8_t result;
1461  uint16_t lastDigit = pressure % 10u;
1462 
1463  if (lastDigit < 5u) {
1464  result = (pressure / 10u);
1465  } else {
1466  result = (pressure / 10u) + 1u;
1467  }
1468 
1469  return result;
1470 }
AlarmPriority
Priority levels of an alarm.
Definition: alarm.h:18
@ ALARM_HIGH
Definition: alarm.h:18
@ ALARM_LOW
Definition: alarm.h:18
@ ALARM_MEDIUM
Definition: alarm.h:18
#define ALARMS_SIZE
#define MODE
Defines the current mode.
Definition: config.h:19
VentilationModes
Supported ventilation modes.
Definition: cycle.h:22
@ PC_CMV
PC-CMV (default)
Definition: cycle.h:24
@ VC_AC
VC-AC.
Definition: cycle.h:32
@ VC_CMV
VC-CMV.
Definition: cycle.h:28
@ PC_AC
PC-AC.
Definition: cycle.h:26
@ PC_VSAI
PC-VSAI.
Definition: cycle.h:30
CyclePhases
Defines the 2 main phases of the respiratory cycle.
Definition: cycle.h:14
@ EXHALATION
Exhalation and pause.
Definition: cycle.h:18
@ INHALATION
Inspiration and inspiration holding.
Definition: cycle.h:16
int32_t maxPressureValue
int32_t pressureValue
int32_t minPressureValue
TestStep
TestState
uint16_t i
#define VERSION
Current version of the software.
Definition: parameters.h:20
HardwareSerial Serial6(PIN_TELEMETRY_SERIAL_RX, PIN_TELEMETRY_SERIAL_TX)
void sendMassFlowMeterFatalError(void)
Send a "mass flow meter" fatal error.
Definition: telemetry.cpp:1321
void sendCalibrationFatalError(int16_t pressureOffsetValue, int16_t minPressureValue, int16_t maxPressureValue, int16_t flowAtStartingValue, int16_t flowWithBlowerOnValue)
Definition: telemetry.cpp:1193
void sendWatchdogRestartFatalError(void)
Send a "watchdog restart" fatal error.
Definition: telemetry.cpp:1155
static const uint8_t header[HEADER_SIZE]
Definition: telemetry.cpp:31
static const uint8_t footer[FOOTER_SIZE]
Definition: telemetry.cpp:33
void sendInconsistentPressureFatalError(uint16_t pressureValue)
Definition: telemetry.cpp:1359
void sendControlAck(uint8_t setting, uint16_t valueValue)
Send a "control ack" message.
Definition: telemetry.cpp:1109
uint64_t computeSystick(void)
Compute current systick.
Definition: telemetry.cpp:105
void sendBootMessage()
Send a "boot" message.
Definition: telemetry.cpp:114
#define HEADER_SIZE
Definition: telemetry.cpp:30
void toBytes16(byte bytes[], uint16_t data)
Convert a u16 so that it can be sent through serial.
Definition: telemetry.cpp:44
#define FIRST_BYTE
Definition: telemetry.cpp:28
void sendBatteryDeeplyDischargedFatalError(uint16_t batteryLevelValue)
Send a "battery deeply discharged" fatal error.
Definition: telemetry.cpp:1275
void sendEolTestSnapshot(TestStep step, TestState state, char message[])
Send an "end-of-line test" snapshot.
Definition: telemetry.cpp:1406
uint8_t mmH2OtoCmH2O(uint16_t pressure)
Convert and round a pressure in mmH2O to a pressure in cmH2O.
Definition: telemetry.cpp:1459
void initTelemetry(void)
Prepare Serial6 to send telemetry data.
Definition: telemetry.cpp:109
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
void computeDeviceId(void)
Compute device ID.
Definition: telemetry.cpp:85
void sendStoppedMessage(uint8_t peakCommand, uint8_t plateauCommand, uint8_t peepCommand, uint8_t cpmCommand, uint8_t expiratoryTerm, bool triggerEnabled, uint8_t triggerOffset, bool alarmSnoozed, uint8_t cpuLoad, VentilationModes ventilationMode, uint8_t inspiratoryTriggerFlow, uint8_t expiratoryTriggerFlow, uint16_t tiMinValue, uint16_t tiMaxValue, uint8_t lowInspiratoryMinuteVolumeAlarmThreshold, uint8_t highInspiratoryMinuteVolumeAlarmThreshold, uint8_t lowExpiratoryMinuteVolumeAlarmThreshold, uint8_t highExpiratoryMinuteVolumeAlarmThreshold, uint8_t lowRespiratoryRateAlarmThreshold, uint8_t highRespiratoryRateAlarmThreshold, uint16_t targetTidalVolumeValue, uint16_t lowTidalVolumeAlarmThresholdValue, uint16_t highTidalVolumeAlarmThresholdValue, uint16_t plateauDurationValue, uint16_t leakAlarmThresholdValue, uint8_t targetInspiratoryFlow, uint16_t inspiratoryDurationCommandValue, uint16_t batteryLevelValue, uint8_t currentAlarmCodes[ALARMS_SIZE], uint16_t localeValue, uint8_t patientHeight, uint8_t patientGender, uint16_t peakPressureAlarmThresholdValue)
Send a "stopped" message.
Definition: telemetry.cpp:164
void toBytes32(byte bytes[], uint32_t data)
Convert a u32 so that it can be sent through serial.
Definition: telemetry.cpp:55
static byte deviceId[12]
Internals.
Definition: telemetry.cpp:26
void sendDataSnapshot(uint16_t centileValue, int16_t pressureValue, CyclePhases phase, uint8_t blowerValvePosition, uint8_t patientValvePosition, uint8_t blowerRpm, uint8_t batteryLevel, int16_t inspiratoryFlowValue, int16_t expiratoryFlowValue)
Send a "data snapshot" message.
Definition: telemetry.cpp:481
#define FOOTER_SIZE
Definition: telemetry.cpp:32
void toBytes64(byte bytes[], uint64_t data)
Convert a u64 so that it can be sent through serial.
Definition: telemetry.cpp:68
void sendMachineStateSnapshot(uint32_t cycleValue, uint8_t peakCommand, uint8_t plateauCommand, uint8_t peepCommand, uint8_t cpmCommand, uint16_t previousPeakPressureValue, uint16_t previousPlateauPressureValue, uint16_t previousPeepPressureValue, uint8_t currentAlarmCodes[ALARMS_SIZE], uint16_t volumeValue, uint8_t expiratoryTerm, bool triggerEnabled, uint8_t triggerOffset, uint8_t previouscpmValue, bool alarmSnoozed, uint8_t cpuLoad, VentilationModes ventilationMode, uint8_t inspiratoryTriggerFlow, uint8_t expiratoryTriggerFlow, uint16_t tiMinValue, uint16_t tiMaxValue, uint8_t lowInspiratoryMinuteVolumeAlarmThreshold, uint8_t highInspiratoryMinuteVolumeAlarmThreshold, uint8_t lowExpiratoryMinuteVolumeAlarmThreshold, uint8_t highExpiratoryMinuteVolumeAlarmThreshold, uint8_t lowRespiratoryRateAlarmThreshold, uint8_t highRespiratoryRateAlarmThreshold, uint16_t targetTidalVolumeValue, uint16_t lowTidalVolumeAlarmThresholdValue, uint16_t highTidalVolumeAlarmThresholdValue, uint16_t plateauDurationValue, uint16_t leakAlarmThresholdValue, uint8_t targetInspiratoryFlow, uint16_t inspiratoryDurationCommandValue, uint16_t previousInspiratoryDurationValue, uint16_t batteryLevelValue, uint16_t localeValue, uint8_t patientHeight, uint8_t patientGender, uint16_t peakPressureAlarmThresholdValue)
Send a "machine state snapshot" message.
Definition: telemetry.cpp:592
#define PROTOCOL_VERSION
Current version of the telemetry protocol.
Definition: telemetry.h:19