mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-05 10:40:42 +00:00
First pass at PRS1 200X humidifier settings.
Some of the values still aren't known, and OSCAR doesn't yet define a channel for heated tube temperature.
This commit is contained in:
parent
250566f3f2
commit
2ace7d3a6d
@ -3293,7 +3293,7 @@ bool PRS1DataChunk::ParseComplianceF0V23(void)
|
||||
this->ParseFlexSetting(flex, MODE_CPAP);
|
||||
|
||||
int humid = data[0x09]; // TODO: why was this 0x0A originally? could the position vary?
|
||||
this->ParseHumidifierSetting(humid, false);
|
||||
this->ParseHumidifierSettingV2(humid, false);
|
||||
|
||||
// TODO: Where is Auto Off/On set? (both off)
|
||||
// TODO: Where is "Altitude Compensation" set? (seems to be 1)
|
||||
@ -3437,7 +3437,7 @@ bool PRS1DataChunk::ParseSummaryF0V23()
|
||||
this->ParseFlexSetting(flex, cpapmode);
|
||||
|
||||
int humid = data[0x09];
|
||||
this->ParseHumidifierSetting(humid, false);
|
||||
this->ParseHumidifierSettingV2(humid, false);
|
||||
|
||||
// Tubing lock has no setting byte
|
||||
|
||||
@ -3572,7 +3572,7 @@ bool PRS1DataChunk::ParseSummaryF0V4(void)
|
||||
this->AddEvent(new PRS1PressureSettingEvent(PRS1_SETTING_RAMP_PRESSURE, ramp_pressure));
|
||||
|
||||
int humid = data[0x0b];
|
||||
this->ParseHumidifierSetting(humid);
|
||||
this->ParseHumidifierSettingV2(humid);
|
||||
|
||||
this->duration = data[0x14] | data[0x15] << 8;
|
||||
|
||||
@ -3658,7 +3658,7 @@ bool PRS1DataChunk::ParseSummaryF5V012(void)
|
||||
this->AddEvent(new PRS1PressureSettingEvent(PRS1_SETTING_RAMP_PRESSURE, ramp_pressure));
|
||||
|
||||
int humid = data[0x0d];
|
||||
this->ParseHumidifierSetting(humid);
|
||||
this->ParseHumidifierSettingV2(humid);
|
||||
|
||||
this->duration = data[0x18] | data[0x19] << 8;
|
||||
|
||||
@ -3705,7 +3705,7 @@ void PRS1DataChunk::ParseFlexSetting(quint8 flex, CPAPMode cpapmode)
|
||||
}
|
||||
|
||||
|
||||
void PRS1DataChunk::ParseHumidifierSetting(int humid, bool supportsHeatedTubing)
|
||||
void PRS1DataChunk::ParseHumidifierSettingV2(int humid, bool supportsHeatedTubing)
|
||||
{
|
||||
if (humid & (0x40 | 0x08)) UNEXPECTED_VALUE(humid, "known bits");
|
||||
|
||||
@ -3818,8 +3818,7 @@ bool PRS1DataChunk::ParseComplianceF0V6(void)
|
||||
case 3: // Mask On
|
||||
tt += data[pos] | (data[pos+1] << 8);
|
||||
this->AddEvent(new PRS1ParsedSliceEvent(tt, MaskOn));
|
||||
//CHECK_VALUES(data[pos+2], 0x50, 0x54); // 0x90 (no humidifier data), 0x50 (15ht, tube 4/5, humid 4), 0x54 (15ht, tube 5, humid 5) 0x4c (15ht, tube temp 3, humidifier 3)
|
||||
//CHECK_VALUES(data[pos+3], 0x80, 0xb0); // 0xB4 (15ht, tube 5, humid 5), 0xB0 (15ht, tube 5, humid 4), 0x90 (tube 4, humid 4), 0x6C (15ht, tube temp 3, humidifier 3)
|
||||
this->ParseHumidifierSettingF0V6(data[pos+2], data[pos+3]);
|
||||
break;
|
||||
case 4: // Mask Off
|
||||
tt += data[pos] | (data[pos+1] << 8);
|
||||
@ -3849,8 +3848,7 @@ bool PRS1DataChunk::ParseComplianceF0V6(void)
|
||||
break;
|
||||
case 6: // Humidier setting change
|
||||
tt += data[pos] | (data[pos+1] << 8); // This adds to the total duration (otherwise it won't match report)
|
||||
//CHECK_VALUES(data[pos+2], 0x54); // when changing from tube 4, humid 4 to tube 5, humid 5
|
||||
//CHECK_VALUES(data[pos+3], 0xb4); // when changing from tube 4, humid 4 to tube 5, humid 5
|
||||
this->ParseHumidifierSettingF0V6(data[pos+2], data[pos+3]);
|
||||
break;
|
||||
default:
|
||||
UNEXPECTED_VALUE(code, "known slice code");
|
||||
@ -3865,6 +3863,46 @@ bool PRS1DataChunk::ParseComplianceF0V6(void)
|
||||
}
|
||||
|
||||
|
||||
void PRS1DataChunk::ParseHumidifierSettingF0V6(unsigned char byte1, unsigned char byte2, bool add_setting)
|
||||
{
|
||||
// Byte 1: 0x90 (no humidifier data), 0x50 (15ht, tube 4/5, humid 4), 0x54 (15ht, tube 5, humid 5) 0x4c (15ht, tube temp 3, humidifier 3)
|
||||
// 0b10010000 no humidifier data
|
||||
// 0b01010000 tube 4 and 5, humidifier 4
|
||||
// 0b01010100 15ht, tube 5, humidifier 5
|
||||
// 0b01001100 15ht, tube 3, humidifier 3
|
||||
// xxx = humidifier setting
|
||||
// ??? ??
|
||||
CHECK_VALUE(byte1 & 3, 0);
|
||||
int unknown = byte1 >> 5;
|
||||
if (unknown != 1 && unknown != 2 && unknown != 4) UNEXPECTED_VALUE(byte1 >> 5, "1, 2, or 4"); // 4 seems to mean no humidifer, 2 uses heated tube, 1 uses adaptive
|
||||
int humidlevel = (byte1 >> 2) & 7;
|
||||
if (humidlevel > 5 || humidlevel < 1) UNEXPECTED_VALUE(humidlevel, "1-5");
|
||||
|
||||
// Byte 2: 0xB4 (15ht, tube 5, humid 5), 0xB0 (15ht, tube 5, humid 4), 0x90 (tube 4, humid 4), 0x6C (15ht, tube temp 3, humidifier 3)
|
||||
// 0x80?
|
||||
// 0b10110100 15ht, tube 5, humidifier 5
|
||||
// 0b10110000 15ht, tube 5, humidifier 4
|
||||
// 0b10010000 tube 4, humidifier 4
|
||||
// 0b01101100 15ht, tube 3, humidifier 3
|
||||
// xxx = humidifier setting
|
||||
// xxx = tube setting
|
||||
// ??
|
||||
CHECK_VALUE(byte2 & 3, 0);
|
||||
CHECK_VALUE(humidlevel, ((byte2 >> 2) & 7));
|
||||
int tubelevel = (byte1 >> 5) & 7;
|
||||
if (tubelevel > 5 || tubelevel < 1) UNEXPECTED_VALUE(tubelevel, "1-5");
|
||||
|
||||
if (add_setting) {
|
||||
//this->AddEvent(new PRS1ParsedSettingEvent(PRS1_SETTING_HUMID_STATUS, (humid & 0x80) != 0)); // this is F0V23 version, doesn't match F0V6
|
||||
//this->AddEvent(new PRS1ParsedSettingEvent(PRS1_SETTING_HEATED_TUBING, (humid & 0x10) != 0)); // this is F0V23 version, doesn't match F0V6
|
||||
this->AddEvent(new PRS1ParsedSettingEvent(PRS1_SETTING_HUMID_LEVEL, humidlevel));
|
||||
|
||||
// TODO: add a channel for PRS1 heated tubing
|
||||
//this->AddEvent(new PRS1ParsedSettingEvent(PRS1_SETTING_TUBE_LEVEL, tubelevel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The below is based on a combination of the mainblock parsing for fileVersion == 3
|
||||
// in ParseSummary() and the switch statements of ParseSummaryF0V6.
|
||||
//
|
||||
@ -3968,9 +4006,8 @@ bool PRS1DataChunk::ParseSettingsF0V6(const unsigned char* data, int size)
|
||||
case 0x30:
|
||||
CHECK_VALUE(data[pos], 3); // flex level?
|
||||
break;
|
||||
case 0x35:
|
||||
// This is not duration. Value seems to line up with second pair of bytes in Mask On slice?
|
||||
//duration += ( data[pos+1] << 8 ) + data[pos+0];
|
||||
case 0x35: // Humidifier setting
|
||||
this->ParseHumidifierSettingF0V6(data[pos], data[pos+1], true);
|
||||
break;
|
||||
case 0x36:
|
||||
CHECK_VALUE(data[pos], 0);
|
||||
|
@ -161,9 +161,12 @@ public:
|
||||
//! \brief Parse a flex setting byte from a .000 or .001 containing compliance/summary data
|
||||
void ParseFlexSetting(quint8 flex, CPAPMode cpapmode);
|
||||
|
||||
//! \brief Parse an humidifier setting byte from a .000 or .001 containing compliance/summary data
|
||||
void ParseHumidifierSetting(int humid, bool supportsHeatedTubing=true);
|
||||
|
||||
//! \brief Parse an humidifier setting byte from a .000 or .001 containing compliance/summary data for fileversion 2 machines: F0V234, F5V012, and maybe others
|
||||
void ParseHumidifierSettingV2(int humid, bool supportsHeatedTubing=true);
|
||||
|
||||
//! \brief Parse an humidifier setting byte from a .000 or .001 containing compliance/summary data for family 0 CPAP/APAP family version 6 machines
|
||||
void ParseHumidifierSettingF0V6(unsigned char byte1, unsigned char byte2, bool add_setting=false);
|
||||
|
||||
//! \brief Figures out which Event Parser to call, based on machine family/version and calls it.
|
||||
bool ParseEvents(CPAPMode mode);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user