From a96a6659876cc01f470b248ce835552c853f032a Mon Sep 17 00:00:00 2001 From: sawinglogz <3787776-sawinglogz@users.noreply.gitlab.com> Date: Thu, 26 Mar 2020 09:01:28 -0400 Subject: [PATCH] Rename PRS1_0E mystery channel to Variable Breathing based on forum discussion, disable it by default. Also make TB an on-demand channel. --- oscar/SleepLib/loader_plugins/prs1_loader.cpp | 70 ++++++++----------- oscar/SleepLib/machine_common.cpp | 2 +- oscar/SleepLib/machine_common.h | 2 +- oscar/tests/sessiontests.cpp | 3 +- 4 files changed, 35 insertions(+), 42 deletions(-) diff --git a/oscar/SleepLib/loader_plugins/prs1_loader.cpp b/oscar/SleepLib/loader_plugins/prs1_loader.cpp index 53171e7b..bedcda30 100644 --- a/oscar/SleepLib/loader_plugins/prs1_loader.cpp +++ b/oscar/SleepLib/loader_plugins/prs1_loader.cpp @@ -229,6 +229,7 @@ ChannelID PRS1_TimedBreath = 0, PRS1_HumidMode = 0, PRS1_TubeTemp = 0; ChannelID PRS1_FlexLock = 0, PRS1_TubeLock = 0, PRS1_RampType = 0; ChannelID PRS1_BackupBreathMode = 0, PRS1_BackupBreathRate = 0, PRS1_BackupBreathTi = 0; ChannelID PRS1_AutoTrial = 0, PRS1_EZStart = 0, PRS1_RiseTime = 0, PRS1_RiseTimeLock = 0; +ChannelID PRS1_VariableBreathing = 0; // TODO: UNCONFIRMED, but seems to match sample data QString PRS1Loader::PresReliefLabel() { return QObject::tr(""); } ChannelID PRS1Loader::PresReliefMode() { return PRS1_FlexMode; } @@ -1127,7 +1128,7 @@ enum PRS1ParsedEventType EV_PRS1_FL, EV_PRS1_PB, EV_PRS1_LL, - EV_PRS1_UNK_DURATION, // unknown duration event, rename once we figure it out + EV_PRS1_VB, // UNCONFIRMED EV_PRS1_HY, EV_PRS1_OA_COUNT, // F3V3 only EV_PRS1_CA_COUNT, // F3V3 only @@ -1530,7 +1531,7 @@ PRS1_DURATION_EVENT(PRS1ClearAirwayEvent, EV_PRS1_CA); PRS1_DURATION_EVENT(PRS1FlowLimitationEvent, EV_PRS1_FL); PRS1_DURATION_EVENT(PRS1PeriodicBreathingEvent, EV_PRS1_PB); PRS1_DURATION_EVENT(PRS1LargeLeakEvent, EV_PRS1_LL); -PRS1_DURATION_EVENT(PRS1UnknownDurationEvent, EV_PRS1_UNK_DURATION); +PRS1_DURATION_EVENT(PRS1VariableBreathingEvent, EV_PRS1_VB); PRS1_DURATION_EVENT(PRS1HypopneaEvent, EV_PRS1_HY); PRS1_VALUE_EVENT(PRS1TotalLeakEvent, EV_PRS1_TOTLEAK); @@ -1589,7 +1590,7 @@ const QVector & GetSupportedEvents(const PRS1DataChunk* chu // they're reported/supported by the parser. static const QVector PRS1OnDemandChannels = { - //PRS1TimedBreathEvent::TYPE, // TODO: TB could be on-demand + PRS1TimedBreathEvent::TYPE, PRS1PressurePulseEvent::TYPE, // Pressure initialized on-demand for F0 due to the possibility of bilevel vs. single pressure. @@ -1655,7 +1656,7 @@ static const QHash> PRS1ImportChannelMap { PRS1ApneaAlarmEvent::TYPE, { /* Not imported */ } }, { PRS1SnoresAtPressureEvent::TYPE, { /* Not imported */ } }, { PRS1AutoPressureSetEvent::TYPE, { /* Not imported */ } }, - { PRS1UnknownDurationEvent::TYPE, { &PRS1_0E } }, + { PRS1VariableBreathingEvent::TYPE, { &PRS1_VariableBreathing } }, // UNCONFIRMED { PRS1HypopneaCount::TYPE, { &CPAP_Hypopnea } }, // F3V3 only, generates individual events on import { PRS1ObstructiveApneaCount::TYPE, { &CPAP_Obstructive } }, // F3V3 only, generates individual events on import @@ -1682,7 +1683,7 @@ static QString parsedEventTypeName(PRS1ParsedEventType t) ENUMSTRING(EV_PRS1_FL); ENUMSTRING(EV_PRS1_PB); ENUMSTRING(EV_PRS1_LL); - ENUMSTRING(EV_PRS1_UNK_DURATION); + ENUMSTRING(EV_PRS1_VB); ENUMSTRING(EV_PRS1_HY); ENUMSTRING(EV_PRS1_OA_COUNT); ENUMSTRING(EV_PRS1_CA_COUNT); @@ -2897,15 +2898,15 @@ bool PRS1Import::ImportEventChunk(PRS1DataChunk* event) continue; } - // Skip zero-length PB or LL (or unknown duration 0E) events - if ((e->m_type == PRS1PeriodicBreathingEvent::TYPE || e->m_type == PRS1LargeLeakEvent::TYPE || e->m_type == PRS1UnknownDurationEvent::TYPE) && + // Skip zero-length PB or LL or VB events + if ((e->m_type == PRS1PeriodicBreathingEvent::TYPE || e->m_type == PRS1LargeLeakEvent::TYPE || e->m_type == PRS1VariableBreathingEvent::TYPE) && (e->m_duration == 0)) { // LL occasionally appear about a minute before a new mask-on slice // begins, when the previous mask-on slice ended with a large leak. // This probably indicates the end of LL and beginning // of breath detection, but we don't get any real data until mask-on. // - // It has also happened once in a similar scenario for PB and 0E, even when + // It has also happened once in a similar scenario for PB and VB, even when // the two mask-on slices are in different sessions! continue; } @@ -2947,9 +2948,9 @@ bool PRS1Import::ImportEventChunk(PRS1DataChunk* event) // Sanity check: warn if a (non-slice) event is earlier than the current mask-on slice if (t < (*m_currentSlice).start && (*m_currentSlice).status == MaskOn) { if (!PRS1NonSliceChannels.contains(e->m_type)) { - // LL and PRS1_0E at the beginning of a mask-on session sometimes start 1 second early, + // LL and VB at the beginning of a mask-on session sometimes start 1 second early, // so suppress that warning. - if ((*m_currentSlice).start - t > 1000 || (e->m_type != PRS1LargeLeakEvent::TYPE && e->m_type != PRS1UnknownDurationEvent::TYPE)) { + if ((*m_currentSlice).start - t > 1000 || (e->m_type != PRS1LargeLeakEvent::TYPE && e->m_type != PRS1VariableBreathingEvent::TYPE)) { qWarning() << sessionid << "Event" << e->m_type << "before mask-on slice:" << ts(t); } } @@ -3097,7 +3098,7 @@ void PRS1Import::ImportEvent(qint64 t, PRS1ParsedEvent* e) case PRS1PeriodicBreathingEvent::TYPE: case PRS1LargeLeakEvent::TYPE: - case PRS1UnknownDurationEvent::TYPE: + case PRS1VariableBreathingEvent::TYPE: // TODO: The graphs silently treat the timestamp of a span as an end time rather than start (see gFlagsLine::paint). // Decide whether to preserve that behavior or change it universally and update either this code or comment. duration = e->m_duration * 1000L; @@ -3497,7 +3498,7 @@ static const QVector ParsedEventsF0V23 = { PRS1HypopneaEvent::TYPE, PRS1FlowLimitationEvent::TYPE, PRS1VibratorySnoreEvent::TYPE, - PRS1UnknownDurationEvent::TYPE, + PRS1VariableBreathingEvent::TYPE, PRS1PeriodicBreathingEvent::TYPE, PRS1LargeLeakEvent::TYPE, PRS1TotalLeakEvent::TYPE, @@ -3621,13 +3622,12 @@ bool PRS1DataChunk::ParseEventsF0V23() // no data bytes this->AddEvent(new PRS1VibratorySnoreEvent(t, 0)); break; - case 0x0e: // ??? - // 5 bytes like PB and LL, but what is it? + case 0x0e: // Variable Breathing? // TODO: does duration double like F0V4? - duration = (data[pos] | (data[pos+1] << 8)); // this looks like a 16-bit value, so may be duration like PB? + duration = (data[pos] | (data[pos+1] << 8)); 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 PRS1UnknownDurationEvent(t - elapsed - duration, duration)); + this->AddEvent(new PRS1VariableBreathingEvent(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. @@ -3697,7 +3697,7 @@ static const QVector ParsedEventsF0V4 = { PRS1HypopneaEvent::TYPE, PRS1FlowLimitationEvent::TYPE, PRS1VibratorySnoreEvent::TYPE, - PRS1UnknownDurationEvent::TYPE, + PRS1VariableBreathingEvent::TYPE, PRS1PeriodicBreathingEvent::TYPE, PRS1LargeLeakEvent::TYPE, PRS1TotalLeakEvent::TYPE, @@ -3822,13 +3822,12 @@ bool PRS1DataChunk::ParseEventsF0V4() // no data bytes this->AddEvent(new PRS1VibratorySnoreEvent(t, 0)); break; - case 0x0e: // ??? - // 5 bytes like PB and LL, but what is it? + case 0x0e: // Variable Breathing? // TODO: does duration double like it does for PB/LL? - duration = 2 * (data[pos] | (data[pos+1] << 8)); // this looks like a 16-bit value, so may be duration like PB? + duration = 2 * (data[pos] | (data[pos+1] << 8)); 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 PRS1UnknownDurationEvent(t - elapsed - duration, duration)); + this->AddEvent(new PRS1VariableBreathingEvent(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. @@ -3907,7 +3906,7 @@ static const QVector ParsedEventsF0V6 = { PRS1HypopneaEvent::TYPE, PRS1FlowLimitationEvent::TYPE, PRS1VibratorySnoreEvent::TYPE, - PRS1UnknownDurationEvent::TYPE, + PRS1VariableBreathingEvent::TYPE, PRS1PeriodicBreathingEvent::TYPE, PRS1LargeLeakEvent::TYPE, PRS1TotalLeakEvent::TYPE, @@ -4046,12 +4045,11 @@ bool PRS1DataChunk::ParseEventsF0V6() // no data bytes this->AddEvent(new PRS1VibratorySnoreEvent(t, 0)); break; - 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? + case 0x0e: // Variable Breathing? + duration = 2 * (data[pos] | (data[pos+1] << 8)); 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 PRS1UnknownDurationEvent(t - elapsed - duration, duration)); + this->AddEvent(new PRS1VariableBreathingEvent(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. @@ -8945,21 +8943,15 @@ void PRS1Loader::initChannels() chan->addOption(0, STR_TR_Off); chan->addOption(1, STR_TR_On); - // TODO: is the below useful? -// -// - - channel.add(GRP_CPAP, new Channel(PRS1_0E = 0x1157, SPAN, MT_CPAP, SESSION, - "PRS1_UNK", - QObject::tr("PRS1 Unknown"), - QObject::tr("Unknown PRS1 span 0x0E"), - "??", + channel.add(GRP_CPAP, chan = new Channel(PRS1_VariableBreathing = 0x1156, SPAN, MT_CPAP, SESSION, + "PRS1_VariableBreathing", + QObject::tr("Variable Breathing"), + QObject::tr("UNCONFIRMED: Possibly variable breathing, which are periods of high deviation from the peak inspiratory flow trend"), + "VB", STR_UNIT_Seconds, DEFAULT, QColor("#ffe8f0"))); + chan->setEnabled(false); // disable by default + channel.add(GRP_CPAP, new Channel(PRS1_BND = 0x1159, SPAN, MT_CPAP, SESSION, "PRS1_BND", QObject::tr("Breathing Not Detected"), diff --git a/oscar/SleepLib/machine_common.cpp b/oscar/SleepLib/machine_common.cpp index ecc1b561..65da71ff 100644 --- a/oscar/SleepLib/machine_common.cpp +++ b/oscar/SleepLib/machine_common.cpp @@ -30,7 +30,7 @@ ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAP ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime; ChannelID INTELLIPAP_Unknown1, INTELLIPAP_Unknown2; -ChannelID PRS1_0E, CPAP_LargeLeak, +ChannelID CPAP_LargeLeak, PRS1_BND, PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, PRS1_MaskResistLock, PRS1_MaskResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI; diff --git a/oscar/SleepLib/machine_common.h b/oscar/SleepLib/machine_common.h index c2c46883..8176fb1a 100644 --- a/oscar/SleepLib/machine_common.h +++ b/oscar/SleepLib/machine_common.h @@ -157,7 +157,7 @@ extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CP CPAP_PressureSet, CPAP_IPAPSet, CPAP_EPAPSet; extern ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime; -extern ChannelID PRS1_0E, CPAP_LargeLeak, PRS1_BND, +extern ChannelID CPAP_LargeLeak, PRS1_BND, PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, CPAP_HumidSetting, PRS1_MaskResistLock, PRS1_MaskResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI; diff --git a/oscar/tests/sessiontests.cpp b/oscar/tests/sessiontests.cpp index beaa7887..0e07540c 100644 --- a/oscar/tests/sessiontests.cpp +++ b/oscar/tests/sessiontests.cpp @@ -58,6 +58,7 @@ extern ChannelID PRS1_TimedBreath, PRS1_HumidMode, PRS1_TubeTemp; extern ChannelID PRS1_FlexLock, PRS1_TubeLock, PRS1_RampType; extern ChannelID PRS1_BackupBreathMode, PRS1_BackupBreathRate, PRS1_BackupBreathTi; extern ChannelID PRS1_AutoTrial, PRS1_EZStart, PRS1_RiseTime, PRS1_RiseTimeLock; +extern ChannelID PRS1_VariableBreathing; extern ChannelID RMS9_EPR, RMS9_EPRLevel, RMS9_Mode, RMS9_SmartStart, RMS9_HumidStatus, RMS9_HumidLevel, RMS9_PtAccess, RMS9_Mask, RMS9_ABFilter, RMS9_ClimateControl, RMS9_TubeType, @@ -176,7 +177,7 @@ static QString eventChannel(ChannelID i) CHANNELNAME(CPAP_Test2); CHANNELNAME(CPAP_PressurePulse); CHANNELNAME(CPAP_Pressure); - CHANNELNAME(PRS1_0E); + CHANNELNAME(PRS1_VariableBreathing); CHANNELNAME(CPAP_PressureSet); CHANNELNAME(CPAP_IPAPSet); CHANNELNAME(CPAP_EPAPSet);