1
0
mirror of https://gitlab.com/pholy/OSCAR-code.git synced 2025-04-26 07:30:45 +00:00

Avoid pos++ in PRS1 DreamStation parsers to that events can be issued independently of parsing order.

This commit is contained in:
sawinglogz 2019-08-20 11:38:55 -04:00
parent 38409f6fbf
commit 0c816c7d4c

View File

@ -1671,53 +1671,53 @@ bool PRS1DataChunk::ParseEventsF5V3(void)
// TB events have a duration in 0.1s, based on the review of pressure waveforms.
// TODO: Ideally the starting time here would be adjusted here, but PRS1ParsedEvents
// currently assume integer seconds rather than ms, so that's done at import.
duration = data[pos++];
duration = data[pos];
this->AddEvent(new PRS1TimedBreathEvent(t, duration));
break;
case 3: // Statistics
// These appear every 2 minutes, so presumably summarize the preceding period.
this->AddEvent(new PRS1IPAPEvent(t, data[pos++], GAIN)); // 00=IPAP (average?)
this->AddEvent(new PRS1IPAPLowEvent(t, data[pos++], GAIN)); // 01=IAP Low
this->AddEvent(new PRS1IPAPHighEvent(t, data[pos++], GAIN)); // 02=IAP High
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos++])); // 03=Total leak (average?)
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos++])); // 04=Breaths Per Minute (average?)
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos++])); // 05=Patient Triggered Breaths (average?)
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos++])); // 06=Minute Ventilation (average?)
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos++])); // 07=Tidal Volume (average?)
this->AddEvent(new PRS1SnoreEvent(t, data[pos++])); // 08=Snore count // TODO: not a VS on official waveform, but appears in flags and contributes to overall VS index
this->AddEvent(new PRS1EPAPEvent(t, data[pos++], GAIN)); // 09=EPAP (average? see event 1 above)
this->AddEvent(new PRS1LeakEvent(t, data[pos++])); // 0A=Leak (average?)
this->AddEvent(new PRS1IPAPEvent(t, data[pos+0], GAIN)); // 00=IPAP (average?)
this->AddEvent(new PRS1IPAPLowEvent(t, data[pos+1], GAIN)); // 01=IAP Low
this->AddEvent(new PRS1IPAPHighEvent(t, data[pos+2], GAIN)); // 02=IAP High
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos+3])); // 03=Total leak (average?)
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos+4])); // 04=Breaths Per Minute (average?)
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos+5])); // 05=Patient Triggered Breaths (average?)
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos+6])); // 06=Minute Ventilation (average?)
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos+7])); // 07=Tidal Volume (average?)
this->AddEvent(new PRS1SnoreEvent(t, data[pos+8])); // 08=Snore count // TODO: not a VS on official waveform, but appears in flags and contributes to overall VS index
this->AddEvent(new PRS1EPAPEvent(t, data[pos+9], GAIN)); // 09=EPAP (average? see event 1 above)
this->AddEvent(new PRS1LeakEvent(t, data[pos+0xa])); // 0A=Leak (average?)
break;
case 0x04: // Pressure Pulse
duration = data[pos++]; // TODO: is this a duration?
duration = data[pos]; // TODO: is this a duration?
this->AddEvent(new PRS1PressurePulseEvent(t, duration));
break;
case 0x05: // Obstructive Apnea
// OA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ObstructiveApneaEvent(t - elapsed, 0));
break;
case 0x06: // Clear Airway Apnea
// CA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ClearAirwayEvent(t - elapsed, 0));
break;
case 0x07: // Hypopnea
// TODO: How is this hypopnea different from events 0xd and 0xe?
// TODO: What is the first byte?
pos++; // unknown first byte?
elapsed = data[pos++]; // based on sample waveform, the hypopnea is over after this
//data[pos+0]; // unknown first byte?
elapsed = data[pos+1]; // based on sample waveform, the hypopnea is over after this
this->AddEvent(new PRS1HypopneaEvent(t - elapsed, 0));
break;
case 0x08: // Flow Limitation
// TODO: We should revisit whether this is elapsed or duration once (if)
// we start calculating flow limitations ourselves. Flow limitations aren't
// as obvious as OA/CA when looking at a waveform.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1FlowLimitationEvent(t - elapsed, 0));
break;
case 0x09: // Vibratory Snore
@ -1731,15 +1731,13 @@ bool PRS1DataChunk::ParseEventsF5V3(void)
case 0x0a: // Periodic Breathing
// PB events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1PeriodicBreathingEvent(t - elapsed - duration, duration));
break;
case 0x0b: // Large Leak
// LL events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1LargeLeakEvent(t - elapsed - duration, duration));
break;
case 0x0d: // Hypopnea
@ -1749,7 +1747,7 @@ bool PRS1DataChunk::ParseEventsF5V3(void)
// TODO: We should revisit whether this is elapsed or duration once (if)
// we start calculating hypopneas ourselves. Their official definition
// is 40% reduction in flow lasting at least 10s.
duration = data[pos++];
duration = data[pos];
this->AddEvent(new PRS1HypopneaEvent(t - duration, 0));
break;
case 0x0f:
@ -2441,66 +2439,64 @@ bool PRS1DataChunk::ParseEventsF3V6(void)
// TB events have a duration in 0.1s, based on the review of pressure waveforms.
// TODO: Ideally the starting time here would be adjusted here, but PRS1ParsedEvents
// currently assume integer seconds rather than ms, so that's done at import.
duration = data[pos++];
duration = data[pos];
// TODO: make sure F3 import logic matches F5 in adjusting TB start time
this->AddEvent(new PRS1TimedBreathEvent(t, duration));
break;
case 2: // Statistics
// These appear every 2 minutes, so presumably summarize the preceding period.
pos++; // TODO: 0 = ???
this->AddEvent(new PRS1EPAPEvent(t, data[pos++], GAIN)); // 01=EPAP (average?)
this->AddEvent(new PRS1IPAPEvent(t, data[pos++], GAIN)); // 02=IPAP (average?)
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos++])); // 03=Total leak (average?)
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos++])); // 04=Breaths Per Minute (average?)
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos++])); // 05=Patient Triggered Breaths (average?)
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos++])); // 06=Minute Ventilation (average?)
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos++])); // 07=Tidal Volume (average?)
this->AddEvent(new PRS1Test2Event(t, data[pos++])); // 08=Flow???
this->AddEvent(new PRS1Test1Event(t, data[pos++])); // 09=TMV???
this->AddEvent(new PRS1SnoreEvent(t, data[pos++])); // 0A=Snore count // TODO: not a VS on official waveform, but appears in flags and contributes to overall VS index
this->AddEvent(new PRS1LeakEvent(t, data[pos++])); // 0B=Leak (average?)
//data[pos+0]; // TODO: 0 = ???
this->AddEvent(new PRS1EPAPEvent(t, data[pos+1], GAIN)); // 01=EPAP (average?)
this->AddEvent(new PRS1IPAPEvent(t, data[pos+2], GAIN)); // 02=IPAP (average?)
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos+3])); // 03=Total leak (average?)
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos+4])); // 04=Breaths Per Minute (average?)
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos+5])); // 05=Patient Triggered Breaths (average?)
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos+6])); // 06=Minute Ventilation (average?)
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos+7])); // 07=Tidal Volume (average?)
this->AddEvent(new PRS1Test2Event(t, data[pos+8])); // 08=Flow???
this->AddEvent(new PRS1Test1Event(t, data[pos+9])); // 09=TMV???
this->AddEvent(new PRS1SnoreEvent(t, data[pos+0xa])); // 0A=Snore count // TODO: not a VS on official waveform, but appears in flags and contributes to overall VS index
this->AddEvent(new PRS1LeakEvent(t, data[pos+0xb])); // 0B=Leak (average?)
break;
case 0x03: // Pressure Pulse
duration = data[pos++]; // TODO: is this a duration?
duration = data[pos]; // TODO: is this a duration?
this->AddEvent(new PRS1PressurePulseEvent(t, duration));
break;
case 0x04: // Obstructive Apnea
// OA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ObstructiveApneaEvent(t - elapsed, 0));
break;
case 0x05: // Clear Airway Apnea
// CA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ClearAirwayEvent(t - elapsed, 0));
break;
case 0x06: // Hypopnea
// TODO: How is this hypopnea different from events 0xd and 0xe?
// TODO: What is the first byte?
pos++; // unknown first byte?
elapsed = data[pos++]; // based on sample waveform, the hypopnea is over after this
//data[pos+0]; // unknown first byte?
elapsed = data[pos+1]; // based on sample waveform, the hypopnea is over after this
this->AddEvent(new PRS1HypopneaEvent(t - elapsed, 0));
break;
case 0x07: // Periodic Breathing
// PB events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1PeriodicBreathingEvent(t - elapsed - duration, duration));
break;
case 0x08: // RERA
elapsed = data[pos++]; // based on sample waveform, the RERA is over after this
elapsed = data[pos]; // based on sample waveform, the RERA is over after this
this->AddEvent(new PRS1RERAEvent(t - elapsed, 0));
break;
case 0x09: // Large Leak
// LL events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1LargeLeakEvent(t - elapsed - duration, duration));
break;
case 0x0a: // Hypopnea
@ -2510,7 +2506,7 @@ bool PRS1DataChunk::ParseEventsF3V6(void)
// TODO: We should revisit whether this is elapsed or duration once (if)
// we start calculating hypopneas ourselves. Their official definition
// is 40% reduction in flow lasting at least 10s.
duration = data[pos++];
duration = data[pos];
this->AddEvent(new PRS1HypopneaEvent(t - duration, 0));
break;
// case 0x0c?
@ -3398,7 +3394,7 @@ bool PRS1DataChunk::ParseEventsF0V6(CPAPMode /*mode*/)
// adjustments. E.g. 6 at 28:11 and 7.3 at 29:05 results in the following dots:
// 6 at 28:11, 6.5 around 28:30, 7.0 around 28:50, 7(.3) at 29:05. That holds until
// subsequent "adjustment" of 7.3 at 30:09 followed by 8.0 at 30:19.
this->AddEvent(new PRS1CPAPEvent(t, data[pos++]));
this->AddEvent(new PRS1CPAPEvent(t, data[pos]));
break;
case 0x02: // Pressure adjustment (bi-level)
// TODO: Have OSCAR treat pressure adjustment events differently than (average?) stats below.
@ -3417,25 +3413,25 @@ bool PRS1DataChunk::ParseEventsF0V6(CPAPMode /*mode*/)
//CHECK_VALUE(data[pos], 40);
break;
case 0x04: // Pressure Pulse
duration = data[pos++]; // TODO: is this a duration?
duration = data[pos]; // TODO: is this a duration?
this->AddEvent(new PRS1PressurePulseEvent(t, duration));
break;
case 0x05: // RERA
elapsed = data[pos++]; // based on sample waveform, the RERA is over after this
elapsed = data[pos]; // based on sample waveform, the RERA is over after this
this->AddEvent(new PRS1RERAEvent(t - elapsed, 0));
break;
case 0x06: // Obstructive Apnea
// OA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ObstructiveApneaEvent(t - elapsed, 0));
break;
case 0x07: // Clear Airway Apnea
// CA events are instantaneous flags with no duration: reviewing waveforms
// shows that the time elapsed between the flag and reporting often includes
// non-apnea breathing.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1ClearAirwayEvent(t - elapsed, 0));
break;
//case 0x08: // never seen
@ -3444,15 +3440,15 @@ bool PRS1DataChunk::ParseEventsF0V6(CPAPMode /*mode*/)
case 0x0b: // Hypopnea
// TODO: How is this hypopnea different from events 0xa, 0x14 and 0x15?
// TODO: What is the first byte?
pos++; // unknown first byte?
elapsed = data[pos++]; // based on sample waveform, the hypopnea is over after this
//data[pos+0]; // unknown first byte?
elapsed = data[pos+1]; // based on sample waveform, the hypopnea is over after this
this->AddEvent(new PRS1HypopneaEvent(t - elapsed, 0));
break;
case 0x0c: // Flow Limitation
// TODO: We should revisit whether this is elapsed or duration once (if)
// we start calculating flow limitations ourselves. Flow limitations aren't
// as obvious as OA/CA when looking at a waveform.
elapsed = data[pos++];
elapsed = data[pos];
this->AddEvent(new PRS1FlowLimitationEvent(t - elapsed, 0));
break;
case 0x0d: // Vibratory Snore
@ -3466,33 +3462,30 @@ bool PRS1DataChunk::ParseEventsF0V6(CPAPMode /*mode*/)
case 0x0e: // ???
// 5 bytes like PB and LL, but what is it?
duration = 2 * (data[pos] | (data[pos+1] << 8)); // this looks like a 16-bit value, so may be duration like PB?
pos += 2;
elapsed = data[pos++]; // this is always 60 seconds unless it's at the end, so it seems like elapsed
elapsed = data[pos+2]; // this is always 60 seconds unless it's at the end, so it seems like elapsed
CHECK_VALUES(elapsed, 60, 0);
//this->AddEvent(new PRS1PeriodicBreathingEvent(t - elapsed - duration, duration));
break;
case 0x0f: // Periodic Breathing
// PB events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1PeriodicBreathingEvent(t - elapsed - duration, duration));
break;
case 0x10: // Large Leak
// LL events are reported some time after they conclude, and they do have a reported duration.
duration = 2 * (data[pos] | (data[pos+1] << 8));
pos += 2;
elapsed = data[pos++];
elapsed = data[pos+2];
this->AddEvent(new PRS1LargeLeakEvent(t - elapsed - duration, duration));
break;
case 0x11: // Statistics
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos++]));
this->AddEvent(new PRS1SnoreEvent(t, data[pos++]));
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos]));
this->AddEvent(new PRS1SnoreEvent(t, data[pos+1]));
// Average pressure: this reads lower than the current CPAP set point when
// a flex mode is on, and exactly the current CPAP set point when off. For
// bi-level it's presumably an average of the actual pressures.
// TODO: What to do with this average pressure? Actual pressure adjustments are handled above.
//this->AddEvent(new PRS1EPAPEvent(t, data[pos++]));
//this->AddEvent(new PRS1EPAPEvent(t, data[pos+2]));
break;
case 0x12: // Snore count per pressure
// Some sessions (with lots of ramps) have multiple of these, each with a
@ -3516,7 +3509,7 @@ bool PRS1DataChunk::ParseEventsF0V6(CPAPMode /*mode*/)
// TODO: We should revisit whether this is elapsed or duration once (if)
// we start calculating hypopneas ourselves. Their official definition
// is 40% reduction in flow lasting at least 10s.
duration = data[pos++];
duration = data[pos];
this->AddEvent(new PRS1HypopneaEvent(t - duration, 0));
break;
default: