mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-06 19:20:45 +00:00
Clean up ParseEventsF5V2 switch statement based on sample data.
This is very incomplete since we currently have only limited sample data for F5V2. The events that have been verified will parse correctly, and the rest will result in a parsing error. There are some very strange changes in the event numbers compared to F5V1 and F5V3, it's unclear why. Note that F5V2 uses a gain of 0.125 like F5V3 instead of 0.1 like F5V1.
This commit is contained in:
parent
1946be162c
commit
a8df58b1ef
@ -1853,7 +1853,7 @@ bool PRS1DataChunk::ParseEventsF5V3(void)
|
||||
switch (code) {
|
||||
case 1: // Pressure adjustment
|
||||
this->AddEvent(new PRS1EPAPSetEvent(t, data[pos++], GAIN));
|
||||
this->AddEvent(new PRS1UnknownDataEvent(m_data, startpos-1, size+1));
|
||||
this->AddEvent(new PRS1UnknownDataEvent(m_data, startpos-1, size+1)); // TODO: what is this?
|
||||
break;
|
||||
case 2: // Timed Breath
|
||||
// TB events have a duration in 0.1s, based on the review of pressure waveforms.
|
||||
@ -2414,7 +2414,7 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
}
|
||||
const unsigned char * data = (unsigned char *)this->m_data.constData();
|
||||
int chunk_size = this->m_data.size();
|
||||
static const QMap<int,int> event_sizes = { {0,4}, {1,2}, {3,4}, {8,4}, {9,4}, {0xa,2}, {0xb,5}, {0xc,5}, {0xd,5}, {0xe,0xd}, {0xf,5}, {0x10,5}, {0x11,2}, {0x12,6} };
|
||||
static const QMap<int,int> event_sizes = { {0,4}, {1,2}, {3,4}, {8,3}, {9,4}, {0xa,3}, {0xb,5}, {0xc,5}, {0xd,5}, {0xe,0xd}, {0xf,5}, {0x10,5}, {0x11,2}, {0x12,6} };
|
||||
|
||||
if (chunk_size < 1) {
|
||||
// This does occasionally happen in F0V6.
|
||||
@ -2422,12 +2422,13 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// F5V3 uses a gain of 0.125 rather than 0.1 to allow for a maximum value of 30 cmH2O
|
||||
static const float GAIN = 0.125; // TODO: this should be parameterized somewhere more logical
|
||||
bool ok = true;
|
||||
int pos = 0, startpos;
|
||||
int code, size;
|
||||
int t = 0;
|
||||
EventDataType data0, data1;
|
||||
//int elapsed, duration, value;
|
||||
int elapsed/*, duration, value*/;
|
||||
do {
|
||||
code = data[pos++];
|
||||
|
||||
@ -2449,7 +2450,9 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
/*
|
||||
case 0x00: // Unknown (ASV Pressure value)
|
||||
DUMP_EVENT();
|
||||
// offset?
|
||||
data0 = data[pos++];
|
||||
|
||||
@ -2465,17 +2468,16 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
break;
|
||||
|
||||
case 0x01: // Unknown
|
||||
DUMP_EVENT();
|
||||
this->AddEvent(new PRS1UnknownValueEvent(code, t, 0, 0.1F));
|
||||
break;
|
||||
|
||||
case 0x02: // Pressure ???
|
||||
data0 = data[pos++];
|
||||
// if (!Code[2]) {
|
||||
// if (!(Code[2]=session->AddEventList(cpapcode,EVL_Event,0.1))) return false;
|
||||
// }
|
||||
// Code[2]->AddEvent(t,data0);
|
||||
break;
|
||||
*/
|
||||
case 0x02: // Pressure adjustment
|
||||
this->AddEvent(new PRS1EPAPSetEvent(t, data[pos++], GAIN));
|
||||
break;
|
||||
/*
|
||||
case 0x03: // BIPAP Pressure
|
||||
DUMP_EVENT();
|
||||
qDebug() << "0x03 Observed in ASV data!!????";
|
||||
|
||||
data0 = data[pos++];
|
||||
@ -2485,75 +2487,69 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
// session->AddEvent(new Event(t,CPAP_EAP, 0, data, 1));
|
||||
// session->AddEvent(new Event(t,CPAP_IAP, 0, &data1, 1));
|
||||
break;
|
||||
|
||||
case 0x04: // Timed Breath
|
||||
data0 = data[pos++];
|
||||
|
||||
this->AddEvent(new PRS1TimedBreathEvent(t, data0));
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
//code=CPAP_Obstructive;
|
||||
data0 = data[pos++];
|
||||
this->AddEvent(new PRS1ObstructiveApneaEvent(t - data0, data0));
|
||||
break;
|
||||
|
||||
*/
|
||||
case 0x04: // Timed Breath
|
||||
// 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];
|
||||
this->AddEvent(new PRS1TimedBreathEvent(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];
|
||||
this->AddEvent(new PRS1ObstructiveApneaEvent(t - elapsed, 0));
|
||||
break;
|
||||
/*
|
||||
case 0x06:
|
||||
DUMP_EVENT();
|
||||
//code=CPAP_ClearAirway;
|
||||
data0 = data[pos++];
|
||||
this->AddEvent(new PRS1ClearAirwayEvent(t - data0, data0));
|
||||
break;
|
||||
*/
|
||||
|
||||
case 0x07:
|
||||
//code=CPAP_Hypopnea;
|
||||
data0 = data[pos++];
|
||||
this->AddEvent(new PRS1HypopneaEvent(t - data0, data0));
|
||||
break;
|
||||
|
||||
case 0x08: // ???
|
||||
// This was breaking parsing for F5V1 prior to using fixed lengths.
|
||||
// That means it's probably very wrong.
|
||||
data0 = data[pos++];
|
||||
//qDebug() << "Code 8 found at " << hex << pos - 1 << " " << tt;
|
||||
|
||||
//if (this->familyVersion>=2) {
|
||||
this->AddEvent(new PRS1HypopneaEvent(t - data0, data0));
|
||||
/*
|
||||
} else {
|
||||
this->AddEvent(new PRS1UnknownValueEvent(code, t - data0, data0));
|
||||
//????
|
||||
//data1=data[pos++]; // ???
|
||||
//pos++;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
case 0x07: // Hypopnea
|
||||
// NOTE: No additional (unknown) first byte as in F5V3 0x07, but see below.
|
||||
// This seems closer to F5V3 0x0d or 0x0e.
|
||||
// What's different about this an 0x08? This was seen in a PB at least once?
|
||||
elapsed = data[pos]; // based on sample waveform, the hypopnea is over after this
|
||||
this->AddEvent(new PRS1HypopneaEvent(t - elapsed, 0));
|
||||
break;
|
||||
case 0x08: // Hypopnea, note this is 0x7 in F5V1
|
||||
// TODO: How is this hypopnea different from event 0x9 and 0x7?
|
||||
// NOTE: No additional (unknown) first byte as in F5V3 0x7, but see below.
|
||||
// This seems closer to F5V3 0x0d or 0x0e.
|
||||
elapsed = data[pos]; // based on sample waveform, the hypopnea is over after this
|
||||
this->AddEvent(new PRS1HypopneaEvent(t - elapsed, 0));
|
||||
break;
|
||||
/*
|
||||
case 0x09: // ASV Codes
|
||||
/*
|
||||
DUMP_EVENT();
|
||||
/ *
|
||||
if (this->familyVersion<2) {
|
||||
//code=CPAP_FlowLimit;
|
||||
data0 = data[pos++];
|
||||
|
||||
this->AddEvent(new PRS1FlowLimitationEvent(t - data0, data0));
|
||||
} else {
|
||||
*/
|
||||
* /
|
||||
data0 = data[pos++];
|
||||
data1 = data[pos++];
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
data0 = data[pos++];
|
||||
//if (this->familyVersion>=2) {
|
||||
this->AddEvent(new PRS1FlowLimitationEvent(t - data0, data0));
|
||||
/*
|
||||
} else {
|
||||
this->AddEvent(new PRS1UnknownValueEvent(code, t - data0, data0));
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
|
||||
*/
|
||||
case 0x0a: // Flow Limitation, note this is 0x9 in F5V1 and 0x8 in F5V3
|
||||
// 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];
|
||||
this->AddEvent(new PRS1FlowLimitationEvent(t - elapsed, 0));
|
||||
break;
|
||||
/*
|
||||
case 0x0b: // Cheyne Stokes
|
||||
DUMP_EVENT();
|
||||
data0 = ((unsigned char *)data)[pos + 1] << 8 | ((unsigned char *)data)[pos];
|
||||
//data0*=2;
|
||||
pos += 2;
|
||||
@ -2562,82 +2558,41 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
//tt-=delta;
|
||||
this->AddEvent(new PRS1PeriodicBreathingEvent(t - data1, data0));
|
||||
break;
|
||||
*/
|
||||
case 0x0c: // Periodic Breathing, note this is 0xb in F5V1 and 0xa in F5V3
|
||||
// PB events are reported some time after they conclude, and they do have a reported duration.
|
||||
duration = 2 * (data[pos] | (data[pos+1] << 8)); // confirmed to double in F5V0
|
||||
elapsed = data[pos+2];
|
||||
this->AddEvent(new PRS1PeriodicBreathingEvent(t - elapsed - duration, duration));
|
||||
break;
|
||||
/*
|
||||
case 0x0d:
|
||||
DUMP_EVENT();
|
||||
|
||||
case 0x0c:
|
||||
|
||||
//if (this->familyVersion>=2) {
|
||||
data0 = (data[pos + 1] << 8 | data[pos]);
|
||||
data0 *= 2;
|
||||
pos += 2;
|
||||
data1 = data[pos++];
|
||||
this->AddEvent(new PRS1PeriodicBreathingEvent(t - data1, data0));
|
||||
/*
|
||||
} else {
|
||||
data0 = data[pos++];
|
||||
qDebug() << "Code 12 found at " << hex << pos - 1 << " " << t - data0;
|
||||
|
||||
this->AddEvent(new PRS1UnknownValueEvent(code, t - data0, data0));
|
||||
pos += 2;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
case 0x0d: // All the other ASV graph stuff.
|
||||
|
||||
//if (this->familyVersion>=2) {
|
||||
data0 = (data[pos + 1] << 8 | data[pos]);
|
||||
data0 *= 2;
|
||||
pos += 2;
|
||||
data1 = data[pos++];
|
||||
//tt = t - qint64(data1) * 1000L;
|
||||
/*
|
||||
} else {
|
||||
this->AddEvent(new PRS1IPAPAverageEvent(t, data[pos++])); // 00=IAP
|
||||
data4 = data[pos++];
|
||||
this->AddEvent(new PRS1IPAPLowEvent(t, data4)); // 01=IAP Low
|
||||
data5 = data[pos++];
|
||||
this->AddEvent(new PRS1IPAPHighEvent(t, data5)); // 02=IAP High
|
||||
|
||||
this->AddEvent(new PRS1TotalLeakEvent(t, data[pos++])); // 03=LEAK
|
||||
|
||||
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos++])); // 04=Breaths Per Minute
|
||||
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos++])); // 05=Patient Triggered Breaths
|
||||
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos++])); // 06=Minute Ventilation
|
||||
//tmp=data[pos++] * 10.0;
|
||||
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos++])); // 07=Tidal Volume
|
||||
this->AddEvent(new PRS1SnoreEvent(t, data[pos++])); // 08=Snore
|
||||
this->AddEvent(new PRS1EPAPAverageEvent(t, data1 = data[pos++])); // 09=EPAP
|
||||
if (this->familyVersion >= 1) {
|
||||
data0 = data[pos++];
|
||||
}
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
case 0x0e: // Unknown
|
||||
// Family 5.2 has this code
|
||||
//if (this->familyVersion>=2) {
|
||||
this->AddEvent(new PRS1IPAPAverageEvent(t, data1=data[pos+0])); // 0
|
||||
this->AddEvent(new PRS1IPAPLowEvent(t, data[pos+1])); // 1
|
||||
this->AddEvent(new PRS1IPAPHighEvent(t, data[pos+2])); // 2
|
||||
this->AddEvent(new PRS1LeakEvent(t, data[pos+3])); // 3 // F5V2, is this really unintentional leak rather than total leak?
|
||||
this->AddEvent(new PRS1TidalVolumeEvent(t, data[pos+7])); // 7
|
||||
this->AddEvent(new PRS1RespiratoryRateEvent(t, data[pos+4])); // 4
|
||||
this->AddEvent(new PRS1PatientTriggeredBreathsEvent(t, data[pos+5])); // 5
|
||||
this->AddEvent(new PRS1MinuteVentilationEvent(t, data[pos+6])); //6
|
||||
this->AddEvent(new PRS1SnoreEvent(t, data[pos+8])); //??
|
||||
this->AddEvent(new PRS1EPAPAverageEvent(t, data[pos+9])); // 9
|
||||
pos+=11;
|
||||
/*
|
||||
} else {
|
||||
qDebug() << "0x0E Observed in ASV data!!????";
|
||||
data0 = data[pos++]; // << 8) | data[pos];
|
||||
|
||||
}
|
||||
//session->AddEvent(new Event(t,cpapcode, 0, data, 1));
|
||||
*/
|
||||
break;
|
||||
*/
|
||||
case 0x0e: // Statistics, note this was 0x0d in F5V0 and F5V1
|
||||
// These appear every 2 minutes, so presumably summarize the preceding period.
|
||||
this->AddEvent(new PRS1IPAPAverageEvent(t, data[pos+0], GAIN)); // 00=IPAP
|
||||
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 PRS1EPAPAverageEvent(t, data[pos+9], GAIN)); // 09=EPAP average
|
||||
this->AddEvent(new PRS1LeakEvent(t, data[pos+0xa])); // 0A=Leak (average?) new to F5V1 (originally found in F5V3)
|
||||
break;
|
||||
/*
|
||||
case 0x0f:
|
||||
DUMP_EVENT();
|
||||
qDebug() << "0x0f Observed in ASV data!!????";
|
||||
|
||||
data0 = data[pos + 1] << 8 | data[pos];
|
||||
@ -2649,6 +2604,7 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
break;
|
||||
|
||||
case 0x10: // Unknown
|
||||
DUMP_EVENT();
|
||||
data0 = data[pos + 1] << 8 | data[pos];
|
||||
pos += 2;
|
||||
data1 = data[pos++];
|
||||
@ -2662,6 +2618,7 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
//session->AddEvent(new Event(t,cpapcode, 0, data, 3));
|
||||
break;
|
||||
case 0x11: // Not Leak Rate
|
||||
DUMP_EVENT();
|
||||
qDebug() << "0x11 Observed in ASV data!!????";
|
||||
//if (!Code[24]) {
|
||||
// Code[24]=new EventList(cpapcode,EVL_Event);
|
||||
@ -2671,6 +2628,7 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
|
||||
|
||||
case 0x12: // Summary
|
||||
DUMP_EVENT();
|
||||
qDebug() << "0x12 Observed in ASV data!!????";
|
||||
data0 = data[pos++];
|
||||
data1 = data[pos++];
|
||||
@ -2678,7 +2636,7 @@ bool PRS1DataChunk::ParseEventsF5V2(void)
|
||||
pos += 2;
|
||||
//session->AddEvent(new Event(t,cpapcode, 0, data,3));
|
||||
break;
|
||||
|
||||
*/
|
||||
default:
|
||||
DUMP_EVENT();
|
||||
UNEXPECTED_VALUE(code, "known event code");
|
||||
|
Loading…
Reference in New Issue
Block a user