/************************************************************************** * * Copyright (c) 2019-2020 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 SelfTests.c * * @author (last) Quang Nguyen * @date (last) 28-Jan-2021 * * @author (original) Quang Nguyen * @date (original) 28-Jan-2021s * ***************************************************************************/ #include "AirTrap.h" #include "BloodFlow.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "FPGA.h" #include "PresOccl.h" #include "SelfTests.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup SelfTests * @{ */ // ********** private definitions ********** #define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. #define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. #define BLOOD_LEAK_SELF_TEST_SET 0x1 ///< Initiate blood leak self-test. #define BLOOD_LEAK_NORMAL_OPERATION 0x0 ///< Return blood leak to normal operation. #define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. #define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -50.0 ///< Arterial pressure low limit after running blood pump. #define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 400 ///< Venous pressure high limit after running blood pump. #define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). /// No cartridge self-tests state machine. typedef enum No_Cart_Self_Tests_State { NO_CART_SELF_TESTS_START_STATE = 0, ///< No cartridge self-tests starting state. NO_CART_SELF_TESTS_WAIT_FOR_CLOSED_DOOR, ///< Wait for door to be closed before running self-tests. NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE, ///< No cartridge occlusion sensors self-test state. NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE, ///< No cartridge blood flow meter self-test state. NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE, ///< No cartridge dialysate flow meter self-test state. NO_CART_SELF_TESTS_PUMPS_STATE, ///< No cartridge self-test for blood pump, dialysate in pump, dialysate out pump state. NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE, ///< No cartridge leak detectors self-test state. NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE, ///< No cartridge board temperature self-test state. NO_CART_SELF_TESTS_DOOR_SWITCH_STATE, ///< No cartridge door switch self-test state. NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE, ///< No cartridge home valves and pumps self-test state. NO_CART_SELF_TESTS_HOME_IDLE_STATE, ///< Wait for valves and pumps finish homing state. NO_CART_SELF_TESTS_COMPLETE, ///< No cartridge self-test complete state. NUM_OF_NO_CART_SELF_TESTS_STATES ///< Number of no cartridge self-tests states. } NO_CART_SELF_TESTS_STATE_T; /// Dry self-tests state machine. typedef enum Dry_Self_Tests_State { DRY_SELF_TESTS_START_STATE = 0, ///< Dry self-tests starting state. DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors dry self-test state. DRY_SELF_TESTS_AIR_TRAP_STATE, ///< Air trap fill level ultrasonic sensor dry self-test state. DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE, ///< Occlusion sensors dry self-test state. DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE, ///< Pressure sensors dry self-test setup valves and pump state. DRY_SELF_TESTS_PRESSURE_SENSORS_STATE, ///< Pressure sensors verify pressure readings state. DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE, ///< Preassure sensors verify normal pressure readings state. DRY_SELF_TESTS_COMPLETE, ///< Dry self-test complete state. NUM_OF_DRY_SELF_TESTS_STATES ///< Number of dry self-tests states. } DRY_SELF_TESTS_STATE_T; /// Wet self-tests state machine. typedef enum Wet_Self_Tests_State { WET_SELF_TESTS_START_STATE = 0, ///< Wet self-tests starting state. WET_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors wet self-tests state. WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE, ///< Fill reservoir 1 with 100 mL of dialysate from reservoir 2 start state. WET_SELF_TESTS_COMPLETE, ///< Wet self-test complete state. NUM_OF_WET_SELF_TESTS_STATES ///< Number of wet self-tests states. } WET_SELF_TESTS_STATE_T; // ********** private data ********** static BOOL noCartSelfTestsResult; ///< Result of no cartridge self-tests. static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; ///< Current state of the no cartridge self-tests state machine. static U32 runPumpStartTime; ///< Beginning time when pumps start running static BOOL hasPumpsStarted; ///< Flag indicates if pumps have started running for self-test. static BOOL drySelfTestsResult; ///< Result of dry self-tests. static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of the dry self-tests state machine. static U32 pressureSelfTestBloodPumpRunStartTime; ///< Pressure dry self-test blood pump runs start time. static F32 previousNormalArterialPressure; ///< Holds the previous normal arterial pressure reading. static F32 previousNormalVenousPressure; ///< Holds the previous normal venous pressure reading. static BOOL wetSelfTestsResult; ///< Result of wet self-tests. static WET_SELF_TESTS_STATE_T currentWetSelfTestsState; ///< Current state of the wet self-tests state machine. // ********** private function prototypes ********** static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestBubbleDetectorsState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestAirTrapState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); /*********************************************************************//** * @brief * The initSelfTests function initializes the SelfTests module. * @details Inputs: none * @details Outputs: SelfTests module initialized. * @return none *************************************************************************/ void initSelfTests( void ) { } /*********************************************************************//** * @brief * The transitionToNoCartSelfTests function resets anything required before * the start of no cartridge self-tests. * @details Inputs: none * @details Outputs: No cartridge self-tests re-initialized. * @return none *************************************************************************/ void transitionToNoCartSelfTests( void ) { noCartSelfTestsResult = FALSE; hasPumpsStarted = FALSE; currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; runPumpStartTime = 0; } /*********************************************************************//** * @brief * The execNoCartSelfTests function executes the no cartridge self-tests * state machine. * @details Inputs: currentNoCartSelfTestsState * @details Outputs: currentNoCartSelfTestsState, noCartSelfTestsResult * @return none *************************************************************************/ void execNoCartSelfTests( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; // execute no cartridge self-tests state machine switch ( currentNoCartSelfTestsState ) { case NO_CART_SELF_TESTS_START_STATE: #ifdef SKIP_SELF_TESTS currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; #else currentNoCartSelfTestsState = NO_CART_SELF_TESTS_WAIT_FOR_CLOSED_DOOR; #endif break; case NO_CART_SELF_TESTS_WAIT_FOR_CLOSED_DOOR: currentNoCartSelfTestsState = handleNoCartSelfTestsWaitForClosedDoor(); break; case NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE: result = execPresOcclTest(); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE: result = execBloodFlowTest(); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE: result = execDialInFlowTest(); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_PUMPS_STATE; break; case NO_CART_SELF_TESTS_PUMPS_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestPumpsState(); break; case NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestLeakDetectorsState( &result ); break; case NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE: // TODO: Implement self tests currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DOOR_SWITCH_STATE; break; case NO_CART_SELF_TESTS_DOOR_SWITCH_STATE: // TODO: Implement self tests currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; break; case NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestHomeValvesAndPumpState(); break; case NO_CART_SELF_TESTS_HOME_IDLE_STATE: if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) { currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE; } break; case NO_CART_SELF_TESTS_COMPLETE: noCartSelfTestsResult = TRUE; break; default: currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_NO_CARTRIDGE_SELF_TEST_STATE, (U32)currentNoCartSelfTestsState ); break; } if ( SELF_TEST_STATUS_FAILED == result ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); } } /*********************************************************************//** * @brief * The isNoCartSelfTestsPassed function returns the status of no cartridge self-tests. * @details Inputs: none * @details Outputs: none * @return TRUE if no cartridge self-tests passed, otherwise FALSE *************************************************************************/ BOOL isNoCartSelfTestsPassed( void ) { return noCartSelfTestsResult; } /*********************************************************************//** * @brief * The transitionToDrySelfTests function resets anything required before * the start of dry self-tests. * @details Inputs: none * @details Outputs: Dry self-tests re-initialized. * @return none *************************************************************************/ void transitionToDrySelfTests() { drySelfTestsResult = FALSE; currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; } /*********************************************************************//** * @brief * The execDrySelfTests function executes the dry self-tests state machine. * @details Inputs: currentDrySelfTestsState * @details Outputs: currentDrySelfTestsState, drySelfTestsResult * @return none *************************************************************************/ void execDrySelfTests( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; // execute dry self-tests state machine switch ( currentDrySelfTestsState ) { case DRY_SELF_TESTS_START_STATE: #ifdef SKIP_SELF_TESTS currentDrySelfTestsState = DRY_SELF_TESTS_COMPLETE; #else currentDrySelfTestsState = DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE; #endif break; case DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE: currentDrySelfTestsState = handleDrySelfTestBubbleDetectorsState(); break; case DRY_SELF_TESTS_AIR_TRAP_STATE: currentDrySelfTestsState = handleDrySelfTestAirTrapState(); break; case DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE: if ( SELF_TEST_STATUS_PASSED == execPresOcclDryTest() ) { currentDrySelfTestsState = DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE; } break; case DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestPressureSensorsSetupState(); break; case DRY_SELF_TESTS_PRESSURE_SENSORS_STATE: currentDrySelfTestsState = handleDrySelfTestPressureSensorsState( &result ); break; case DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE: currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalState( &result ); break; case DRY_SELF_TESTS_COMPLETE: drySelfTestsResult = TRUE; break; default: currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_DRY_SELF_TEST_STATE, (U32)currentDrySelfTestsState ); break; } if ( SELF_TEST_STATUS_FAILED == result ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentDrySelfTestsState ); } } /*********************************************************************//** * @brief * The isDrySelfTestsPassed function returns the status of dry self-tests. * @details Inputs: none * @details Outputs: none * @return TRUE if dry self-tests passed, otherwise FALSE *************************************************************************/ BOOL isDrySelfTestsPassed( void ) { return drySelfTestsResult; } /*********************************************************************//** * @brief * The transitionToWetSelfTests function resets anything required before * the start of wet self-tests. * @details Inputs: none * @details Outputs: Wet self-tests re-initialized. * @return none *************************************************************************/ void transitionToWetSelfTests() { wetSelfTestsResult = FALSE; currentWetSelfTestsState = WET_SELF_TESTS_START_STATE; } /*********************************************************************//** * @brief * The execWetSelfTests function executes the wet self-tests state machine. * @details Inputs: currentWetSelfTestsState * @details Outputs: currentWetSelfTestsState, wetSelfTestsResult * @return none *************************************************************************/ void execWetSelfTests( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; // execute wet self-tests state machine switch ( currentWetSelfTestsState ) { case WET_SELF_TESTS_START_STATE: #ifdef SKIP_SELF_TESTS currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; #else currentWetSelfTestsState = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; #endif break; case WET_SELF_TESTS_BUBBLE_DETECTOR_STATE: { BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); if ( ( FALSE == isADADetectedAir ) && ( FALSE == isADADetectedAir ) ) { currentWetSelfTestsState = WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE; } else { result = SELF_TEST_STATUS_FAILED; } } break; case WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE: currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; break; case WET_SELF_TESTS_COMPLETE: wetSelfTestsResult = TRUE; break; default: currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_WET_SELF_TEST_STATE, (U32)currentWetSelfTestsState ); break; } if ( SELF_TEST_STATUS_FAILED == result ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentWetSelfTestsState ); } } /*********************************************************************//** * @brief * The isDrySelfTestsPassed function returns the status of wet self-tests. * @details Inputs: none * @details Outputs: none * @return TRUE if wet self-tests passed, otherwise FALSE *************************************************************************/ BOOL isWetSelfTestsPassed( void ) { return wetSelfTestsResult; } /*********************************************************************//** * @brief * The handleNoCartridgeWaitForClosedDoor function executes the wait for * door to be closed state of no cartridge self-tests state machine. * @details Inputs: none * @details Outputs: none * @return the next state of no cartridge self-tests state machine *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ) { NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_WAIT_FOR_CLOSED_DOOR; signalBloodPumpHardStop(); signalDialInPumpHardStop(); signalDialOutPumpHardStop(); if ( STATE_CLOSED == getFPGADoorState() ) { state = NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE; } return state; } /*********************************************************************//** * @brief * The handleNoCartSelfTestPumpsState function runs blood, dialysate inlet, * dialysate outlet pumps for certain time to make sure no alarms occur. * @details Inputs: none * @details Outputs: none * @return the next state of no cartridge self-tests state machine *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ) { NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_PUMPS_STATE; if ( FALSE == hasPumpsStarted ) { hasPumpsStarted = TRUE; setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); runPumpStartTime = getMSTimerCount(); } if ( TRUE == didTimeout( runPumpStartTime, PUMP_RUN_SELF_TEST_TIME_MS ) ) { signalBloodPumpHardStop(); signalDialInPumpHardStop(); signalDialOutPumpHardStop(); setFPGASensorTest( BLOOD_LEAK_SELF_TEST_SET ); state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; } return state; } /*********************************************************************//** * @brief * The handleNoCartSelfTestHomeValvesAndPumpState function homes all valves * and pumps. * @details Inputs: none * @details Outputs: none * @return the next state of no cartridge self-tests state machine *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ) { VALVE_T valve; for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) { homeValve( valve ); } homeBloodPump(); homeDialInPump(); homeDialOutPump(); return NO_CART_SELF_TESTS_HOME_IDLE_STATE; } /*********************************************************************//** * @brief * The handleNoCartSelfTestLeakDetectorsState function verify leak detectors status. * @details Inputs: none * @details Outputs: none * @return the next state of no cartridge self-tests state machine *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ) { NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; if ( TRUE == getFPGABloodLeakDetectorStatus() ) { setFPGASensorTest( BLOOD_LEAK_NORMAL_OPERATION ); state = NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE; } else { *result = SELF_TEST_STATUS_FAILED; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestBubbleDetectorsState function verify no fluid is detected * by bubble detectors. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestBubbleDetectorsState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE; BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); if ( ( TRUE == isADADetectedAir ) && ( TRUE == isADADetectedAir ) ) { state = DRY_SELF_TESTS_AIR_TRAP_STATE; } else { activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestAirTrapState function verify no fluid is detected * by air trap. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestAirTrapState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_AIR_TRAP_STATE; if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) { state = DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE; } else { activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureSensorsSetupState function handles the setup * for pressure sensors dry self-test. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsSetupState( void ) { previousNormalArterialPressure = getMeasuredArterialPressure(); previousNormalVenousPressure = getMeasuredVenousPressure(); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); setValveAirTrap( STATE_CLOSED ); setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); pressureSelfTestBloodPumpRunStartTime = getMSTimerCount(); return DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureSensorsState function tests the readings of * pressure sensors and verify they are in correct range. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; F32 const arterialPressure = getMeasuredArterialPressure(); F32 const venousPressure = getMeasuredVenousPressure(); if ( ( TRUE == didTimeout( pressureSelfTestBloodPumpRunStartTime, BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ) ) || ( ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG >= arterialPressure ) || ( VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG <= venousPressure ) ) { if ( ( arterialPressure < 0) && ( venousPressure > 0 ) ) { setValvePosition( VBV, VALVE_POSITION_B_OPEN ); setValveAirTrap( STATE_CLOSED ); state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; } else { *result = SELF_TEST_STATUS_FAILED; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureSensorsNormalState function verify the readings of * pressure sensors after returning to normal state. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure); F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure); if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) { state = DRY_SELF_TESTS_COMPLETE; } else { *result = SELF_TEST_STATUS_FAILED; } return state; } /**@}*/