Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -rf284ba9abf19a9bdc01e56805875125778d14229 -r14be978c00cef299cf67b515117b689de6cef353 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision f284ba9abf19a9bdc01e56805875125778d14229) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 14be978c00cef299cf67b515117b689de6cef353) @@ -102,6 +102,7 @@ #define OCCLUSION_THRESHOLD_OFFSET 5500 ///< Threshold offset. Combined with initial reading after cartridge install, a threshold is derived above which an occlusion is detected. #define OCCLUSION_CLEAR_THRESHOLD_OFFSET 5000 ///< Threshold offset. Combined with initial reading after cartridge install, a threshold is derived below which an occlusion is cleared. +#define PARTIAL_OCCLUSION_THRESHOLD_OFFSET 1100 ///< Threshold offset. Combined with during treatment occlusion reading, a threshold is derived above which a partial occlusion is detected. #define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. #define MIN_OCCLUSION_COUNTS 2000 ///< Minimum occlusion sensor reading for range check. @@ -127,6 +128,9 @@ /// 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 ) +/// Measured blood pump occlusion is filtered w/ 30 second moving average for partial occlusions check. +#define SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 30 ) + #define DATA_PUBLISH_COUNTER_START_COUNT 5 ///< Data publish counter start count. #define SHIFT_14_BITS 14 ///< Shift 14 bits. @@ -179,14 +183,23 @@ static OVERRIDE_F32_T shortFilteredArterialPressure = { 0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure after short (1 s) filter. static F32 longFilteredVenousPressure; ///< Measured venous pressure after long (10 s) filter. static OVERRIDE_F32_T shortFilteredVenousPressure = { 0.0, 0.0, 0.0, 0 }; ///< Measured venous pressure after short (1 s) filter. -static STABILIZATION_PERIODS_T pressureStabilizeTime; ///< Pressure stabilization time based on system events such as airpump, treatment param changes etc., +static OVERRIDE_U32_T filteredBloodPumpOccl = { 0, 0, 0, 0 }; ///< Measured blood pump occlusion after 30s filter. +static STABILIZATION_PERIODS_T pressureStabilizeTime; ///< Pressure stabilization time based on system events such as airpump, treatment param changes etc., static BOOL resetFillExemptPeriod; ///< Flag to reset the exempt period after defined time expire. static BOOL lowVenousPressureExemptCheck; ///< low venous pressure exempt check flag based on the air trap valve status static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. +static U32 bloodPumpOcclusionDuringTreatement; ///< Measured filtered blood pump occlusion reading taken during treatment. +static BOOL partialBloodPumpOcclBaselineUpdate; ///< Flag to update partial occlusion baseline in events such as start of treatment,resume from partial BP occlusion alarm occurrence. +static BOOL isPartialBloodPumpOcclBaselineSet; ///< Flag to raise alarm only when partial blood pump occlusion baseline set at start of treatment dialysis. static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. +static U32 bloodPumpOcclReadings[ SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG ]; ///< Holds blood pump occlusion rolling average. +static U32 bloodPumpOcclReadingsIdx = 0; ///< Index for next sample in rolling average array. +static U32 bloodPumpOcclReadingsTotal = 0; ///< Rolling total - used to calc average. +static U32 bloodPumpOcclReadingsCount = 0; ///< Number of samples in blood pump occl rolling average buffer. + 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. @@ -224,6 +237,8 @@ static void publishPresOcclData( void ); static void determineArtVenPressureLimits( void ); static void filterInlinePressureReadings( F32 artPres, F32 venPres ); +static void setOcclusionBaselineDuringTreatement( void ); +static void filterBloodPumpOcclReadings( U32 bloodPumpOccl ); /*********************************************************************//** * @brief @@ -266,10 +281,14 @@ shortFilteredArterialPressure.data = 0.0F; longFilteredVenousPressure = 0.0F; shortFilteredVenousPressure.data = 0.0F; + filteredBloodPumpOccl.data = 0; presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; presOcclState = PRESSURE_WAIT_FOR_POST_STATE; presOcclPostState = PRESSURE_SELF_TEST_STATE_START; bloodPumpOcclusionAfterCartridgeInstall = 0; + bloodPumpOcclusionDuringTreatement = 0; + partialBloodPumpOcclBaselineUpdate = FALSE; + isPartialBloodPumpOcclBaselineSet = FALSE; pressureStabilizeTime = USE_NORMAL_STABILIZATION_PERIOD; resetFillExemptPeriod = TRUE; lowVenousPressureExemptCheck = TRUE; @@ -394,6 +413,21 @@ /*********************************************************************//** * @brief + * The setOcclusionBaselineDuringTreatement function sets the partial occlusion sensor level + * during treatment. This function called at start of treatment, periodic interval during + * treatment. + * @details Inputs: bloodPumpOcclusion + * @details Outputs: bloodPumpOcclusionDuringTreatement + * @return none + *************************************************************************/ +static void setOcclusionBaselineDuringTreatement( void ) +{ + bloodPumpOcclusionDuringTreatement = getFilteredBloodPumpOccl(); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_PARTIAL_OCCLUSION_BASELINE, bloodPumpOcclusionDuringTreatement, PARTIAL_OCCLUSION_THRESHOLD_OFFSET ); +} + +/*********************************************************************//** + * @brief * The setPressureLimitsToOuterBounds function sets the min/max pressure * limits for arterial and venous pressure to their outer boundaries. * @details Inputs: none @@ -526,6 +560,18 @@ /*********************************************************************//** * @brief + * The signalBloodPumpPressureOcclbaseline function sets the flag. + * @details Inputs: partialBloodPumpOcclBaselineUpdate + * @details Outputs: partialBloodPumpOcclBaselineUpdate + * @return none + *************************************************************************/ +void signalBloodPumpPressureOcclbaseline( void ) +{ + partialBloodPumpOcclBaselineUpdate = TRUE; +} + +/*********************************************************************//** + * @brief * The execPresOccl function executes the pressure and occlusion monitor. * @details Inputs: presOcclState * @details Outputs: presOcclState @@ -686,6 +732,14 @@ stabilizationStartTimeMs = getMSTimerCount(); currPresLimitsState = PRESSURE_LIMITS_STATE_STABILIZATION_2; pressureStabilizeTime = USE_NORMAL_STABILIZATION_PERIOD; + + //Update partial blood pump occlusion baseline only in dialysis state + if ( ( TRUE == partialBloodPumpOcclBaselineUpdate ) && ( TREATMENT_DIALYSIS_STATE == currTxState ) ) + { + partialBloodPumpOcclBaselineUpdate = FALSE; + setOcclusionBaselineDuringTreatement(); + isPartialBloodPumpOcclBaselineSet = TRUE; + } } break; @@ -735,6 +789,9 @@ stabilizationStartTimeMs = getMSTimerCount(); pressureStabilizeTime = STABILIZATION_PERIOD_OFF; currPresLimitsState = PRESSURE_LIMITS_STATE_STABILIZATION_2; + + //Periodical Update of partial blood pump occlusion baseline + setOcclusionBaselineDuringTreatement(); } break; @@ -812,6 +869,9 @@ // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); + + // Filter blood pump occlusion readings + filterBloodPumpOcclReadings( getMeasuredBloodPumpOcclusion() ); } /*********************************************************************//** @@ -965,6 +1025,7 @@ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); + U32 filteredBpOccl = getFilteredBloodPumpOccl(); BOOL outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS ? TRUE : FALSE ); #ifndef _RELEASE_ @@ -1026,6 +1087,22 @@ clearAlarmCondition( ALARM_ID_HD_OCCLUSION_BLOOD_PUMP ); } + // Partial Occlusion check during treatment + if ( MODE_TREA == hdMode ) + { + if ( ( TRUE == isBloodPumpRunning() ) && ( TRUE == isPartialBloodPumpOcclBaselineSet ) ) + { + // Check for partial occlusion + if ( filteredBpOccl > ( PARTIAL_OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionDuringTreatement ) ) + { + signalBloodPumpHardStop(); // Stop pump immediately + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_PARTIAL_OCCLUSION_BLOOD_PUMP, filteredBpOccl, PARTIAL_OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionDuringTreatement ) + // Update partial occlusion baseline + signalBloodPumpPressureOcclbaseline(); + } + } + } + // Check for venous occlusion #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_VENOUS_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) @@ -1131,6 +1208,18 @@ /*********************************************************************//** * @brief + * The getFilteredBloodPumpOccl function gets the measured filtered blood pump occlusion. + * @details Inputs: filteredBloodPumpOccl + * @details Outputs: none + * @return the current filtered blood pump occlusion. + *************************************************************************/ +U32 getFilteredBloodPumpOccl( void ) +{ + return getU32OverrideValue( &filteredBloodPumpOccl ); +} + +/*********************************************************************//** + * @brief * The getFilteredVenousPressure function gets the measured filtered venous pressure. * @details Inputs: shortFilteredVenousPressure * @details Outputs: none @@ -1236,6 +1325,29 @@ /*********************************************************************//** * @brief + * The filterBloodPumpOcclReadings function adds a new blood pump occlusion + * sample to the filters. + * @details Inputs: none + * @details Outputs: bloodPumpOcclReadings[], bloodPumpOcclReadingsIdx, bloodPumpOcclReadingsTotal, bloodPumpOcclReadingsCount, + * filteredBloodPumpOccl + * @param bloodPumpOccl newest blood pump occlusion sample to add to filters + * @return none + *************************************************************************/ +static void filterBloodPumpOcclReadings( U32 bloodPumpOccl ) +{ + if ( bloodPumpOcclReadingsCount >= SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG ) + { + bloodPumpOcclReadingsTotal -= bloodPumpOcclReadings[ bloodPumpOcclReadingsIdx ]; + } + bloodPumpOcclReadings[ bloodPumpOcclReadingsIdx ] = bloodPumpOccl; + bloodPumpOcclReadingsTotal += bloodPumpOccl; + bloodPumpOcclReadingsIdx = INC_WRAP( bloodPumpOcclReadingsIdx, 0, SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG - 1 ); + bloodPumpOcclReadingsCount = INC_CAP( bloodPumpOcclReadingsCount, SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG ); + filteredBloodPumpOccl.data = bloodPumpOcclReadingsTotal / bloodPumpOcclReadingsCount; +} + +/*********************************************************************//** + * @brief * The publishPresOcclData function publishes pressure/occlusion data at the * set interval. * @details Inputs: latest pressure and occlusion readings @@ -1249,16 +1361,18 @@ { PRESSURE_OCCLUSION_DATA_T data; - data.arterialPressure = getFilteredArterialPressure(); - data.venousPressure = getFilteredVenousPressure(); - data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); - data.presLimitState = currPresLimitsState; - data.artMinLimit = currentArterialMinLimit; - data.artMaxLimit = currentArterialMaxLimit; - data.venMinLimit = currentVenousMinLimit; - data.venMaxLimit = currentVenousMaxLimit; - data.arterialLongFilterPres = longFilteredArterialPressure; - data.venousLongFilterPres = longFilteredVenousPressure; + data.arterialPressure = getFilteredArterialPressure(); + data.venousPressure = getFilteredVenousPressure(); + data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); + data.presLimitState = currPresLimitsState; + data.artMinLimit = currentArterialMinLimit; + data.artMaxLimit = currentArterialMaxLimit; + data.venMinLimit = currentVenousMinLimit; + data.venMaxLimit = currentVenousMaxLimit; + data.arterialLongFilterPres = longFilteredArterialPressure; + data.venousLongFilterPres = longFilteredVenousPressure; + data.filteredbldPumpOcclusion = getFilteredBloodPumpOccl(); + data.partialOcclBaseline = PARTIAL_OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionDuringTreatement; broadcastData( MSG_ID_PRESSURE_OCCLUSION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); presOcclDataPublicationTimerCounter = 0; @@ -1581,4 +1695,49 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetFilteredBloodPumpOcclusionOverride function overrides the measured + * filtered blood pump occlusion pressure. + * @details Inputs: none + * @details Outputs: filteredBloodPumpOccl + * @param value override measured filtered blood pump occlusion pressure with + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFilteredBloodPumpOcclusionOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + filteredBloodPumpOccl.ovData = value; + filteredBloodPumpOccl.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetFilteredBloodPumpOcclusionOverride function resets the override of the + * measured filtered blood pump occlusion pressure. + * @details Inputs: none + * @details Outputs: filteredBloodPumpOccl + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetFilteredBloodPumpOcclusionOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + filteredBloodPumpOccl.override = OVERRIDE_RESET; + filteredBloodPumpOccl.ovData = filteredBloodPumpOccl.ovInitData; + } + + return result; +} + /**@}*/