/************************************************************************** * * Copyright (c) 2020-2024 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 * * @author (last) Vinayakam Mani * @date (last) 06-May-2024 * * @author (original) Sean * @date (original) 15-Jan-2020 * ***************************************************************************/ #include "PresOccl.h" #include "AirPump.h" #include "AlarmMgmt.h" #include "BloodFlow.h" #include "FPGA.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "SelfTests.h" #include "TaskGeneral.h" #include "Temperatures.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup PressureOcclusion * @{ */ // ********** private definitions ********** /// Default publication interval for pressure and occlusion data. #define PRES_OCCL_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the pressure/occlusion data is published on the CAN bus. #define PRES_LIMIT_STABILIZATION_OFF ( 0 ) ///< pressure limit stabilization period off #define PRES_LIMIT_STABILIZATION_2_TIME_MS ( 60 * MS_PER_SECOND ) ///< Duration of pressure limit second stage stabilization period (in ms) #define PRES_LIMIT_STABILIZATION_TIME_MS ( 60 * MS_PER_SECOND ) ///< Duration of pressure limit stabilization period (in ms). #define PRES_LIMIT_SHORT_STABILIZE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Duration of pressure limit short stabilization period (in ms). #define PRES_LIMIT_RESTABILIZE_TIME_MS ( 15 * SEC_PER_MIN * MS_PER_SECOND ) ///< Duration of pressure limit re-stabilize period (in ms). // Pressure Limit minimum stabilization time before short stabilization time activation static const U32 PRES_LIMIT_MIN_STABILIZATION_TIME_IN_MS = ( PRES_LIMIT_STABILIZATION_TIME_MS - PRES_LIMIT_SHORT_STABILIZE_TIME_MS ); #define ARTERIAL_PRESSURE_CONVERSION_OFFSET 0x800000 ///< Arterial pressure conversion coefficient. #define ARTERIAL_PRESSURE_V_BIAS ( 3.0F ) ///< Bias voltage for arterial pressure sensor. #define ARTERIAL_PRESSURE_SENSITIVITY ( 0.000005F ) ///< Sensitivity for arterial pressure sensor is 5 uV / mmHg #define ARTERIAL_PRESSURE_V_PER_BIT ( ARTERIAL_PRESSURE_V_BIAS / \ (F32)ARTERIAL_PRESSURE_CONVERSION_OFFSET ) ///< Volts per bit in 24-bit arterial pressure sensor reading. #define VENOUS_PRESSURE_OFFSET ( 1638 ) ///< Offset for 14-bit venous pressure sensor reading. #define VENOUS_PRESSURE_SCALE ( 14745 - VENOUS_PRESSURE_OFFSET ) ///< Scale for venous pressure sensor. #define VENOUS_PRESSURE_MIN_PSI ( -30.0F ) ///< Minimum of scale for venous pressure sensor reading (in PSI). #define VENOUS_PRESSURE_MAX_PSI ( 30.0F ) ///< Maximum of scale for venous pressure sensor reading (in PSI). #define MIN_VENOUS_PRESSURE_FOR_RAMP_MMHG ( 0.0F ) ///< Minimum venous pressure during blood pump ramp up (in mmHg). #define VENOUS_OFFSET_WITH_AIRPUMP_MMHG ( 150.0F ) ///< Value to increase venous pressure high limit alarm when air pump is operating. #define ARTERIAL_PRESSURE_OFFSET ( 1638 ) ///< Offset for 14-bit arterial pressure sensor reading. #define ARTERIAL_PRESSURE_SCALE ( 14745 - VENOUS_PRESSURE_OFFSET ) ///< Scale for arterial pressure sensor. #define ARTERIAL_PRESSURE_MIN_PSI ( -30.0F ) ///< Minimum of scale for arterial pressure sensor reading (in PSI). #define ARTERIAL_PRESSURE_MAX_PSI ( 30.0F ) ///< Maximum of scale for arterial pressure sensor reading (in PSI). #define ARTERIAL_PRESSURE_SELF_TEST_MIN ( -100.0F ) ///< Minimum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum arterial pressure reading (in mmHg) for range check. #define ARTERIAL_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum arterial pressure reading (in mmHg) for range check. #define ARTERIAL_PRESSURE_LIMIT_MAX_MMHG ( 100.0F ) ///< Maximum arterial pressure limit (in mmHg). #define ARTERIAL_PRESSURE_LIMIT_MIN_MMHG ( -300.0F ) ///< Minimum arterial pressure limit (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MIN ( -100.0F ) ///< Minimum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_LIMIT_MAX_MMHG ( 400.0F ) ///< Maximum venous pressure limit (in mmHg). #define VENOUS_PRESSURE_LIMIT_MIN_MMHG ( 20.0F ) ///< Minimum venous pressure limit (in mmHg). #define VENOUS_PRESSURE_OCCL_OFFSET_MMHG ( 50.0F ) ///< Venous pressure occlusion threshold offset from max alarm limit (in mmHg). #define VENOUS_PRESSURE_EXEMPTION_PERIOD ( ( 2 * MS_PER_SECOND ) / \ TASK_GENERAL_INTERVAL ) ///< Venous pressure low exemption period (in task interval) after fill for all blood flow rate #define MIN_TIME_BETWEEN_AIR_TRAP_FILL_EXEMPTIONS_MS ( 1200 ) ///< To monitor low Venous pressure in the defined interval in a case where continuous air fill event happens followed by exemption period to stabilize the pressure #define MIN_TIME_BETWEEN_AIR_TRAP_FILL_EXEMPTIONS_WINDOW ( MIN_TIME_BETWEEN_AIR_TRAP_FILL_EXEMPTIONS_MS / \ TASK_GENERAL_INTERVAL ) ///< Low Venous pressure monitoring window between air fill events based on the task interval time #define PSI_TO_MMHG ( 51.7149F ) ///< Conversion factor for converting PSI to mmHg. // The new arterial pressure sensor is the same as the venous pressure sensor #define VENOUS_PRESSURE_NORMAL_OP 0 ///< Venous pressure status bits indicate normal operation. #define VENOUS_PRESSURE_CMD_MODE 1 ///< Venous pressure status bits indicate sensor in command mode. #define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). #define VENOUS_PRESSURE_DIAG_CONDITION 3 ///< Venous pressure status bits diagnostic condition (alarm). #define ARTERIAL_PRESSURE_NORMAL_OP 0 ///< Arterial pressure status bits indicate normal operation. #define ARTERIAL_PRESSURE_CMD_MODE 1 ///< Arterial pressure status bits indicate sensor in command mode. #define ARTERIAL_PRESSURE_STALE_DATA 2 ///< Arterial pressure status bits indicate data is stale (no new data since last fpga read). #define ARTERIAL_PRESSURE_DIAG_CONDITION 3 ///< Arterial pressure status bits diagnostic condition (alarm). #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 1000 ///< 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. #define OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX 24500 ///< Occlusion sensors maximum pressure reading limit when cartridge is considered loaded. #define MAX_ART_VEN_OFFSET_MMHG 15.0F ///< Maximum arterial/venous offset allowed. #define EMPTY_SALINE_BAG_THRESHOLD_MMHG -300.0F ///< Threshold below which the saline bag is considered empty (in mmHg). 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. #define HIGH_VEN_PRES_ALARM_PERSISTENCE 500 ///< Alarm persistence period for high venous pressure alarm #define PRES_OCCL_ALARM_PERSISTENCE ( 3 * MS_PER_SECOND ) ///< Alarm persistence period for occlusion alarms #define VEN_OCCL_ALARM_PERSISTENCE 100 ///< Alarm persistence period for venous occlusion alarm. #define AIR_PUMP_TOLERANCE_TIMEOUT_MS (1 * MS_PER_SECOND ) ///< Time to allow increased maximum venous high limit /// 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 arterial pressure is filtered w/ 10 second moving average for pressure compensation of flow. #define SIZE_OF_LONG_VEN_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) /// 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/ 10 second moving average for partial occlusions check. #define SIZE_OF_BLOODPUMP_OCCL_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) /// Interval (15 minutes in task time) at which the partial blood pump occlusion baseline update happens during dialysis state. #define PERIODIC_PARTIAL_BLOODPUMP_OCCL_BASELINE_UPDATE ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * SEC_PER_MIN * 15 ) #define DATA_PUBLISH_COUNTER_START_COUNT 5 ///< Data publish counter start count. #define SHIFT_14_BITS 14 ///< Shift 14 bits. #define PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Occlusion sensor FPGA error timeout in milliseconds. #ifndef _RELEASE_ #define MIN_OCCLUSION_COUNTS_V3 1500 ///< Minimum occlusion count for v3 hardware #endif /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States { PRESSURE_WAIT_FOR_POST_STATE = 0, ///< Wait for POST state. PRESSURE_CONTINUOUS_READ_STATE, ///< Continuous read sensors state. NUM_OF_PRESSURE_STATES ///< Number of pressure/occlusion monitor states. } PRESSURE_STATE_T; /// Defined states for the pressure and occlusion self-test state machine. typedef enum PresOccl_Self_Test_States { PRESSURE_SELF_TEST_STATE_START = 0, ///< Self test start state. PRESSURE_TEST_STATE_IN_PROGRESS, ///< Self test in progress state. PRESSURE_TEST_STATE_COMPLETE, ///< Self test completed state. NUM_OF_PRESSURE_SELF_TEST_STATES ///< Number of pressure/occlusion self-test states. } PRESSURE_SELF_TEST_STATE_T; // ********** private data ********** static PRESSURE_STATE_T presOcclState; ///< Current state of pressure monitor state machine. static U32 presOcclDataPublicationTimerCounter = 0; ///< Used to schedule pressure data publication to CAN bus. static U32 venLowPresExemptAfterAirTrapFillTimerCtr; ///< Exempt low ven pressure limit alarm for a time following an air trap fill. static U32 prevVenLowPresExemptAfterAirTrapFillTimerCtr; ///< previous venous low pressure exempt fill time counter /// 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 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 PRESSURE_LIMITS_STATES_T currPresLimitsState; ///< Current pressure limits state. static F32 arterialPressureOffset; ///< Arterial pressure sensor offset (in mmHg). static F32 venousPressureOffset; ///< Venous pressure sensor offset (in mmHg). static S32 stableArterialPressure; ///< Arterial pressure that limit window is based on (in mmHg). static S32 stableVenousPressure; ///< Venous pressure that limit window is based on (in mmHg). static S32 currentArterialMaxLimit; ///< Maximum arterial pressure limit (in mmHg). static S32 currentArterialMinLimit; ///< Minimum arterial pressure limit (in mmHg). static S32 currentVenousMaxLimit; ///< Maximum venous pressure limit (in mmHg). static S32 currentVenousMinLimit; ///< Minimum venous pressure limit (in mmHg). static BOOL pressureLimitsActive; ///< Flag indicates whether arterial and venous pressure alarm limits are active. static U32 stabilizationStartTimeMs; ///< Timestamp taken when pressure limit stabilization began (ms). static F32 longFilteredArterialPressure; ///< Measured arterial pressure after long (10 s) filter. 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 OVERRIDE_F32_T filteredBloodPumpOccl = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump occlusion after 10s 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 OVERRIDE_F32_T bloodPumpPartialOcclusionBaseline = { 0.0, 0.0, 0.0, 0 }; ///< Measured filtered blood pump occlusion baseline 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 U32 partialBloodPumpOcclBaselineUpdateTimerCounter = 0; ///< Used to update partial occlusion base line periodically during 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. 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 venPressureReadingsLong[ SIZE_OF_LONG_VEN_ROLLING_AVG ]; ///< Holds flow samples for long venous pressure rolling average. static U32 venPressureReadingsLongIdx = 0; ///< Index for next sample in rolling average array. static F32 venPressureReadingsLongTotal = 0.0; ///< Rolling total - used to calc average. static U32 venPressureReadingsLongCount = 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. static PRESSURE_SELF_TEST_STATE_T presOcclPostState; ///< Pressure self test post state. static HD_PRESSURE_SENSORS_CAL_RECORD_T pressureSensorsCalRecord; ///< Pressure sensors calibration record. static HD_OCCLUSION_SENSORS_CAL_RECORD_T occlusionSensorsCalRecord; ///< Occlusion sensors calibration record. // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclWaitForPOSTState( void ); static PRESSURE_STATE_T handlePresOcclContReadState( void ); static void execPressureLimits( void ); static void convertInlinePressures( void ); static void convertOcclusionPressures( void ); static void checkArterialPressureInRange( void ); static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); 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 * The initPresOccl function initializes the PresOccl module. * @details Inputs: none * @details Outputs: PresOccl module initialized. * @return none *************************************************************************/ void initPresOccl( void ) { // Initialize persistent pressure alarms initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_HIGH, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_HIGH, 0, HIGH_VEN_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_OCCL_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, 0, PRES_ALARM_PERSISTENCE ); // Initialize the FPGA persistent alarms initFPGAPersistentAlarm( FPGA_PERS_ERROR_OCCLUSION_PRESSURE_SENSOR, ALARM_ID_HD_OCCLUSION_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_ARTERIAL_PRESSURE_SENSOR, ALARM_ID_HD_ARTERIAL_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, ALARM_ID_HD_VENOUS_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); setPressureLimitsToOuterBounds(); currPresLimitsState = PRESSURE_LIMITS_STATE_OFF; pressureLimitsActive = FALSE; stabilizationStartTimeMs = 0; stableArterialPressure = 0; stableVenousPressure = 0; venLowPresExemptAfterAirTrapFillTimerCtr = 0; prevVenLowPresExemptAfterAirTrapFillTimerCtr = 0; resetArtVenPressureOffsets(); longFilteredArterialPressure = 0.0F; shortFilteredArterialPressure.data = 0.0F; longFilteredVenousPressure = 0.0F; shortFilteredVenousPressure.data = 0.0F; filteredBloodPumpOccl.data = 0.0F; bloodPumpPartialOcclusionBaseline.data = 0.0F; partialBloodPumpOcclBaselineUpdateTimerCounter = 0; presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; presOcclState = PRESSURE_WAIT_FOR_POST_STATE; presOcclPostState = PRESSURE_SELF_TEST_STATE_START; bloodPumpOcclusionAfterCartridgeInstall = 0; partialBloodPumpOcclBaselineUpdate = FALSE; pressureStabilizeTime = USE_NORMAL_STABILIZATION_PERIOD; resetFillExemptPeriod = TRUE; lowVenousPressureExemptCheck = TRUE; } /*********************************************************************//** * @brief * The resetArtVenPressureOffsets function resets the arterial and venous * offsets to zero. * @details Inputs: none * @details Outputs: arterialPressureOffset, venousPressureOffset * @return none *************************************************************************/ void resetArtVenPressureOffsets( void ) { arterialPressureOffset = 0.0F; venousPressureOffset = 0.0F; } /*********************************************************************//** * @brief * The setArtVenPressureOffsets function sets the arterial and venous * offsets to current readings. * @details Inputs: none * @details Outputs: arterialPressureOffset, venousPressureOffset * @return none *************************************************************************/ void setArtVenPressureOffsets( void ) { arterialPressureOffset = getMeasuredArterialPressure(); venousPressureOffset = getMeasuredVenousPressure(); if ( ( fabs( arterialPressureOffset ) > MAX_ART_VEN_OFFSET_MMHG ) || ( fabs( venousPressureOffset ) > MAX_ART_VEN_OFFSET_MMHG ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, arterialPressureOffset, venousPressureOffset ); } } /*********************************************************************//** * @brief * The isCartridgeLoaded function determines whether a cartridge has been * properly loaded by looking at the BP occlusion pressure sensor. * @details Inputs: BP occlusion pressure * @details Outputs: none * @return TRUE if BP occlusion sensor reads above loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeLoaded( void ) { BOOL result = FALSE; U32 bpOccl = getMeasuredBloodPumpOcclusion(); if ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) { result = TRUE; } return result; } /*********************************************************************//** * @brief * The isCartridgeUnloaded function determines if a cartridge has been * unloaded by looking at the BP occlusion pressure sensor. * @details Inputs: BP occlusion pressure * @details Outputs: none * @return TRUE if occlusion sensor are below loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeUnloaded( void ) { BOOL const bpOcclBelowLoadedThreshold = ( getMeasuredBloodPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD ? TRUE : FALSE ); return bpOcclBelowLoadedThreshold; } /*********************************************************************//** * @brief * The isSalineBagEmpty function determines whether the saline bag is empty. * It is assumed that this function will only be called from mode handling * (General Task) when pumping (BP) from the saline bag. * Determination is based on pressure going below a negative threshold. * @details Inputs: arterial line pressure * @details Outputs: none * @return TRUE if arterial line pressure is below threshold, FALSE if not. *************************************************************************/ BOOL isSalineBagEmpty( void ) { BOOL result = FALSE; if ( getMeasuredArterialPressure() < EMPTY_SALINE_BAG_THRESHOLD_MMHG ) { if ( ++emptySalineBagCtr >= EMPTY_SALINE_BAG_PERSISTENCE ) { result = TRUE; } } else { emptySalineBagCtr = 0; } return result; } /*********************************************************************//** * @brief * 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 * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall * @return none *************************************************************************/ void setOcclusionInstallLevel( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif { bloodPumpOcclusionAfterCartridgeInstall = getMeasuredBloodPumpOcclusion(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_OCCLUSION_BASELINE, bloodPumpOcclusionAfterCartridgeInstall, OCCLUSION_THRESHOLD_OFFSET ); } } /*********************************************************************//** * @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: filteredBloodPumpOccl * @details Outputs: bloodPumpPartialOcclusionBaseline * @return none *************************************************************************/ static void setOcclusionBaselineDuringTreatement( void ) { bloodPumpPartialOcclusionBaseline.data = getFilteredBloodPumpOccl(); partialBloodPumpOcclBaselineUpdateTimerCounter = 0; SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_PARTIAL_OCCLUSION_BASELINE, getBloodPumpPartialOcclBaseline(), 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 * @details Outputs: currentArterialMaxLimit, currentArterialMinLimit, * currentVenousMaxLimit, currentVenousMinLimit * @return none *************************************************************************/ void setPressureLimitsToOuterBounds( void ) { currentArterialMaxLimit = (S32)ARTERIAL_PRESSURE_LIMIT_MAX_MMHG; currentArterialMinLimit = (S32)ARTERIAL_PRESSURE_LIMIT_MIN_MMHG; currentVenousMaxLimit = (S32)VENOUS_PRESSURE_LIMIT_MAX_MMHG; currentVenousMinLimit = (S32)VENOUS_PRESSURE_LIMIT_MIN_MMHG; } /*********************************************************************//** * @brief * The updatePressureLimitWindows function updates the pressure limit * stable pressure levels when windows set/changed by user. * If treatment in progress, windowed limits around new stable pressures * will be in effect immediately (next monitor pass). If treatment paused, * resume will start a new stabilization period ending in another set of * stable pressures before windowed limits recalculated. * @details Inputs: pressureStabilizeTime * @details Outputs: stableArterialPressure, stableVenousPressure * @return none *************************************************************************/ void updatePressureLimitWindows( void ) { F32 filtArt; F32 filtVen; S32 curArtPres; S32 curVenPres; if ( USE_SHORT_STABILIZATION_PERIOD == pressureStabilizeTime ) { filtArt = getFilteredArterialPressure(); filtVen = getFilteredVenousPressure(); } else { filtArt = getLongFilteredArterialPressure(); filtVen = getLongFilteredVenousPressure(); } curArtPres = FLOAT_TO_INT_WITH_ROUND( filtArt ); curVenPres = FLOAT_TO_INT_WITH_ROUND( filtVen ); stableArterialPressure = curArtPres; stableVenousPressure = curVenPres; // want to broadcast new limits right away so UI can update tx screen presOcclDataPublicationTimerCounter = getU32OverrideValue( &presOcclDataPublishInterval ); } /*********************************************************************//** * @brief * The signalInitiatePressureStabilization function signals that user has * changed the blood and/or dialysate flow rate. If pressure limits state * was stable, a rate change will kick us back to stabilization state. * Else reset stabilize counter. * @details Inputs: currPresLimitsState * @details Outputs: currPresLimitsState, stabilizationStartTimeMs, pressureStabilizeTime * @param stabilizationPeriod stabilization periods. Use defines: * STABILIZATION_PERIOD_OFF, USE_NORMAL_STABILIZATION_PERIOD, USE_SHORT_STABILIZATION_PERIOD * @return none *************************************************************************/ void signalInitiatePressureStabilization( STABILIZATION_PERIODS_T stabilizationPeriod ) { // User update of blood/dialysate flow rate or UF rate or initiates/resets a stabilization period (if we were in stabilization or stable state) if ( PRESSURE_LIMITS_STATE_STABILIZATION == currPresLimitsState ) { U32 currentTime = getMSTimerCount(); U32 expiredTime = u32DiffWithWrap( stabilizationStartTimeMs, currentTime ); // if pressure is already stabilized enough, assign the short stabilize time for the recent event ( air pump on). // else,allow the ongoing stabilization to complete. // allow Normal stabilization on a case when user updates flow rate or UF rate etc., if ( ( expiredTime > PRES_LIMIT_MIN_STABILIZATION_TIME_IN_MS ) || ( stabilizationPeriod == USE_NORMAL_STABILIZATION_PERIOD ) ) { pressureStabilizeTime = stabilizationPeriod; stabilizationStartTimeMs = getMSTimerCount(); } } else if ( ( PRESSURE_LIMITS_STATE_STABLE == currPresLimitsState ) || ( PRESSURE_LIMITS_STATE_STABILIZATION_2 == currPresLimitsState ) ) { pressureStabilizeTime = stabilizationPeriod; currPresLimitsState = PRESSURE_LIMITS_STATE_STABILIZATION; stabilizationStartTimeMs = getMSTimerCount(); } } /*********************************************************************//** * @brief * The determineArtVenPressureLimits function determines current pressure * limits based on whether we are in stabilization or stable situation. * @details Inputs: currPresLimitsState * @details Outputs: currentArterialMaxLimit, currentArterialMinLimit, * currentVenousMaxLimit, currentVenousMinLimit * @return none *************************************************************************/ static void determineArtVenPressureLimits( void ) { if ( ( PRESSURE_LIMITS_STATE_STABLE == currPresLimitsState ) || ( PRESSURE_LIMITS_STATE_STABILIZATION_2 == currPresLimitsState ) ) { // apply pressure windows when stable S32 artOffset = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ) / 2; // Arterial is symmetric S32 venMinOffset = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ); // Venous is asymmetric S32 venMaxOffset = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ) - venMinOffset; currentArterialMinLimit = stableArterialPressure - artOffset; currentArterialMinLimit = MAX( currentArterialMinLimit, ARTERIAL_PRESSURE_LIMIT_MIN_MMHG ); currentArterialMaxLimit = stableArterialPressure + artOffset; currentArterialMaxLimit = MIN( currentArterialMaxLimit, ARTERIAL_PRESSURE_LIMIT_MAX_MMHG ); currentVenousMinLimit = stableVenousPressure - venMinOffset; currentVenousMinLimit = MAX( currentVenousMinLimit, VENOUS_PRESSURE_LIMIT_MIN_MMHG ); currentVenousMaxLimit = stableVenousPressure + venMaxOffset; currentVenousMaxLimit = MIN( currentVenousMaxLimit, VENOUS_PRESSURE_LIMIT_MAX_MMHG ); } else { // apply outer limits when not stable setPressureLimitsToOuterBounds(); } // set flag indicating whether pressure limits are active based on current current limits state pressureLimitsActive = ( currPresLimitsState > PRESSURE_LIMITS_STATE_IDLE ? TRUE : FALSE ); } /*********************************************************************//** * @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 * @return none *************************************************************************/ void execPresOccl( void ) { // State machine switch ( presOcclState ) { case PRESSURE_WAIT_FOR_POST_STATE: presOcclState = handlePresOcclWaitForPOSTState(); break; case PRESSURE_CONTINUOUS_READ_STATE: presOcclState = handlePresOcclContReadState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_PRES_OCCL_INVALID_STATE, presOcclState ) break; } // Publish pressure/occlusion data on interval publishPresOcclData(); } /*********************************************************************//** * @brief * The handlePresOcclWaitForPOSTState function handles the wait for POST * state. * @details Inputs: presOcclPostState * @details Outputs: none * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclWaitForPOSTState( void ) { PRESSURE_STATE_T result = PRESSURE_WAIT_FOR_POST_STATE; if ( PRESSURE_TEST_STATE_COMPLETE == presOcclPostState ) { result = PRESSURE_CONTINUOUS_READ_STATE; } return result; } /*********************************************************************//** * @brief * The handlePresOcclContReadState function handles the continuous read state * of the pressure/occlusion monitor state machine. * @details Inputs: FPGA pressure/occlusion readings * @details Outputs: pressure sensor values updated * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclContReadState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; // Read latest in-line (arterial and venous) pressures convertInlinePressures(); // Read latest occlusion pressures convertOcclusionPressures(); // Handle pressure limits state machine execPressureLimits(); // Set arterial/venous pressure limits according to current pressure limits state determineArtVenPressureLimits(); // Check in-line pressures are in range checkArterialPressureInRange(); checkVenousPressureInRange(); // Check for occlusions checkOcclusions(); return result; } /*********************************************************************//** * @brief * The execPressureLimits function executes the pressure limits state machine. * @details Inputs: currPresLimitsState, stabilizationStartTimeMs * @details Outputs: currPresLimitsState, stabilizationStartTimeMs * @return next pressure limits state *************************************************************************/ static void execPressureLimits( void ) { BOOL bpRunning = isBloodPumpRunning(); BOOL bpRampComplete = isBloodPumpRampComplete(); HD_OP_MODE_T currMode = getCurrentOperationMode(); TREATMENT_STATE_T currTxState = getTreatmentState(); U32 stabilizeTime = PRES_LIMIT_STABILIZATION_TIME_MS; if ( currMode != MODE_TREA ) { currPresLimitsState = PRESSURE_LIMITS_STATE_OFF; } // Increment the partial occlusion baseline update counter only in Dialysis state if ( ( MODE_TREA == currMode ) && ( currTxState == TREATMENT_DIALYSIS_STATE ) ) { partialBloodPumpOcclBaselineUpdateTimerCounter++; } switch ( currPresLimitsState ) { case PRESSURE_LIMITS_STATE_OFF: if ( ( MODE_TREA == currMode ) && ( currTxState != TREATMENT_RECIRC_STATE ) ) { // Tx mode starts in blood prime - want wide limits in that state currPresLimitsState = PRESSURE_LIMITS_STATE_WIDE; } break; case PRESSURE_LIMITS_STATE_IDLE: if ( TRUE == bpRampComplete ) { currPresLimitsState = PRESSURE_LIMITS_STATE_WIDE; } break; case PRESSURE_LIMITS_STATE_WIDE: if ( bpRunning != TRUE ) { currPresLimitsState = PRESSURE_LIMITS_STATE_IDLE; } else if ( ( TREATMENT_DIALYSIS_STATE == currTxState ) || ( TREATMENT_STOP_STATE == currTxState ) ) { stabilizationStartTimeMs = getMSTimerCount(); pressureStabilizeTime = USE_NORMAL_STABILIZATION_PERIOD; currPresLimitsState = PRESSURE_LIMITS_STATE_STABILIZATION; } else if ( currTxState == TREATMENT_RECIRC_STATE ) { currPresLimitsState = PRESSURE_LIMITS_STATE_OFF; } break; case PRESSURE_LIMITS_STATE_STABILIZATION: // update stabilization time if ( USE_SHORT_STABILIZATION_PERIOD == pressureStabilizeTime ) { stabilizeTime = PRES_LIMIT_SHORT_STABILIZE_TIME_MS; } // Normal stabilization period else { stabilizeTime = PRES_LIMIT_STABILIZATION_TIME_MS; } if ( bpRunning != TRUE ) { currPresLimitsState = PRESSURE_LIMITS_STATE_IDLE; } else if ( ( currTxState != TREATMENT_DIALYSIS_STATE ) && ( currTxState != TREATMENT_STOP_STATE ) ) { currPresLimitsState = PRESSURE_LIMITS_STATE_WIDE; } else if ( TRUE == didTimeout( stabilizationStartTimeMs, stabilizeTime ) ) { updatePressureLimitWindows(); 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(); } } break; case PRESSURE_LIMITS_STATE_STABILIZATION_2: // zero stabilize time for 15 mins once pressure limits adjust scenario if ( STABILIZATION_PERIOD_OFF == pressureStabilizeTime ) { stabilizeTime = PRES_LIMIT_STABILIZATION_OFF; } //60 sec second stage stabilization else { stabilizeTime = PRES_LIMIT_STABILIZATION_2_TIME_MS; } // second stage stabilization helps to re determine the pressure due to UF control change etc., if ( bpRunning != TRUE ) { currPresLimitsState = PRESSURE_LIMITS_STATE_IDLE; } else if ( ( currTxState != TREATMENT_DIALYSIS_STATE ) && ( currTxState != TREATMENT_STOP_STATE ) ) { currPresLimitsState = PRESSURE_LIMITS_STATE_WIDE; } else if ( TRUE == didTimeout( stabilizationStartTimeMs, stabilizeTime ) ) { updatePressureLimitWindows(); stabilizationStartTimeMs = getMSTimerCount(); currPresLimitsState = PRESSURE_LIMITS_STATE_STABLE; // Reset to normal period as default. pressureStabilizeTime = USE_NORMAL_STABILIZATION_PERIOD; } else if ( ( currTxState == TREATMENT_DIALYSIS_STATE ) && ( partialBloodPumpOcclBaselineUpdateTimerCounter >= PERIODIC_PARTIAL_BLOODPUMP_OCCL_BASELINE_UPDATE ) ) { //Periodical Update of partial blood pump occlusion baseline setOcclusionBaselineDuringTreatement(); } break; case PRESSURE_LIMITS_STATE_STABLE: // Pressure is re determined after every 15 minutes once and be remain in limited pressure windows. if ( bpRunning != TRUE ) { currPresLimitsState = PRESSURE_LIMITS_STATE_IDLE; } else if ( ( currTxState != TREATMENT_DIALYSIS_STATE ) && ( currTxState != TREATMENT_STOP_STATE ) ) { currPresLimitsState = PRESSURE_LIMITS_STATE_WIDE; } else if ( TRUE == didTimeout( stabilizationStartTimeMs, PRES_LIMIT_RESTABILIZE_TIME_MS ) ) { stabilizationStartTimeMs = getMSTimerCount(); pressureStabilizeTime = STABILIZATION_PERIOD_OFF; currPresLimitsState = PRESSURE_LIMITS_STATE_STABILIZATION_2; } else if ( ( currTxState == TREATMENT_DIALYSIS_STATE ) && ( partialBloodPumpOcclBaselineUpdateTimerCounter >= PERIODIC_PARTIAL_BLOODPUMP_OCCL_BASELINE_UPDATE ) ) { //Periodical Update of partial blood pump occlusion baseline setOcclusionBaselineDuringTreatement(); } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_PRES_LIMITS_INVALID_STATE, currPresLimitsState ) break; } } /*********************************************************************//** * @brief * The convertInlinePressures function reads inline pressure sensor readings * and converts to mmHg. Sensor status/alarm is checked. * @details Inputs: none * @details Outputs: arterialPressure, venousPressure * @return none *************************************************************************/ static void convertInlinePressures( void ) { // Venous pressure sensor data U16 fpgaVenPres = getFPGAVenousPressure(); U08 venReadCtr = getFPGAVenousPressureReadCounter(); U08 venErrorCtr = getFPGAVenousPressureErrorCounter(); U16 venPres = fpgaVenPres & 0x3FFF; // 14-bit data U08 venPresStatus = (U08)( fpgaVenPres >> SHIFT_14_BITS ); // High 2 bits is status code for venous pressure // Arterial pressure sensor data U16 fpgaArtPres = getFPGADVTArterialPressure(); U08 artReadCtr = getFPGADVTArterialPressureReadCounter(); U08 artErrorCtr = getFPGATDVTArterialPressureErrorCounter(); U16 artPres = fpgaArtPres & 0x3FFF; U08 artPresStatus = (U08)( fpgaArtPres >> SHIFT_14_BITS ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_ARTERIAL_PRESSURE_SENSOR, artReadCtr ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, venReadCtr ); if ( ARTERIAL_PRESSURE_NORMAL_OP == artPresStatus ) { F32 artPresPSI; // If the arterial pressure status is normal, convert the counts to pressure in mmHg artPresPSI = ( (F32)( artPres - ARTERIAL_PRESSURE_OFFSET ) * ( ARTERIAL_PRESSURE_MAX_PSI - ARTERIAL_PRESSURE_MIN_PSI ) / (F32)ARTERIAL_PRESSURE_SCALE ) + ARTERIAL_PRESSURE_MIN_PSI; artPresPSI = artPresPSI * PSI_TO_MMHG; arterialPressure.data = artPresPSI - arterialPressureOffset; } if ( VENOUS_PRESSURE_NORMAL_OP == venPresStatus ) { F32 venPresPSI; // Convert venous pressure to PSI and then mmHg venPresPSI = ( (F32)( venPres - VENOUS_PRESSURE_OFFSET ) * ( VENOUS_PRESSURE_MAX_PSI - VENOUS_PRESSURE_MIN_PSI ) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN_PSI; venPresPSI = venPresPSI * PSI_TO_MMHG; venousPressure.data = venPresPSI - venousPressureOffset; } // Filter inline pressure readings filterInlinePressureReadings( getMeasuredArterialPressure(), getMeasuredVenousPressure() ); } /*********************************************************************//** * @brief * The convertOcclusionPressures function reads occlusion sensor readings. * @details Inputs: FPGA * @details Outputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion * @return none *************************************************************************/ static void convertOcclusionPressures( void ) { U08 bpReadCtr = getFPGABloodPumpOcclusionReadCounter(); U08 bpErrorCtr = getFPGABloodPumpOcclusionErrorCounter(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_OCCLUSION_PRESSURE_SENSOR, bpReadCtr ); // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); // Filter blood pump occlusion readings filterBloodPumpOcclReadings( getMeasuredBloodPumpOcclusion() ); } /*********************************************************************//** * @brief * The checkArterialPressureInRange function checks that artieral pressure is * within the set alarm limits. Alarm is triggered if not. * @details Inputs: arterialPressure, pressureLimitsActive, currentArterialMinLimit, * currentArterialMaxLimit * @details Outputs: Alarm if out of range * @return none *************************************************************************/ static void checkArterialPressureInRange( void ) { F32 artPres = getFilteredArterialPressure(); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ARTERIAL_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { // Check arterial pressure is in absolute max range if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, ( artPres > ARTERIAL_PRESSURE_MAX_MMHG || artPres < ARTERIAL_PRESSURE_MIN_MMHG ) ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, artPres ); } // Check arterial pressure when limits active if ( pressureLimitsActive != FALSE ) { BOOL artPresLow, artPresHigh; artPresLow = ( artPres < (F32)currentArterialMinLimit ? TRUE : FALSE ); artPresHigh = ( artPres > (F32)currentArterialMaxLimit ? TRUE : FALSE ); // Check arterial pressure is within alarm limits if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_LOW, artPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_LOW, artPres, (F32)currentArterialMinLimit ); } if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_HIGH, artPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_HIGH, artPres, (F32)currentArterialMaxLimit ); } } else { // Reset persistence if limits inactive isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_LOW, FALSE ); isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_HIGH, FALSE ); } } } /*********************************************************************//** * @brief * The checkVenousPressureInRange function checks that venous pressure is * within the set alarm limits. Alarm is triggered if not. * @details Inputs: venousPressure, pressureLimitsActive, currentVenousMinLimit, resetFillExemptPeriod * currentVenousMaxLimit, venLowPresExemptAfterAirTrapFillTimerCtr, prevVenLowPresExemptAfterAirTrapFillTimerCtr * @details Outputs: venLowPresExemptAfterAirTrapFillTimerCtr,alarm if out of range * @return none *************************************************************************/ static void checkVenousPressureInRange( void ) { F32 venPres = getFilteredVenousPressure(); OPN_CLS_STATE_T airTrapValveState = getValveAirTrapStatus(); // track time since last air trap fill if ( ( STATE_OPEN == airTrapValveState ) && ( TRUE == resetFillExemptPeriod ) ) { venLowPresExemptAfterAirTrapFillTimerCtr = 0; resetFillExemptPeriod = FALSE; lowVenousPressureExemptCheck = FALSE; } else { // Increment counter on airtrap valve close state. Also, when next fill happens within exempt period, counter will be keep incremented irrespective of valve state. if ( TRUE == lowVenousPressureExemptCheck ) { venLowPresExemptAfterAirTrapFillTimerCtr++; } } #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_VENOUS_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { // Check venous pressure is in absolute max range if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, ( venPres > VENOUS_PRESSURE_MAX_MMHG || venPres < VENOUS_PRESSURE_MIN_MMHG ) ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); } // Check venous pressure when limits active if ( pressureLimitsActive != FALSE ) { BOOL venPresLow, venPresHigh; // Fixed exemption period (in general task intervals) for low venous pressure alarms after air trap fills U32 exemptPeriod = VENOUS_PRESSURE_EXEMPTION_PERIOD; // minimumMonitoring Window helps to check and raise low venous pressure alarm on a case where repeated fill events occurrence. // During this interval, if another airtrap fill occurs, there is no exemptions provided to stabilize the pressure and low venous pressure being raised when it goes below threshold value. U32 minimumMonitoringWindow = exemptPeriod + MIN_TIME_BETWEEN_AIR_TRAP_FILL_EXEMPTIONS_WINDOW ; venPresLow = ( venPres < (F32)currentVenousMinLimit ? TRUE : FALSE ); venPresHigh = ( venPres > (F32)currentVenousMaxLimit ? TRUE : FALSE ); // Check venous pressure is within alarm limits // Low venous pressure is checked after exemption period and before end of reset period(minimum monitoring window) or until next air trap fill occurs if ( ( venLowPresExemptAfterAirTrapFillTimerCtr > exemptPeriod ) && ( ( venLowPresExemptAfterAirTrapFillTimerCtr <= minimumMonitoringWindow ) || ( venLowPresExemptAfterAirTrapFillTimerCtr > prevVenLowPresExemptAfterAirTrapFillTimerCtr ) ) ) { if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_LOW, venPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_LOW, venPres, (F32)currentVenousMinLimit ); } } // during reset period, if airTrapValve open, still alarm needs to be raised , hence persistence clearance should happen before or after reset period. if ( ( airTrapValveState == STATE_OPEN ) && ( ( venLowPresExemptAfterAirTrapFillTimerCtr < exemptPeriod ) || ( venLowPresExemptAfterAirTrapFillTimerCtr > minimumMonitoringWindow ) ) ) { isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_LOW, FALSE ); } if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_HIGH, venPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_HIGH, venPres, (F32)currentVenousMaxLimit ); } // Reset exempt flag only after exempt period for the last fill and after reset period (minimum monitoring window) resetFillExemptPeriod = ( venLowPresExemptAfterAirTrapFillTimerCtr > minimumMonitoringWindow ? TRUE : FALSE ); prevVenLowPresExemptAfterAirTrapFillTimerCtr = venLowPresExemptAfterAirTrapFillTimerCtr ; } else { // Reset persistence if limits inactive isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_LOW, FALSE ); isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_HIGH, FALSE ); } } } /*********************************************************************//** * @brief * The checkPressureLimits function gets the pressure/occlusion data * publication interval. * @details Inputs: occlusion pressures for the pumps * @details Outputs: Alarm if occlusion limit exceeded * @return none *************************************************************************/ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); F32 filteredBpOccl = getFilteredBloodPumpOccl(); BOOL outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS ? TRUE : FALSE ); #ifndef _RELEASE_ if( HW_CONFIG_BETA == getHardwareConfigStatus() ) { outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS_V3 ? TRUE : FALSE ); } #endif #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif { F32 venPres = getMeasuredVenousPressure(); HD_OP_MODE_T hdMode = getCurrentOperationMode(); U32 hdSubMode = getCurrentSubMode(); BOOL ptxMode = ( MODE_PRET == hdMode && hdSubMode > HD_PRE_TREATMENT_CART_INSTALL_STATE ? TRUE : FALSE ); BOOL txModeRecirc = ( ( MODE_TREA == hdMode ) && ( TREATMENT_RECIRC_STATE == getTreatmentState() ) ? TRUE : FALSE ); BOOL txModeDialysis = ( ( MODE_TREA == hdMode ) && ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) ? TRUE : FALSE ); // Range check occlusion sensor (OB) if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, outOfRange ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl, bloodPumpOcclusionAfterCartridgeInstall ) } // Check for occlusion in PreTreatment modes when the cartridge is installed // and setOcclusionInstallLevel has been called. if ( MODE_PRET == hdMode ) { if ( ( TRUE == isBloodPumpRunning() ) && ( getPreTreatmentSubState() > HD_PRE_TREATMENT_CART_INSTALL_STATE ) && ( getDrySelfTestsState() > DRY_SELF_TESTS_START_STATE ) ) { // Check for occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_OCCLUSION_BLOOD_PUMP, bpOccl, OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) } } } // Check for occlusion in Treatment modes where pumps are moving else if ( MODE_TREA == hdMode ) { if ( TRUE == isBloodPumpRunning() ) { // Check for occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_OCCLUSION_BLOOD_PUMP, bpOccl, OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) } } } // Clear alarm regardless of op mode once conditions are met. if ( bpOccl <= ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { clearAlarmCondition( ALARM_ID_HD_OCCLUSION_BLOOD_PUMP ); } // Partial Occlusion check during treatment dialysis state and pressure stable or stabilization_2 state if ( ( TRUE == txModeDialysis ) && ( ( PRESSURE_LIMITS_STATE_STABLE == currPresLimitsState ) || ( PRESSURE_LIMITS_STATE_STABILIZATION_2 == currPresLimitsState ) ) ) { // Check for partial occlusion if ( filteredBpOccl > ( PARTIAL_OCCLUSION_THRESHOLD_OFFSET + getBloodPumpPartialOcclBaseline() ) ) { signalBloodPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_PARTIAL_OCCLUSION_BLOOD_PUMP, filteredBpOccl, PARTIAL_OCCLUSION_THRESHOLD_OFFSET + getBloodPumpPartialOcclBaseline() ) // Update partial occlusion baseline signalBloodPumpPressureOcclBaseline(); } } // Check for venous occlusion #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_VENOUS_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { // only trigger alarm if BP is running if ( isBloodPumpRunning() != FALSE ) { // must be in pre-treatment OR treatment recirculation mode to trigger this alarm if ( ( ( TRUE == ptxMode ) || ( TRUE == txModeRecirc ) ) && ( venPres > VENOUS_PRESSURE_LIMIT_MAX_MMHG + VENOUS_PRESSURE_OCCL_OFFSET_MMHG ) ) { if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, TRUE ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, venPres ); } } else { isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, FALSE ); } } else { isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, FALSE ); } } } } /*********************************************************************//** * @brief * The signalLowVenousPressureCheck function sets the low venous pressure Exempt check flag to increment the counter. * @details Inputs: lowVenousPressureExemptCheck * @details Outputs: lowVenousPressureExemptCheck * @return none. *************************************************************************/ void signalLowVenousPressureCheck( void ) { // When flag set, low venous pressure exempt counter increments. lowVenousPressureExemptCheck = TRUE; } /*********************************************************************//** * @brief * The getMeasuredArterialPressure function gets the current arterial pressure. * @details Inputs: arterialPressure * @details Outputs: none * @return the current arterial pressure (in mmHg). *************************************************************************/ F32 getMeasuredArterialPressure( void ) { F32 result = arterialPressure.data; if ( OVERRIDE_KEY == arterialPressure.override ) { result = arterialPressure.ovData; } 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 getF32OverrideValue( &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 * The getMeasuredVenousPressure function gets the measured venous pressure. * @details Inputs: venousPressure * @details Outputs: none * @return the current venous pressure (in mmHg). *************************************************************************/ F32 getMeasuredVenousPressure( void ) { F32 result = venousPressure.data; if ( OVERRIDE_KEY == venousPressure.override ) { result = venousPressure.ovData; } return result; } /*********************************************************************//** * @brief * The getFilteredBloodPumpOccl function gets the measured filtered blood pump occlusion. * @details Inputs: filteredBloodPumpOccl * @details Outputs: none * @return the current filtered blood pump occlusion. *************************************************************************/ F32 getFilteredBloodPumpOccl( void ) { return getF32OverrideValue( &filteredBloodPumpOccl ); } /*********************************************************************//** * @brief * The getBloodPumpPartialOcclBaseline function gets the blood pump partial occlusion baseline. * @details Inputs: bloodPumpPartialOcclusionBaseline * @details Outputs: none * @return the blood pump occlusion base line. *************************************************************************/ F32 getBloodPumpPartialOcclBaseline( void ) { return getF32OverrideValue( &bloodPumpPartialOcclusionBaseline ); } /*********************************************************************//** * @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 getF32OverrideValue( &shortFilteredVenousPressure ); } /*********************************************************************//** * @brief * The getLongFilteredVenousPressure function gets the current long filtered * venous pressure. * @details Inputs: longFilteredVenousPressure * @details Outputs: none * @return the current long filtered venous pressure (in mmHg). *************************************************************************/ F32 getLongFilteredVenousPressure( void ) { return longFilteredVenousPressure; } /*********************************************************************//** * @brief * The getMeasuredBloodPumpOcclusion function gets the measured blood pump * occlusion pressure. * @details Inputs: bloodPumpOcclusion * @details Outputs: none * @return the current blood pump occlusion pressure (in mmHg). *************************************************************************/ U32 getMeasuredBloodPumpOcclusion( void ) { U32 result = bloodPumpOcclusion.data; if ( OVERRIDE_KEY == bloodPumpOcclusion.override ) { result = bloodPumpOcclusion.ovData; } return result; } /*********************************************************************//** * @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 ) { // Long filter for arterial pressure. if ( artPressureReadingsLongCount >= SIZE_OF_LONG_ART_ROLLING_AVG ) { 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; // Short filter for arterial pressure. if ( artPressureReadingsShortCount >= SIZE_OF_SHORT_ART_ROLLING_AVG ) { 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.data = artPressureReadingsShortTotal / (F32)artPressureReadingsShortCount; // Long filter for venous pressure. if ( venPressureReadingsLongCount >= SIZE_OF_LONG_VEN_ROLLING_AVG ) { venPressureReadingsLongTotal -= venPressureReadingsLong[ venPressureReadingsLongIdx ]; } venPressureReadingsLong[ venPressureReadingsLongIdx ] = venPres; venPressureReadingsLongTotal += venPres; venPressureReadingsLongIdx = INC_WRAP( venPressureReadingsLongIdx, 0, SIZE_OF_LONG_VEN_ROLLING_AVG - 1 ); venPressureReadingsLongCount = INC_CAP( venPressureReadingsLongCount, SIZE_OF_LONG_VEN_ROLLING_AVG ); longFilteredVenousPressure = venPressureReadingsLongTotal / (F32)venPressureReadingsLongCount; // 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.data = venPressureReadingsShortTotal / (F32)venPressureReadingsShortCount; } /*********************************************************************//** * @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 = (F32)bloodPumpOcclReadingsTotal / (F32)bloodPumpOcclReadingsCount; } /*********************************************************************//** * @brief * The publishPresOcclData function publishes pressure/occlusion data at the * set interval. * @details Inputs: latest pressure and occlusion readings * @details Outputs: Pressure/occlusion data are published to CAN bus. * @return none *************************************************************************/ static void publishPresOcclData( void ) { // Publish pressure/occlusion data on interval if ( ++presOcclDataPublicationTimerCounter >= getU32OverrideValue( &presOcclDataPublishInterval ) ) { 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.bldPumpOcclusionLongFilter = getFilteredBloodPumpOccl(); data.partialOcclBaseline = getBloodPumpPartialOcclBaseline(); broadcastData( MSG_ID_PRESSURE_OCCLUSION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); presOcclDataPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The execPresOcclTest function executes the PresOccl self-test. * @details Inputs: none * @details Outputs: Triggers fault when test case fails * @return none *************************************************************************/ void execPresOcclTest( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif { U32 bpPressure = getMeasuredBloodPumpOcclusion(); F32 arterialPressure = getFilteredArterialPressure(); F32 venousPressure = getFilteredVenousPressure(); if ( bpPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SELF_TEST_FAILURE, bpPressure ); } 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 ); } if ( ( venousPressure < VENOUS_PRESSURE_SELF_TEST_MIN ) || ( venousPressure > VENOUS_PRESSURE_SELF_TEST_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_SELF_TEST_FAILURE, venousPressure ); } } } /*********************************************************************//** * @brief * The execPresOcclDryTest function executes the PresOccl dry self-test. * @details Inputs: 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 ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_OCCLUSION_SELF_TEST ) != SW_CONFIG_ENABLE_VALUE ) #endif { U32 bpPressure = getMeasuredBloodPumpOcclusion(); if ( ( bpPressure < CARTRIDGE_LOADED_THRESHOLD ) || ( bpPressure > OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CARTRIDGE_LOADED, bpPressure ); result = SELF_TEST_STATUS_FAILED; } } return result; } /*********************************************************************//** * @brief * The execPresOcclSelfTest function executes the PresOccl self-test. * @details Inputs: none * @details Outputs: pressureSensorsCalRecord, occlusionSensorsCalRecord * @return the result of the PresOccl self-test. *************************************************************************/ SELF_TEST_STATUS_T execPresOcclSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; BOOL calStatus = FALSE; // Get the pressure sensors and occlusion sensors calibration records calStatus |= getNVRecord2Driver( GET_CAL_PRESSURE_SENSORS, (U08*)&pressureSensorsCalRecord, sizeof( HD_PRESSURE_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_HD_PRESSURE_SESNSORS, ALARM_ID_NO_ALARM ); calStatus |= getNVRecord2Driver( GET_CAL_OCCLUSION_SESNSORS, (U08*)&occlusionSensorsCalRecord, sizeof( HD_OCCLUSION_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_OCCLUSION_SENSORS, ALARM_ID_NO_ALARM ); presOcclPostState = PRESSURE_TEST_STATE_COMPLETE; if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; } return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetPresOcclDataPublishIntervalOverride function overrides the * pressure and occlusion data publish interval. * @details Inputs: none * @details Outputs: presOcclDataPublishInterval * @param value override pressure and occlusion data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetPresOcclDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; presOcclDataPublishInterval.ovData = intvl; presOcclDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetPresOcclDataPublishIntervalOverride function resets the override * of the pressure and occlusion data publish interval. * @details Inputs: none * @details Outputs: presOcclDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetPresOcclDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; presOcclDataPublishInterval.override = OVERRIDE_RESET; presOcclDataPublishInterval.ovData = presOcclDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetArterialPressureOverride function overrides the measured arterial * pressure. * @details Inputs: none * @details Outputs: arterialPressure, shortFilteredArterialPressure * @param value override arterial pressure (in mmHg) * @param filtered override filtered value or raw value * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetArterialPressureOverride( F32 value, BOOL filtered ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( FALSE == filtered ) { arterialPressure.ovData = value; arterialPressure.override = OVERRIDE_KEY; } else { shortFilteredArterialPressure.ovData = value; shortFilteredArterialPressure.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetArterialPressureOverride function resets the override of the * arterial pressure. * @details Inputs: none * @details Outputs: arterialPressure, shortFilteredArterialPressure * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetArterialPressureOverride( BOOL filtered ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( FALSE == filtered ) { arterialPressure.override = OVERRIDE_RESET; arterialPressure.ovData = arterialPressure.ovInitData; } else { shortFilteredArterialPressure.override = OVERRIDE_RESET; shortFilteredArterialPressure.ovData = shortFilteredArterialPressure.ovInitData; } } return result; } /*********************************************************************//** * @brief * The testSetVenousPressureOverride function overrides the measured venous * pressure. * @details Inputs: none * @details Outputs: venousPressure, shortFilteredVenousPressure * @param value override measured venous pressure with (in mmHg) * @param filtered override filtered value or raw value * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetVenousPressureOverride( F32 value, BOOL filtered ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( FALSE == filtered ) { venousPressure.ovData = value; venousPressure.override = OVERRIDE_KEY; } else { shortFilteredVenousPressure.ovData = value; shortFilteredVenousPressure.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetVenousPressureOverride function resets the override of the * venous pressure. * @details Inputs: none * @details Outputs: venousPressure, shortFilteredVenousPressure * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetVenousPressureOverride( BOOL filtered ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( FALSE == filtered ) { venousPressure.override = OVERRIDE_RESET; venousPressure.ovData = venousPressure.ovInitData; } else { shortFilteredVenousPressure.override = OVERRIDE_RESET; shortFilteredVenousPressure.ovData = shortFilteredVenousPressure.ovInitData; } } return result; } /*********************************************************************//** * @brief * The testSetBloodPumpOcclusionOverride function overrides the measured * blood pump occlusion pressure. * @details Inputs: none * @details Outputs: bloodPumpOcclusion * @param value override measured blood pump occlusion pressure with * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodPumpOcclusionOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpOcclusion.ovData = value; bloodPumpOcclusion.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBloodPumpOcclusionOverride function resets the override of the * measured blood pump occlusion pressure. * @details Inputs: none * @details Outputs: bloodPumpOcclusion * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodPumpOcclusionOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpOcclusion.override = OVERRIDE_RESET; bloodPumpOcclusion.ovData = bloodPumpOcclusion.ovInitData; } 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( F32 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; } /*********************************************************************//** * @brief * The testSetBloodPumpPartialOcclusionOverride function overrides the * blood pump partial occlusion pressure baseline. * @details Inputs: none * @details Outputs: bloodPumpPartialOcclusionBaseline * @param value override blood pump occlusion baseline * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodPumpPartialOcclusionBaselineOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpPartialOcclusionBaseline.ovData = value; bloodPumpPartialOcclusionBaseline.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBloodPumpPartialOcclusionBaselineOverride function resets the override of the * blood pump partial occlusion baseline. * @details Inputs: none * @details Outputs: bloodPumpPartialOcclusionBaseline * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodPumpPartialOcclusionBaselineOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpPartialOcclusionBaseline.override = OVERRIDE_RESET; bloodPumpPartialOcclusionBaseline.ovData = bloodPumpPartialOcclusionBaseline.ovInitData; } return result; } /**@}*/