Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r844f98879b7425c207b58562e623ab960adbc357 -rb9eccdfcf1727112664b85977a16a18811b9fde7 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 844f98879b7425c207b58562e623ab960adbc357) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision b9eccdfcf1727112664b85977a16a18811b9fde7) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file PresOccl.c +* @file PresOccl.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Dara Navaei +* @date (last) 14-Oct-2021 * -* @author (original) Sean -* @date (original) 15-Jan-2020 +* @author (original) Sean +* @date (original) 15-Jan-2020 * ***************************************************************************/ @@ -24,7 +24,8 @@ #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Temperatures.h" -#include "Timers.h" +#include "Timers.h" +#include "Valves.h" /** * @addtogroup PressureOcclusion @@ -77,6 +78,13 @@ static const U32 EMPTY_SALINE_BAG_PERSISTENCE = ( 250 / TASK_GENERAL_INTERVAL ); ///< Time that saline bag looks empty before saying it is empty. #define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. + +/// Measured arterial pressure is filtered w/ 10 second moving average for pressure compensation of flow. +#define SIZE_OF_LONG_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) +/// Measured arterial pressure is filtered w/ 1 second moving average for inline pressure. +#define SIZE_OF_SHORT_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) +/// Measured venous pressure is filtered w/ 1 second moving average for inline pressure and unfiltered for occlusion detection. +#define SIZE_OF_SHORT_VEN_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States @@ -102,27 +110,42 @@ /// Interval (in ms) at which to publish pressure/occlusion data to CAN bus. static OVERRIDE_U32_T presOcclDataPublishInterval = { PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL, 0, 0 }; -static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure. +static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure. +static OVERRIDE_F32_T arterialPressureOffset = {0.0, 0.0, 0.0, 0 }; ///< Calculated arterial pressure offset. static OVERRIDE_F32_T venousPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured venous pressure. static OVERRIDE_U32_T bloodPumpOcclusion = {0, 0, 0, 0 }; ///< Measured blood pump occlusion pressure. -static OVERRIDE_U32_T dialInPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate inlet pump occlusion pressure. -static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate outlet pump occlusion pressure. +static F32 longFilteredArterialPressure; ///< Measured arterial pressure after long (10 s) filter. +static F32 shortFilteredArterialPressure; ///< Measured arterial pressure after short (1 s) filter. +static F32 shortFilteredVenousPressure; ///< Measured venous pressure after short (1 s) filter. +#ifndef DISABLE_PRESSURE_CHECKS static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. -static U32 dialInPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate inlet pump occlusion reading taken after cartridge install. -static U32 dialOutPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate outlet pump occlusion reading taken after cartridge install. +#endif static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. static U08 lastArterialPressureReadCtr; ///< Previous arterial pressure sensor read count. static U08 lastVenousPressureReadCtr; ///< Previous venous pressure sensor read count. +#ifndef DISABLE_PRESSURE_CHECKS static U08 lastBPOcclReadCtr; ///< Previous BP occlusion sensor read count. -static U08 lastDPiOcclReadCtr; ///< Previous DPi occlusion sensor read count. -static U08 lastDPoOcclReadCtr; ///< Previous DPo occlusion sensor read count. static U08 lastBPErrorCtr; ///< Previous BP error count. -static U08 lastDPIErrorCtr; ///< Previous DPi error count. -static U08 lastDPOErrorCtr; ///< Previous DPo error count. +#endif +static F32 artPressureReadingsLong[ SIZE_OF_LONG_ART_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 artPressureReadingsLongIdx = 0; ///< Index for next sample in rolling average array. +static F32 artPressureReadingsLongTotal = 0.0; ///< Rolling total - used to calc average. +static U32 artPressureReadingsLongCount = 0; ///< Number of samples in flow rolling average buffer. + +static F32 artPressureReadingsShort[ SIZE_OF_SHORT_ART_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 artPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. +static F32 artPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. +static U32 artPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. + +static F32 venPressureReadingsShort[ SIZE_OF_SHORT_VEN_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 venPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. +static F32 venPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. +static U32 venPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. + // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclContReadState( void ); @@ -132,6 +155,7 @@ static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); +static void filterInlinePressureReadings( F32 artPres, F32 venPres ); /*********************************************************************//** * @brief @@ -143,56 +167,49 @@ void initPresOccl( void ) { // Initialize persistent pressure alarms - initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_LOW, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_LOW, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_HIGH, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_HIGH, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_SENSOR_TEMP_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPI_OCCLUSON_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPO_OCCLUSION_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); lastArterialPressureReadCtr = 0; lastVenousPressureReadCtr = 0; +#ifndef DISABLE_PRESSURE_CHECKS lastBPOcclReadCtr = 0; - lastDPiOcclReadCtr = 0; - lastDPoOcclReadCtr = 0; lastBPErrorCtr = 0; - lastDPIErrorCtr = 0; - lastDPOErrorCtr = 0; +#endif + longFilteredArterialPressure = 0.0; + shortFilteredArterialPressure = 0.0; + shortFilteredVenousPressure = 0.0; + +#ifndef DISABLE_PRESSURE_CHECKS bloodPumpOcclusionAfterCartridgeInstall = 0; - dialInPumpOcclusionAfterCartridgeInstall = 0; - dialOutPumpOcclusionAfterCartridgeInstall = 0; +#endif } /*********************************************************************//** * @brief * The isCartridgeLoaded function determines whether a cartridge has been - * properly loaded by looking at the 3 occlusion pressure sensors. - * @details Inputs: occlusion pressures for the pumps + * properly loaded by looking at the BP occlusion pressure sensor. + * @details Inputs: BP occlusion pressure * @details Outputs: none - * @return TRUE if all 3 occlusion sensors read above loaded threshold, FALSE if not. + * @return TRUE if BP occlusion sensor reads above loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeLoaded( void ) { BOOL result = FALSE; U32 bpOccl = getMeasuredBloodPumpOcclusion(); - U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); - if ( ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) && ( diOccl >= CARTRIDGE_LOADED_THRESHOLD ) && - ( doOccl >= CARTRIDGE_LOADED_THRESHOLD ) ) + if ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) { result = TRUE; } @@ -203,18 +220,16 @@ /*********************************************************************//** * @brief * The isCartridgeUnloaded function determines if a cartridge has been - * unloaded by looking at the 3 occlusion pressure sensors. - * @details Inputs: occlusion pressures for the pumps + * unloaded by looking at the BP occlusion pressure sensor. + * @details Inputs: BP occlusion pressure * @details Outputs: none - * @return TRUE if all 3 occlusion sensors read below loaded threshold, FALSE if not. + * @return TRUE if occlusion sensor are below loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeUnloaded( void ) { - BOOL const bpOcclBelowLoadedThreshold = getMeasuredBloodPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; - BOOL const diOcclBelowLoadedThreshold = getMeasuredDialInPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; - BOOL const doOcclBelowLoadedThreshold = getMeasuredDialOutPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; + BOOL const bpOcclBelowLoadedThreshold = ( getMeasuredBloodPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD ? TRUE : FALSE ); - return ( bpOcclBelowLoadedThreshold && diOcclBelowLoadedThreshold && doOcclBelowLoadedThreshold ); + return bpOcclBelowLoadedThreshold; } /*********************************************************************//** @@ -248,18 +263,18 @@ /*********************************************************************//** * @brief - * The setOcclusionInstallLevels function sets the occlusion sensor levels + * The setOcclusionInstallLevel function sets the occlusion sensor level * for an installed cartridge. This function should be called after a new * cartridge is installed. - * @details Inputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion - * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall, dialInPumpOcclusionAfterCartridgeInstall, dialOutPumpOcclusionAfterCartridgeInstall + * @details Inputs: bloodPumpOcclusion + * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall * @return none *************************************************************************/ -void setOcclusionInstallLevels( void ) +void setOcclusionInstallLevel( void ) { +#ifndef DISABLE_PRESSURE_CHECKS bloodPumpOcclusionAfterCartridgeInstall = getMeasuredBloodPumpOcclusion(); - dialInPumpOcclusionAfterCartridgeInstall = getMeasuredDialInPumpOcclusion(); - dialOutPumpOcclusionAfterCartridgeInstall = getMeasuredDialOutPumpOcclusion(); +#endif } /*********************************************************************//** @@ -339,8 +354,6 @@ F32 venTemp = getTemperatureValue( TEMPSENSOR_VENOUS_PRESSURE_SENSOR ); U08 venReadCtr = getFPGAVenousPressureReadCounter(); - // TODO - any filtering required??? - // Convert arterial pressure to mmHg if no fault if ( 0 == artPresAlarm ) { @@ -350,7 +363,15 @@ // Check for stale arterial pressure reading if ( FALSE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr || artErrorCtr > 0 ) ) ) { - arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); +#ifndef PBA_ESTIMATION + arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ) + getF32OverrideValue( &arterialPressureOffset ); +#else + // TODO - temporary test code - remove later + F32 artPres = -0.1146 * getMeasuredBloodPumpMCSpeed(); + artPres = MAX(-200.0,artPres); + artPres = MIN(0,artPres); + arterialPressure.data = artPres; +#endif } else { @@ -394,6 +415,9 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_VENOUS_PRESSURE_SENSOR_FAULT, venTemp ) } + + // Filter inline pressure readings + filterInlinePressureReadings( getMeasuredArterialPressure(), getMeasuredVenousPressure() ); } /*********************************************************************//** @@ -406,54 +430,30 @@ static void convertOcclusionPressures( void ) { U08 bpReadCtr = getFPGABloodPumpOcclusionReadCounter(); - U08 dpiReadCtr = getFPGADialInPumpOcclusionReadCounter(); - U08 dpoReadCtr = getFPGADialOutPumpOcclusionReadCounter(); U08 bpErrorCtr = getFPGABloodPumpOcclusionErrorCounter(); - U08 dpiErrorCtr = getFPGADialInPumpOcclusionErrorCounter(); - U08 dpoErrorCtr = getFPGADialOutPumpOcclusionErrorCounter(); #ifndef DISABLE_PRESSURE_CHECKS // Check for sensor errors if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, ( bpErrorCtr != lastBPErrorCtr ) ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, (U32)bpErrorCtr ) } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, ( dpiErrorCtr != lastDPIErrorCtr ) ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, (U32)dpiErrorCtr ) - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, ( dpoErrorCtr != lastDPOErrorCtr ) ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, (U32)dpoErrorCtr ) - } // Check for stale occlusion reads if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( bpReadCtr == lastBPOcclReadCtr ) ) ) { activateAlarmNoData( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( dpiReadCtr == lastDPiOcclReadCtr ) ) ) - { - activateAlarmNoData( ALARM_ID_HD_DPI_OCCLUSON_READ_TIMEOUT_ERROR ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( dpoReadCtr == lastDPoOcclReadCtr ) ) ) - { - activateAlarmNoData( ALARM_ID_HD_DPO_OCCLUSION_READ_TIMEOUT_ERROR ); - } #endif // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); - dialInPumpOcclusion.data = (U32)getFPGADialInPumpOcclusion(); - dialOutPumpOcclusion.data = (U32)getFPGADialOutPumpOcclusion(); +#ifndef DISABLE_PRESSURE_CHECKS // Record occlusion read and error counters for next time around lastBPOcclReadCtr = bpReadCtr; - lastDPiOcclReadCtr = dpiReadCtr; - lastDPoOcclReadCtr = dpoReadCtr; lastBPErrorCtr = bpErrorCtr; - lastDPIErrorCtr = dpiErrorCtr; - lastDPOErrorCtr = dpoErrorCtr; +#endif } /*********************************************************************//** @@ -466,7 +466,7 @@ *************************************************************************/ static void checkArterialPressureInRange( void ) { - F32 artPres = getMeasuredArterialPressure(); + F32 artPres = getFilteredArterialPressure(); #ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is in range @@ -475,37 +475,30 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, artPres ); } -#endif // Check arterial pressure during treatment mode - if ( MODE_TREA == getCurrentOperationMode() ) + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); -#ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is within user set alarm limits if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) - { - clearAlarmCondition( ALARM_ID_ARTERIAL_PRESSURE_LOW ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) - { - clearAlarmCondition( ALARM_ID_ARTERIAL_PRESSURE_HIGH ); - } -#endif } + else + { // Reset persistence if alarm is out of scope + isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, FALSE ); + } +#endif } /*********************************************************************//** @@ -518,7 +511,7 @@ *************************************************************************/ static void checkVenousPressureInRange( void ) { - F32 venPres = getMeasuredVenousPressure(); + F32 venPres = getFilteredVenousPressure(); #ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is in range @@ -527,36 +520,37 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); } -#endif // Check arterial pressure during treatment mode - if ( MODE_TREA == getCurrentOperationMode() ) + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); -#ifndef DISABLE_PRESSURE_CHECKS - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + // Cannot monitor for low venous pressure while venting air trap + if ( getValveAirTrapStatus() != STATE_OPEN ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + } } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) - { - clearAlarmCondition( ALARM_ID_VENOUS_PRESSURE_LOW ); + else + { // clear persistence if air trap valve is open + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); } if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) - { - clearAlarmCondition( ALARM_ID_VENOUS_PRESSURE_HIGH ); - } -#endif } + else + { // Reset persistence if alarm is out of scope + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, FALSE ); + } +#endif } /*********************************************************************//** @@ -570,25 +564,15 @@ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); - U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); #ifndef DISABLE_PRESSURE_CHECKS - // Range check occlusion sensors + // Range check occlusion sensor if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl < MIN_OCCLUSION_COUNTS ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl < MIN_OCCLUSION_COUNTS ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl < MIN_OCCLUSION_COUNTS ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl ); - } - // Check for occlusions + // Check for occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately @@ -598,24 +582,6 @@ { clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); } - if ( diOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) - { - signalDialInPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) - } - else if ( diOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) - { - clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_IN_PUMP ); - } - if ( doOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) - { - signalDialOutPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) - } - else if ( doOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) - { - clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP ); - } #endif } @@ -637,6 +603,30 @@ return result; } + +/*********************************************************************//** + * @brief + * The getFilteredArterialPressure function gets the current filtered arterial pressure. + * @details Inputs: shortFilteredArterialPressure + * @details Outputs: none + * @return the current filtered arterial pressure (in mmHg). + *************************************************************************/ +F32 getFilteredArterialPressure( void ) +{ + return shortFilteredArterialPressure; +} + +/*********************************************************************//** + * @brief + * The getLongFilteredArterialPressure function gets the current long filtered arterial pressure. + * @details Inputs: longFilteredArterialPressure + * @details Outputs: none + * @return the current long filtered arterial pressure (in mmHg). + *************************************************************************/ +F32 getLongFilteredArterialPressure( void ) +{ + return longFilteredArterialPressure; +} /*********************************************************************//** * @brief @@ -656,6 +646,18 @@ return result; } + +/*********************************************************************//** + * @brief + * The getFilteredVenousPressure function gets the measured filtered venous pressure. + * @details Inputs: shortFilteredVenousPressure + * @details Outputs: none + * @return the current filtered venous pressure (in mmHg). + *************************************************************************/ +F32 getFilteredVenousPressure( void ) +{ + return shortFilteredVenousPressure; +} /*********************************************************************//** * @brief @@ -677,44 +679,53 @@ return result; } -/*********************************************************************//** - * @brief - * The getMeasuredDialInPumpOcclusion function gets the measured dialysate - * inlet pump occlusion pressure. - * @details Inputs: dialInPumpOcclusion - * @details Outputs: none - * @return the current dialysis inlet pump occlusion pressure (in mmHg). - *************************************************************************/ -U32 getMeasuredDialInPumpOcclusion( void ) +/*********************************************************************//** + * @brief + * The filterInlinePressureReadings function adds a new arterial and venous + * pressure sample to the filters. + * @details Inputs: none + * @details Outputs: artPressureReadingsLong[], artPressureReadingsLongIdx, artPressureReadingsLongTotal, artPressureReadingsLongCount, + * artPressureReadingsShort, artPressureReadingsShortIdx, artPressureReadingsShortTotal, artPressureReadingsShortCount, + * venPressureReadingsShort, venPressureReadingsShortIdx, venPressureReadingsShortTotal, venPressureReadingsShortCount, + * longFilteredArterialPressure, shortFilteredArterialPressure, shortFilteredVenousPressure + * @param artPres newest arterial pressure sample to add to filters + * @param venPres newest venous pressure sample to add to filter + * @return none + *************************************************************************/ +static void filterInlinePressureReadings( F32 artPres, F32 venPres ) { - U32 result = dialInPumpOcclusion.data; - - if ( OVERRIDE_KEY == dialInPumpOcclusion.override ) + // Long filter for arterial pressure. + if ( artPressureReadingsLongCount >= SIZE_OF_LONG_ART_ROLLING_AVG ) { - result = dialInPumpOcclusion.ovData; + artPressureReadingsLongTotal -= artPressureReadingsLong[ artPressureReadingsLongIdx ]; } + artPressureReadingsLong[ artPressureReadingsLongIdx ] = artPres; + artPressureReadingsLongTotal += artPres; + artPressureReadingsLongIdx = INC_WRAP( artPressureReadingsLongIdx, 0, SIZE_OF_LONG_ART_ROLLING_AVG - 1 ); + artPressureReadingsLongCount = INC_CAP( artPressureReadingsLongCount, SIZE_OF_LONG_ART_ROLLING_AVG ); + longFilteredArterialPressure = artPressureReadingsLongTotal / (F32)artPressureReadingsLongCount; - return result; -} - -/*********************************************************************//** - * @brief - * The getMeasuredDialOutPumpOcclusion function gets the measured dialysate - * outlet pump occlusion pressure. - * @details Inputs: dialOutPumpOcclusion - * @details Outputs: none - * @return the current dialysis outlet pump occlusion pressure (in mmHg). - *************************************************************************/ -U32 getMeasuredDialOutPumpOcclusion( void ) -{ - U32 result = dialOutPumpOcclusion.data; - - if ( OVERRIDE_KEY == dialOutPumpOcclusion.override ) + // Short filter for arterial pressure. + if ( artPressureReadingsShortCount >= SIZE_OF_SHORT_ART_ROLLING_AVG ) { - result = dialOutPumpOcclusion.ovData; + artPressureReadingsShortTotal -= artPressureReadingsShort[ artPressureReadingsShortIdx ]; } + artPressureReadingsShort[ artPressureReadingsShortIdx ] = artPres; + artPressureReadingsShortTotal += artPres; + artPressureReadingsShortIdx = INC_WRAP( artPressureReadingsShortIdx, 0, SIZE_OF_SHORT_ART_ROLLING_AVG - 1 ); + artPressureReadingsShortCount = INC_CAP( artPressureReadingsShortCount, SIZE_OF_SHORT_ART_ROLLING_AVG ); + shortFilteredArterialPressure = artPressureReadingsShortTotal / (F32)artPressureReadingsShortCount; - return result; + // Short filter for venous pressure. + if ( venPressureReadingsShortCount >= SIZE_OF_SHORT_VEN_ROLLING_AVG ) + { + venPressureReadingsShortTotal -= venPressureReadingsShort[ venPressureReadingsShortIdx ]; + } + venPressureReadingsShort[ venPressureReadingsShortIdx ] = venPres; + venPressureReadingsShortTotal += venPres; + venPressureReadingsShortIdx = INC_WRAP( venPressureReadingsShortIdx, 0, SIZE_OF_SHORT_VEN_ROLLING_AVG - 1 ); + venPressureReadingsShortCount = INC_CAP( artPressureReadingsShortCount, SIZE_OF_SHORT_VEN_ROLLING_AVG ); + shortFilteredVenousPressure = venPressureReadingsShortTotal / (F32)venPressureReadingsShortCount; } /*********************************************************************//** @@ -732,13 +743,13 @@ { PRESSURE_OCCLUSION_DATA_T data; - data.arterialPressure = getMeasuredArterialPressure(); - data.venousPressure = getMeasuredVenousPressure(); + data.arterialPressure = shortFilteredArterialPressure; + data.venousPressure = shortFilteredVenousPressure; data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); - data.diPumpOcclusion = getMeasuredDialInPumpOcclusion(); - data.doPumpOcclusion = getMeasuredDialOutPumpOcclusion(); + data.diPumpOcclusion = 0; // TODO - remove unused fields + data.doPumpOcclusion = 0; - broadcastPresOcclData( data ); + broadcastData( MSG_ID_PRESSURE_OCCLUSION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); presOcclDataPublicationTimerCounter = 0; } } @@ -754,26 +765,14 @@ { #ifndef DISABLE_PRESSURE_CHECKS U32 const bpPressure = getMeasuredBloodPumpOcclusion(); - U32 const dialysateInPressure = getMeasuredDialInPumpOcclusion(); - U32 const dialysateOutPressure = getMeasuredDialOutPumpOcclusion(); - F32 const arterialPressure = getMeasuredArterialPressure(); - F32 const venousPressure = getMeasuredVenousPressure(); + F32 const arterialPressure = getFilteredArterialPressure(); + F32 const venousPressure = getFilteredVenousPressure(); if ( bpPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SELF_TEST_FAILURE, bpPressure ); } - if ( dialysateInPressure > CARTRIDGE_LOADED_THRESHOLD ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DIP_OCCLUSION_SELF_TEST_FAILURE, dialysateInPressure ); - } - - if ( dialysateOutPressure > CARTRIDGE_LOADED_THRESHOLD ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DOP_OCCLUSION_SELF_TEST_FAILURE, dialysateOutPressure ); - } - if ( ( arterialPressure <= ARTERIAL_PRESSURE_SELF_TEST_MIN ) || ( arterialPressure >= ARTERIAL_PRESSURE_SELF_TEST_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_SELF_TEST_FAILURE, arterialPressure ); @@ -790,7 +789,7 @@ * @brief * The execPresOcclDryTest function executes the PresOccl dry self-test. * @details Inputs: none - * @details Outputs: none + * @details Outputs: Triggers no cartridge loaded alarm if no cartridge detected. * @return the result of the PresOccl dry self-test. *************************************************************************/ SELF_TEST_STATUS_T execPresOcclDryTest( void ) @@ -799,36 +798,12 @@ #ifndef DISABLE_OCCLUSION_SELF_TEST U32 const bpPressure = getMeasuredBloodPumpOcclusion(); - U32 const dialysateInPressure = getMeasuredDialInPumpOcclusion(); - U32 const dialysateOutPressure = getMeasuredDialOutPumpOcclusion(); if ( ( bpPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( bpPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) { + activateAlarmNoData( ALARM_ID_NO_CARTRIDGE_LOADED ); result = SELF_TEST_STATUS_FAILED; } - - if ( ( dialysateInPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( dialysateInPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) - { - result = SELF_TEST_STATUS_FAILED; - } - - if ( ( dialysateOutPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( dialysateOutPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) - { - result = SELF_TEST_STATUS_FAILED; - } - - if ( SELF_TEST_STATUS_FAILED == result ) - { - if ( ( bpPressure <= CARTRIDGE_LOADED_THRESHOLD ) && ( dialysateInPressure <= CARTRIDGE_LOADED_THRESHOLD ) && - ( dialysateOutPressure <= CARTRIDGE_LOADED_THRESHOLD ) ) - { - activateAlarmNoData( ALARM_ID_NO_CARTRIDGE_LOADED ); - } - else - { - activateAlarmNoData( ALARM_ID_CARTRIDGE_INSTALLED_IMPROPERLY ); - } - } #endif return result; @@ -1019,96 +994,51 @@ } return result; -} +} + +/*********************************************************************//** + * @brief + * The testSetBloodPumpOcclusionOverride function overrides the arterial + * pressure offset. + * @details Inputs: none + * @details Outputs: arterialPressureOffset + * @param value override arterial pressure offset with + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetArterialPressureOffsetOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + arterialPressureOffset.ovData = value; + arterialPressureOffset.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetArterialPressureOffsetOverride function resets the override of the + * arterial pressure offset. + * @details Inputs: none + * @details Outputs: arterialPressureOffset + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetArterialPressureOffsetOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + arterialPressureOffset.override = OVERRIDE_RESET; + arterialPressureOffset.ovData = arterialPressureOffset.ovInitData; + } + + return result; +} -/*********************************************************************//** - * @brief - * The testSetDialInPumpOcclusionOverride function overrides the measured - * dialysate inlet pump occlusion pressure.n - * @details Inputs: none - * @details Outputs: dialInPumpOcclusion - * @param value override measured dialysate inlet pump occlusion pressure - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDialInPumpOcclusionOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInPumpOcclusion.ovData = value; - dialInPumpOcclusion.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetDialInPumpOcclusionOverride function resets the override of the - * measured dialysate inlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialInPumpOcclusion - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDialInPumpOcclusionOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInPumpOcclusion.override = OVERRIDE_RESET; - dialInPumpOcclusion.ovData = dialInPumpOcclusion.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetDialOutPumpOcclusionOverride function overrides the measured - * dialysate outlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialOutPumpOcclusion - * @param value override measured dialysate outlet pump occlusion pressure - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDialOutPumpOcclusionOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialOutPumpOcclusion.ovData = value; - dialOutPumpOcclusion.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetDialOutPumpOcclusionOverride function resets the override of the - * measured dialysate outlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialOutPumpOcclusion - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDialOutPumpOcclusionOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialOutPumpOcclusion.override = OVERRIDE_RESET; - dialOutPumpOcclusion.ovData = dialOutPumpOcclusion.ovInitData; - } - - return result; -} - /**@}*/