Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r88696f3c6a5d82503064a73433d39fa000728d93 -r3fc2a198a40b588b8d1a5684838be098456ad023 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 88696f3c6a5d82503064a73433d39fa000728d93) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 3fc2a198a40b588b8d1a5684838be098456ad023) @@ -1,24 +1,37 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2023 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 +* @file SelfTests.c * -* @author (last) Quang Nguyen -* @date (last) 28-Jan-2021 +* @author (last) Michael Garthwaite +* @date (last) 08-Mar-2023 * -* @author (original) Quang Nguyen -* @date (original) 28-Jan-2021s +* @author (original) Quang Nguyen +* @date (original) 28-Jan-2021 * ***************************************************************************/ +#include "AirPump.h" +#include "AirTrap.h" #include "BloodFlow.h" +#include "BloodLeak.h" +#include "Bubble.h" +#include "DGInterface.h" #include "DialInFlow.h" +#include "DialOutFlow.h" +#include "FPGA.h" +#include "ModeTreatmentParams.h" #include "PresOccl.h" #include "SelfTests.h" +#include "SyringePump.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Valves.h" /** * @addtogroup SelfTests @@ -27,127 +40,2051 @@ // ********** private definitions ********** -/// 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_OCCLUSION_SENSORS, ///< No cartridge self-test for occlusion sensors. - NO_CART_SELF_TESTS_BLOOD_FLOW_METERS, ///< No cartridge self-test for blood flow meter. - NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS, ///< No cartridge self-test for dialysate flow meter. - NO_CART_SELF_TESTS_VALVE_BLOOD_TRAP, ///< No cartridge self-test for valve blood trap. - NO_CART_SELF_TESTS_PUMPS, ///< No cartridge self-test for blood pump, dialysate in pump, dialysate out pump. - NO_CART_SELF_TESTS_LEAK_DETECTORS, ///< No cartridge self-test for leak detectors. - NO_CART_SELF_TESTS_BOARD_TEMPERATURE, ///< No cartridge self-test for board temperature. - NO_CART_SELF_TESTS_DOOR_SWITCH, ///< No cartridge self-test for door switch. - 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; +#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_PUMP_PRESSURE_SELF_TEST_FLOW 100 +#define DIAL_IN_PUMP_PRESSURE_SELF_TEST_FLOW 400 +#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay 1 second then check for syringe pump prime occlusion. +#define PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ( 1 * MS_PER_SECOND ) ///< Delay 1 second prior to getting initial normal baseline pressures. +#define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 30 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. +#define VENOUS_PRESSURE_SELF_TEST_MAX_TEST_TIME ( 60 * MS_PER_SECOND ) ///< Pressure self-test time to run venous self test in ms. +#define DECAY_PRESSURE_SELF_TEST_TIME ( 4 * MS_PER_SECOND ) ///< time to wait for pressure to decay in ms. +#define STABILTY_PRESSURE_SELF_TEST_TIME ( 5 * MS_PER_SECOND ) ///< Time to wait for pressure to stabilize in ms. +#define NORMALIZED_PRESSURE_SELF_TEST_TIME ( 20 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize in ms. +#define NORMALIZED_PRESSURE_SELF_TEST_VBT_TIMER ( 1 * MS_PER_SECOND ) ///< Time to wait until we open VBT during normal pressure tests. +#define NORMALIZED_PRESSURE_SELF_TEST_VBT_TIMERX ( 7 * MS_PER_SECOND ) ///< Time to wait until we open VBT during normal pressure tests (for old builds that don't support air pump). +#define NORMALIZED_PRESSURE_SELF_TEST_VDI_TIMER ( 5 * MS_PER_SECOND ) ///< Time to wait until we open VDI during normal pressure tests. + +#define ARTERIAL_DECAY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in arterial pressure readings after the pump stops (in mmHg). +#define VENOUS_DECAY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in venous pressure readings after the pump stops (in mmHg). +#define ARTERIAL_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in arterial pressure readings while in a stable pressured state (in mmHg). +#define VENOUS_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in venous pressure readings while in a stable pressured state (in mmHg). + +#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -200.0F ///< Arterial pressure low limit after running blood pump. +#define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 200.0F ///< Venous pressure high limit after running blood pump. +#define VENOUS_PRESSURE_SELF_TEST_FIRST_PASS_LIMIT_MMHG 250.0F ///< Venous pressure high limit after running air pump in first test. + +#define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 20.0F ///< Difference in pressure readings after return to normal state tolerance (in mmHg). + +#define DIP_FLOW_RATE_SETUP_ML_MIN 150 ///< Dialysate inlet pump flow rate during the setup for wet self-test. +#define DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN 100 ///< Dialysate inlet pump flow rate during the first displacement in wet self-test. +#define DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 600 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. + +#define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100.0F ///< Target of first displacement volume in ml. +#define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 600.0F ///< Target of second displacement volume in ml. +#define WET_SELF_TEST_INTEGRATED_VOLUME_PCT_TOLERANCE 0.10F ///< Tolerance on integrated volume as a percentage (10%). +#define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 20.0F ///< Tolerance on integrated volume in grams. +#define WET_SELF_TEST_INTEGRATED_VOLUME_WIDER_TOLERANCE 100.0F ///< Wider tolerance on integrated volume in grams, during debug. +#define WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G 20.0F ///< Tolerance in the load cell readings of the displacement in grams. +#define WET_SELF_TEST_FIRST_DISPLACEMENT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Time to displace dialysate in wet self-test in ms (first). +#define WET_SELF_TEST_SECOND_DISPLACEMENT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Time to displace dialysate in wet self-test in ms (second). +#define RESERVOIR_SETTLE_TIME_MS ( 5 * MS_PER_SECOND ) ///< Time allotted for reservoir to settle in ms. + +#define MAX_NO_CARTRIDGE_SELF_TEST_TIME 30 ///< Maximum no cartridge self-test time (in seconds). +#define MAX_DRY_SELF_TEST_TIME ( 12 * SEC_PER_MIN ) ///< Maximum dry self-test time (in seconds). +#define CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Time (in ms) required to wait for occlusion pressure to settle after cartridge insertion. + +#define SELF_TEST_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND ) ///< Interval (ms/task time) at which self-test time data is published on the CAN bus. + +#define PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG 10.0F ///< Prior to dry pressure leak test, arterial and venous pressure sensors should read zero +/- this tolerance. +#define MAX_EMPTY_RESERVOIR_WEIGHT_G 15.0F ///< Maximum reservoir weight to be considered empty for cartridge pressure leak test. + // ********** private data ********** -static BOOL isNoCartSelfTestsResult; -static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; +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 havePumpsStartedForNCST; ///< Flag indicates pumps have started running for no cartridge pumps self-test. +static BOOL pumpHomingRequestedForNCST; ///< Flag indicates pumps should be homed after running no cartridge pumps self-test. +static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of the dry self-tests state machine. +static U32 pressureSelfTestPreNormalStartTime; ///< Pressure dry self-test pre-normal start time. +static U32 pressureSelfTestBloodPumpRunStartTime; ///< Pressure dry self-test blood pump runs start time. +static U32 pressureSelfTestVenousTestStartTime; ///< Pressure dry self-test dip runs start time. +static U32 pressureSelfTestNormalizedStartTime; ///< Normalized pressure dry self-test start time. +static U32 pressureSelfTestDecayStartTime; ///< Decay pressure dry self-test start time. +static U32 pressureSelfTestStabilityStartTime; ///< Stability pressure dry self-test start time. +static F32 previousNormalArterialPressure; ///< Holds the previous normal arterial pressure reading. +static F32 previousNormalVenousPressure; ///< Holds the previous normal venous pressure reading. +static F32 peakArterialPressure; ///< Holds the peak arterial pressure reading. +static F32 peakVenousPressure; ///< Holds the peak normal venous pressure reading. +static F32 decayedArterialPressure; ///< Holds the decayed arterial pressure reading after blood pump is stopped. +static F32 decayedVenousPressure; ///< Holds the decayed venous pressure reading after blood pump is stopped. +static BOOL dryPressureTestsCompleted; ///< Flag indicates dry cartridge pressure leak testing has been completed. + +static BOOL wetSelfTestsResult; ///< Result of wet self-tests. +static WET_SELF_TESTS_STATE_T currentWetSelfTestsState; ///< Current state of the wet self-tests state machine. +static U32 settleStartTime; ///< Wait for reservoir to settle start time. +static U32 displacementStartTime; ///< Dialysate displacement starting time. +static F32 fmdIntegratedVolume; ///< FMD integrated volume over displacement time. +static F32 reservoirVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Hold the current volume of all reservoirs. +static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been sent to DG. + +static U32 selfTestCartridgeSettleTime; ///< Cartridge settle start time. +static U32 selfTestStartTime; ///< Starting time of self-test (in ms). +static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). +static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. + +static BOOL useHeparin; ///< Flag indicates the user of heparin. + +static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. + // ********** private function prototypes ********** +static void resetSelfTestsFlags( void ); +static void setupForSelfTestsStop( void ); + +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeSyringePumpState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeIdleState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ); + +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStartState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestCartridgeLoadedCheckState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsDecayState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsStabilityState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); + +static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestStoppedState( void ); + /*********************************************************************//** * @brief - * The initPrime function initializes the prime sub-mode module. - * This function will reset anything required before the start of priming sequence. + * The initSelfTests function initializes the SelfTests module. * @details Inputs: none - * @details Outputs: Prime sub-mode module initialized. + * @details Outputs: SelfTests module initialized. * @return none *************************************************************************/ void initSelfTests( void ) { - isNoCartSelfTestsResult = FALSE; - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; + selfTestStartTime = 0; + selfTestPreviousPublishDataTime = 0; + syringeOcclusionDelayStartTime = 0; } /*********************************************************************//** * @brief - * The execSelfTests function executes the prime sub-mode state machine. - * @details Inputs: currentPrimeState - * @details Outputs: currentPrimeState + * The signalResumeSelfTests function signals the self-tests to resume + * previous operation. + * @details Inputs: none + * @details Outputs: primeResumeRequested * @return none *************************************************************************/ +void signalResumeSelfTests( void ) +{ + selfTestsResumeRequested = TRUE; +} + +/*********************************************************************//** + * @brief + * The resetSelfTestsFlags function resets all self-tests signal flags. + * @details Inputs: none + * @details Outputs: signal flags set to FALSE + * @return none + *************************************************************************/ +static void resetSelfTestsFlags( void ) +{ + selfTestsResumeRequested = FALSE; +} + +/*********************************************************************//** + * @brief + * The setupForSelfTestsStop function sets actuators appropriately for self-tests + * states. + * @details Inputs: none + * @details Outputs: All pumps stopped + * @return none + *************************************************************************/ +static void setupForSelfTestsStop( void ) +{ + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + + if ( TRUE == isAlarmActive( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM ) ) + { + retractSyringePump(); + } + else + { + stopSyringePump(); + } + + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); +} + +/*********************************************************************//** + * @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 ) +{ + F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) ) + { + useHeparin = FALSE; + } + else +#endif + { + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ? TRUE : FALSE ); + } + + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + runPumpStartTime = 0; + havePumpsStartedForNCST = FALSE; + pumpHomingRequestedForNCST = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); + + doorClosedRequired( TRUE, TRUE ); + + // Pumps should be off + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + stopSyringePump(); + + // Set valves to default positions + setValveAirTrap( STATE_CLOSED ); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); + + resetSelfTestsFlags(); +} + +/*********************************************************************//** + * @brief + * The execNoCartSelfTests function executes the no cartridge self-tests + * state machine. + * @details Inputs: currentNoCartSelfTestsState + * @details Outputs: currentNoCartSelfTestsState + * @return none + *************************************************************************/ void execNoCartSelfTests( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + NO_CART_SELF_TESTS_STATE_T priorSubState = currentNoCartSelfTestsState; // execute no cartridge self-tests state machine switch ( currentNoCartSelfTestsState ) { - case NO_CART_SELF_TESTS_START_STATE: - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_OCCLUSION_SENSORS; + case NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestsWaitForClosedDoor(); break; - case NO_CART_SELF_TESTS_OCCLUSION_SENSORS: - result = execPresOcclTest(); - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS; + case NO_CART_SELF_TESTS_PRESSURE_CHECKS_STATE: + execPresOcclTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_STATE; break; - case NO_CART_SELF_TESTS_BLOOD_FLOW_METERS: - result = execBloodFlowTest(); - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS; + case NO_CART_SELF_TESTS_HOME_VALVES_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestHomeValvesState(); break; - case NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS: - result = execDialInFlowTest(); - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_VALVE_BLOOD_TRAP; + case NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestHomeSyringePumpState(); break; - case NO_CART_SELF_TESTS_VALVE_BLOOD_TRAP: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_PUMPS; + case NO_CART_SELF_TESTS_PUMPS_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestPumpsState(); break; - case NO_CART_SELF_TESTS_PUMPS: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_LEAK_DETECTORS; + case NO_CART_SELF_TESTS_HOME_IDLE_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestHomeIdleState(); break; - case NO_CART_SELF_TESTS_LEAK_DETECTORS: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BOARD_TEMPERATURE; + case NO_CART_SELF_TESTS_STOPPED_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestStoppedState(); break; - case NO_CART_SELF_TESTS_BOARD_TEMPERATURE: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DOOR_SWITCH; + case NO_CART_SELF_TESTS_COMPLETE_STATE: break; - case NO_CART_SELF_TESTS_DOOR_SWITCH: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE; + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_NO_CARTRIDGE_SELF_TEST_STATE, currentNoCartSelfTestsState ); break; + } - case NO_CART_SELF_TESTS_COMPLETE: - isNoCartSelfTestsResult = TRUE; + // Self-tests flags should be handled by now, reset if flags not handled with current state + resetSelfTestsFlags(); + + if ( priorSubState != currentNoCartSelfTestsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentNoCartSelfTestsState ); + } + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) + { + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + + if ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ) + { + SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; + + data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; + data.countdown = ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); + broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); + } + else + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CART_SELF_TEST_TIMEOUT, currentNoCartSelfTestsState ); + } + } +} + +/*********************************************************************//** + * @brief + * The getNoCartSelfTestsState function returns the current state of no + * cartridge self-tests sub-mode. + * @details Inputs: currentNoCartSelfTestsState + * @details Outputs: none + * @return current no cartridge self-tests state + *************************************************************************/ +U32 getNoCartSelfTestsState( void ) +{ + return (U32)currentNoCartSelfTestsState; +} + +/*********************************************************************//** + * @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() +{ + currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; + pressureSelfTestBloodPumpRunStartTime = 0; + pressureSelfTestNormalizedStartTime = 0; + previousNormalArterialPressure = 0.0; + previousNormalVenousPressure = 0.0; + dryPressureTestsCompleted = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); + selfTestCartridgeSettleTime = getMSTimerCount(); + doorClosedRequired( FALSE, TRUE ); + + // Pumps should be off + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + stopSyringePump(); + + // Set valves to default positions + setValveAirTrap( STATE_CLOSED ); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); + + resetSelfTestsFlags(); +} + +/*********************************************************************//** + * @brief + * The execDrySelfTests function executes the dry self-tests state machine. + * @details Inputs: currentDrySelfTestsState + * @details Outputs: currentDrySelfTestsState, pressureSelfTestPreNormalStartTime + * @return none + *************************************************************************/ +void execDrySelfTests( void ) +{ + DRY_SELF_TESTS_STATE_T priorSubState = currentDrySelfTestsState; + + // execute dry self-tests state machine + switch ( currentDrySelfTestsState ) + { + case DRY_SELF_TESTS_START_STATE: + currentDrySelfTestsState = handleDrySelfTestStartState(); break; + case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: + currentDrySelfTestsState = handleDrySelfTestWaitForDoorCloseState(); + break; + + case DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestUsedCartridgeCheckState(); + break; + + case DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestCartridgeLoadedCheckState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalSetupState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsVenousSetupState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsVenousState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_ARTERIAL_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsArterialSetupState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_ARTERIAL: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsArterialState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_DECAY_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsDecayState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_STABILITY_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsStabilityState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalState(); + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpOcclusionDetectionState(); + break; + + case DRY_SELF_TESTS_STOPPED_STATE: + currentDrySelfTestsState = handleDrySelfTestStoppedState(); + break; + + case DRY_SELF_TESTS_COMPLETE_STATE: + 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 ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_DRY_SELF_TEST_STATE, currentDrySelfTestsState ); break; } - if ( SELF_TEST_STATUS_FAILED == result ) + // Self-tests flags should be handled by now, reset if flags not handled with current state + resetSelfTestsFlags(); + + if ( priorSubState != currentDrySelfTestsState ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRETREATMENT_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDrySelfTestsState ); } + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) + { + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + SELF_TEST_DRY_PAYLOAD_T data; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + + data.timeout = MAX_DRY_SELF_TEST_TIME; + data.countdown = ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); + broadcastData( MSG_ID_HD_DRY_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_DRY_PAYLOAD_T ) ); + } } /*********************************************************************//** * @brief - * The isNoCartSelfTestsPassed function returns the status of no cartridge self-tests. + * The getDrySelfTestsState function returns the current state of dry self-tests sub-mode. + * @details Inputs: currentDrySelfTestsState + * @details Outputs: none + * @return current dry self-tests state + *************************************************************************/ +U32 getDrySelfTestsState( void ) +{ + return (U32)currentDrySelfTestsState; +} + +/*********************************************************************//** + * @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; + settleStartTime = 0; + displacementStartTime = 0; + fmdIntegratedVolume = 0.0; + isValvesSettingSent = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); + + // Pumps should be off + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + stopSyringePump(); + + // Set valves to default positions + setValveAirTrap( STATE_CLOSED ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + + resetSelfTestsFlags(); +} + +/*********************************************************************//** + * @brief + * The execWetSelfTests function executes the wet self-tests state machine. + * @details Inputs: currentWetSelfTestsState + * @details Outputs: currentWetSelfTestsState, wetSelfTestsResult + * @return none + *************************************************************************/ +void execWetSelfTests( void ) +{ + WET_SELF_TESTS_STATE_T priorSubState = currentWetSelfTestsState; + +#ifndef _RELEASE_ + if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_WET_SELF_TEST ) ) ) + { + currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE_STATE; + } +#endif + + // execute wet self-tests state machine + switch ( currentWetSelfTestsState ) + { + case WET_SELF_TESTS_START_STATE: + currentWetSelfTestsState = handleWetSelfTestStartState(); + break; + + case WET_SELF_TESTS_BUBBLE_CHECK_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestSetupState(); + break; + + case WET_SELF_TESTS_BUBBLE_CHECK_STATE: + currentWetSelfTestsState = handleWetSelfTestBubblesState(); + break; + + case WET_SELF_TESTS_PRIME_CHECK_STATE: + currentWetSelfTestsState = handleWetSelfTestPrimeCheckState(); + break; + + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE: + currentWetSelfTestsState = handleWetSelfTestBloodLeakDetectorState(); + break; + + case WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementSetupState(); + break; + + case WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementState(); + break; + + case WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementVerifyState(); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementSetupState(); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementState(); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementVerifyState(); + break; + + case WET_SELF_TESTS_STOPPED_STATE: + currentWetSelfTestsState = handleWetSelfTestStoppedState(); + break; + + case WET_SELF_TESTS_COMPLETE_STATE: + wetSelfTestsResult = TRUE; + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_WET_SELF_TEST_STATE, currentWetSelfTestsState ); + break; + } + + // Self-tests flags should be handled by now, reset if flags not handled with current state + resetSelfTestsFlags(); + + if ( priorSubState != currentWetSelfTestsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentWetSelfTestsState ); + } +} + +/*********************************************************************//** + * @brief + * The isDrySelfTestsPassed function returns the status of wet self-tests. + * @details Inputs: none * @details Outputs: none - * @return TRUE if no cartridge self-tests passed, otherwise FALSE + * @return TRUE if wet self-tests passed, otherwise FALSE *************************************************************************/ -BOOL isNoCartSelfTestsPassed( void ) +BOOL isWetSelfTestsPassed( void ) { - return isNoCartSelfTestsResult; + return wetSelfTestsResult; } +/*********************************************************************//** + * @brief + * The getWetSelfTestState function returns the state of wet self-tests. + * @details Inputs: none + * @details Outputs: none + * @return state of the wet self test + *************************************************************************/ +U32 getWetSelfTestState( void ) +{ + return (U32)currentWetSelfTestsState; +} + +/*********************************************************************//** + * @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_DOOR_CLOSE_STATE; + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + selfTestStartTime = getMSTimerCount(); + + if ( STATE_CLOSED == frontDoor ) + { + state = NO_CART_SELF_TESTS_PRESSURE_CHECKS_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleNoCartSelfTestHomeValvesState function starts homing process for + * all the valves. + * @details Inputs: none + * @details Outputs: Home all valves + * @return the next state of no cartridge self-tests state machine + *************************************************************************/ +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesState( void ) +{ + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE; + VALVE_T valve; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + homeValve( valve ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleNoCartSelfTestHomeSyringePumpState function homes syringe pump. + * @details Inputs: useHeparin + * @details Outputs: Home syringe pump + * @return the next state of no cartridge self-tests state machine + *************************************************************************/ +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeSyringePumpState( void ) +{ + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE; + BOOL syringeHome = isSyringePumpHome(); + BOOL syringeStopped = isSyringePumpStopped(); + BOOL syringePreloaded = isSyringePumpPreLoaded(); + + if ( TRUE == useHeparin ) + { + if ( ( TRUE != syringeHome ) && ( TRUE == syringeStopped ) && ( FALSE == syringePreloaded ) ) + { + retractSyringePump(); + } + else if ( ( TRUE == syringeHome ) && ( TRUE == syringeStopped ) && ( FALSE == syringePreloaded ) ) + { + // Is syringe loaded? + if ( TRUE == isSyringeDetected() ) + { + activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); + } + else + { + preloadSyringePlunger(); + } + } + else if ( TRUE == syringePreloaded ) + { + state = NO_CART_SELF_TESTS_PUMPS_STATE; + } + } + else + { + state = NO_CART_SELF_TESTS_PUMPS_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_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: havePumpsStartedForNCST + * @details Outputs: pumpHomingRequestedForNCST, + * Ran self-test for blood, dialysate in, dialysate out pumps + * @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 == havePumpsStartedForNCST ) + { + havePumpsStartedForNCST = 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 == pumpHomingRequestedForNCST ) + { + // Home pumps for cartridge installation + homeBloodPump(); + homeDialInPump(); + homeDialOutPump(); + state = NO_CART_SELF_TESTS_HOME_IDLE_STATE; + } + else if ( TRUE == didTimeout( runPumpStartTime, PUMP_RUN_SELF_TEST_TIME_MS ) ) + { + // Request homing of pumps for cartridge installation + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + pumpHomingRequestedForNCST = TRUE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleNoCartSelfTestHomeIdleState function waits for all pumps finish homing. + * @details Inputs: none + * @details Outputs: All pumps finished homing + * @return the next state of no cartridge self-tests state machine + *************************************************************************/ +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeIdleState( void ) +{ + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_IDLE_STATE; + + if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) + { + state = NO_CART_SELF_TESTS_COMPLETE_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleNoCartSelfTestStoppedState function handles the stopped no + * cartridge self-tests operation. + * @details Inputs: none + * @details Outputs: none + * @return the next state of no cart self-tests state machine + *************************************************************************/ +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ) +{ + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_STOPPED_STATE; + + doorClosedRequired( FALSE, FALSE ); + + // Restart self-test start time + selfTestStartTime = getMSTimerCount(); + + if ( TRUE == selfTestsResumeRequested ) + { + selfTestsResumeRequested = FALSE; + havePumpsStartedForNCST = FALSE; + pumpHomingRequestedForNCST = FALSE; + doorClosedRequired( TRUE, TRUE ); + state = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestStartState function makes sure door is + * closed before starting self-tests. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStartState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_START_STATE; + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + if ( STATE_CLOSED == pumpTrack ) + { + // Ensure occlusion sensor has time to settle after cartridge insertion before starting dry self-tests + if ( TRUE == didTimeout( selfTestCartridgeSettleTime, CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ) ) + { + setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed + doorClosedRequired( TRUE, TRUE ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) + { + signalAllowDGFlushFills(); + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else +#endif + { +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) // Allow res 1&2 fills now if air pump not disabled +#endif + { + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); + } + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } + } + } + + else + { + // doorClosedRequired() will trigger alarms if pumpTrack is open + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestWaitForDoorCloseState function makes sure door is + * closed before starting self-tests. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + // Restart self-test start time + selfTestStartTime = getMSTimerCount(); + + if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) ) + { + state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestUsedCartridgeCheckState function verify no fluid is + * detected by bubble detectors to ensure the cartridge is new. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + BUBBLE_STATUS_T ADVBubbleStatus = getBubbleStatus( ADV ); + + SEND_EVENT_WITH_2_U32_DATA(HD_EVENT_DRY_SELF_TEST_CARTRIDGE_RESULT,(U32)ADVBubbleStatus,(U32)BUBBLE_DETECTED) + + if ( ( BUBBLE_DETECTED == ADVBubbleStatus ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) + { + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_WORN_OUT_CARTRIDGE ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); + } +#ifndef _RELEASE_ + else + { + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } +#endif + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestCartridgeLoadedCheckState function verifies a cartridge + * is installed by checking sufficient pressure at OB sensor. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestCartridgeLoadedCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + + if ( SELF_TEST_STATUS_PASSED == execPresOcclDryTest() ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_OPEN ); + pressureSelfTestPreNormalStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_SETUP_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsSetupState function handles the setup + * for pressure sensors dry self-test. + * @details Inputs: pressureSelfTestPreNormalStartTime + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_SETUP_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) + { + + // Wait for reservoirs to drain before starting this test + if ( ( getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) < MAX_EMPTY_RESERVOIR_WEIGHT_G ) && ( getLoadCellWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) < MAX_EMPTY_RESERVOIR_WEIGHT_G ) ) + { + if ( TRUE == didTimeout( pressureSelfTestPreNormalStartTime, PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ) ) + { + previousNormalArterialPressure = getFilteredArterialPressure(); + previousNormalVenousPressure = getFilteredVenousPressure(); + state = DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS_SETUP_STATE; + + // Check to see if sensor is within normal ranges before we execute pressure sensor tests + if ( ( fabs( previousNormalArterialPressure ) > PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG ) || ( fabs( previousNormalVenousPressure ) > PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, previousNormalArterialPressure, previousNormalVenousPressure ); + } + } + } + } + else +#endif + { + if ( TRUE == didTimeout( pressureSelfTestPreNormalStartTime, PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ) ) + { // Record baseline pressures before pressurizing blood side circuit side of cartridge + previousNormalArterialPressure = getFilteredArterialPressure(); + previousNormalVenousPressure = getFilteredVenousPressure(); + + // Check to see if sensor is within normal ranges before we execute pressure sensor tests + if ( ( fabs( previousNormalArterialPressure ) > PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG ) || ( fabs( previousNormalVenousPressure ) > PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, previousNormalArterialPressure, previousNormalVenousPressure ); + } + else + { + state = DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS_SETUP_STATE; + } + } + } + + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsVenousSetupState function handles the setup + * for the venous pressure sensor dry self-test. + * @details Inputs: none + * @details Outputs: pressureSelfTestVenousTestStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) + { +#endif + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); +#ifndef _RELEASE_ + } + else + { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + } +#endif + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) + { +#endif + setAirPumpState( AIR_PUMP_STATE_ON ); +#ifndef _RELEASE_ + } + else + { + setDialInPumpTargetFlowRate( DIAL_IN_PUMP_PRESSURE_SELF_TEST_FLOW, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } +#endif + pressureSelfTestVenousTestStartTime = getMSTimerCount(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsVenousState function tests the readings of + * the venous pressure sensor and verify they are in correct range. + * @details Inputs: pressureSelfTestVenousTestStartTime + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_VENOUS; + F32 const venousPressure = getFilteredVenousPressure(); + + // End the test when reaching target pressure or time out + if ( VENOUS_PRESSURE_SELF_TEST_FIRST_PASS_LIMIT_MMHG <= venousPressure ) + { +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) + { +#endif + setAirPumpState( AIR_PUMP_STATE_OFF ); +#ifndef _RELEASE_ + } + else + { + signalDialInPumpHardStop(); + } +#endif + state = DRY_SELF_TESTS_PRESSURE_SENSORS_ARTERIAL_SETUP_STATE; + } + + if ( TRUE == didTimeout( pressureSelfTestVenousTestStartTime, VENOUS_PRESSURE_SELF_TEST_MAX_TEST_TIME ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, venousPressure, VENOUS_PRESSURE_SELF_TEST_FIRST_PASS_LIMIT_MMHG ); + setAirPumpState( AIR_PUMP_STATE_OFF ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsArterialSetupState function handles the setup + * for the arterial pressure sensor dry self-test. + * @details Inputs: + * @details Outputs: pressureSelfTestBloodPumpRunStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_ARTERIAL; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + 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( BLOOD_PUMP_PRESSURE_SELF_TEST_FLOW, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + pressureSelfTestBloodPumpRunStartTime = getMSTimerCount(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsArterialState function tests the readings of + * the arterial pressure sensor and verify they are in correct range. + * @details Inputs: pressureSelfTestBloodPumpRunStartTime + * @details Outputs: peakVenousPressure, peakArterialPressure, + * pressureSelfTestDecayStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_ARTERIAL; + F32 const arterialPressure = getFilteredArterialPressure(); + F32 const venousPressure = getFilteredVenousPressure(); + + // End the test when reaching target pressure or time out + // Test pass when reading positive arterial pressure and negative venous pressure + if ( ( ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG >= arterialPressure ) && ( VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG <= venousPressure ) ) + { + peakVenousPressure = venousPressure; + peakArterialPressure = arterialPressure; + signalBloodPumpHardStop(); + + pressureSelfTestDecayStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_PRESSURE_SENSORS_DECAY_STATE; + } + + if ( TRUE == didTimeout( pressureSelfTestBloodPumpRunStartTime, BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, venousPressure, arterialPressure ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsDecayState function verifies + * the readings of pressure sensors after we have verified the sensors + * are in the correct range by observing the loss in pressure once + * the pump has stopped. + * @details Inputs: pressureSelfTestDecayStartTime, peakArterialPressure, + * peakVenousPressure + * @details Outputs: decayedArterialPressure, decayedVenousPressure + * pressureSelfTestStabilityStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsDecayState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_DECAY_STATE; + F32 const arterialPressure = getFilteredArterialPressure(); + F32 const venousPressure = getFilteredVenousPressure(); + F32 arterialDecayDiff = 0; + F32 venousDecayDiff = 0; + + // update peak pressure value from pressurized state + // if pressure continues to increase due to filter lag. + // Arterial goes negative while Venous goes positive. + if ( arterialPressure < peakArterialPressure ) + { + peakArterialPressure = arterialPressure; + } + if ( venousPressure > peakVenousPressure ) + { + peakVenousPressure = venousPressure; + } + + if ( ( TRUE == didTimeout( pressureSelfTestDecayStartTime, DECAY_PRESSURE_SELF_TEST_TIME ) ) ) + { + arterialDecayDiff = fabs( arterialPressure - peakArterialPressure ); + venousDecayDiff = fabs( venousPressure - peakVenousPressure ); + + if ( ( arterialDecayDiff < ARTERIAL_DECAY_PRESSURE_DIFF_TOLERANCE_MMHG ) && + ( venousDecayDiff < VENOUS_DECAY_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + { + decayedArterialPressure = arterialPressure; + decayedVenousPressure = venousPressure; + pressureSelfTestStabilityStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_PRESSURE_SENSORS_STABILITY_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, arterialDecayDiff, venousDecayDiff ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsStabilityState function verifies the readings of + * pressure sensors in a stable, pressurized state after decay has been observed. + * @details Inputs: pressureSelfTestNormalizedStartTime, decayedArterialPressure + * decayedVenousPressure + * @details Outputs: pressureSelfTestNormalizedStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsStabilityState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STABILITY_STATE; + F32 arterialStabilityDiff = 0; + F32 venousStabilityDiff = 0; + + if ( ( TRUE == didTimeout( pressureSelfTestStabilityStartTime, STABILTY_PRESSURE_SELF_TEST_TIME ) ) ) + { + arterialStabilityDiff = fabs( getFilteredArterialPressure() - decayedArterialPressure ); + venousStabilityDiff = fabs( getFilteredVenousPressure() - decayedVenousPressure ); + + if ( ( arterialStabilityDiff < ARTERIAL_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ) && + ( venousStabilityDiff < VENOUS_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + { + pressureSelfTestNormalizedStartTime = getMSTimerCount(); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + + state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, arterialStabilityDiff, venousStabilityDiff ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsNormalState function verify the readings of + * pressure sensors after returning to normal state. + * @details Inputs: pressureSelfTestNormalizedStartTime + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; + + F32 const arterialPressureDiff = fabs( getFilteredArterialPressure() - previousNormalArterialPressure ); + F32 const venousPressureDiff = fabs( getFilteredVenousPressure() - previousNormalVenousPressure ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) + { + // open VDI to Pos A after timer threshold + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_VDI_TIMER ) ) + { + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + } + // open air trap after time threshold. + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_VBT_TIMERX ) ) + { + setValveAirTrap( STATE_OPEN ); + } + } + else +#endif + { + // open air trap after time threshold. + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_VBT_TIMER ) ) + { + setValveAirTrap( STATE_OPEN ); + } + } + + // After VBT opened, start looking to see if pressures normalize + if ( ( STATE_OPEN == getValveAirTrapStatus() ) && + ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + { + dryPressureTestsCompleted = TRUE; + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + + // If pressures do not normalize within max t/o, alarm + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_TIME ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_NORMAL_TEST_FAILURE, arterialPressureDiff, venousPressureDiff ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpPrimeState function handles the prime + * operation for syringe pump. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + + if ( TRUE == useHeparin ) + { + if ( FALSE == isSyringePumpRunning() ) + { + if ( TRUE == isSyringePlungerFound() ) + { + if ( TRUE == isSyringePumpPrimed() ) + { + state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; + syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 3 seconds has elapsed + } + else + { + primeSyringePump(); + } + } + else + { + if ( TRUE == isSyringePumpPreLoaded() ) + { + seekSyringePlunger(); + } + else + { + preloadSyringePlunger(); + } + } + } + } + else + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) // Allow res 1&2 fills now if air pump not disabled + { + if ( state != DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE ) + { + signalAllowDGFlushFills(); + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); + } + } +#endif + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpOcclusionDetectionState function handles + * occlusion detection after prime has completed. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; + + if ( TRUE == didTimeout( syringeOcclusionDelayStartTime, SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ) ) + { + if ( FALSE == checkForPrimeOcclusion() ) // transition to complete state only when occlusion is removed + { + // clear the occlusion alarm condition to allow user to resume + clearAlarmCondition( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION ); // Resume option will appear + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestStoppedState function handles the stopped dry self-tests + * operation. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED_STATE; + + doorClosedRequired( FALSE, FALSE ); + + // if not enough heparin alarm, pre-load pusher after retract completes + if ( TRUE == isAlarmActive( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM ) ) + { // prevent resume until syringe is retracted and pre-loaded + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); + if ( isSyringePumpRunning() != TRUE ) + { + if ( TRUE == isSyringePumpHome() ) + { + preloadSyringePlunger(); + } + else if ( TRUE == isSyringePumpPreLoaded() ) + { + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + } + } + } + + // if resume request, resume dry self-tests + if ( TRUE == selfTestsResumeRequested ) + { + // Restart self-test start time + selfTestStartTime = getMSTimerCount(); + selfTestsResumeRequested = FALSE; + selfTestCartridgeSettleTime = getMSTimerCount(); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) + { + doorClosedRequired( TRUE, TRUE ); + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else +#endif + { // if we've completed pressure testing, resume to syringe pump prime state, otherwise go back to start of dry self-tests + if ( TRUE == dryPressureTestsCompleted ) + { + doorClosedRequired( TRUE, TRUE ); + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else + { + doorClosedRequired( FALSE, TRUE ); + state = DRY_SELF_TESTS_START_STATE; + } + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestStartState function handles setup state for wet + * self-tests sub-mode. + * @details Inputs: heparin bolus volume setting + * @details Outputs: setup valves + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_SETUP_STATE; + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + + // if user set a Heparin bolus volume, request bolus to be initiated now + if ( ( bolusVol > 0.0F ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) + { + startHeparinBolus(); // moved here from startHeparinPump() in Dialysis.c + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSetupState function setup for bubble self-test + * check. + * @details Inputs: none + * @details Outputs: bubble detector self-test requested + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_STATE; + + selfTestBubble( ADV ); + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestBubblesState function waiting for air bubble detectors + * self-tests to finish. + * @details Inputs: bubbleSelfTestStatus + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_STATE; + + if ( SELF_TEST_STATUS_PASSED == getBubbleSelfTestStatus( ADV ) ) + { + state = WET_SELF_TESTS_PRIME_CHECK_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestPrimeCheckState function checks arterial and venous + * lines to make sure they are primed. + * @details Inputs: Arterial and venous bubble detectors status + * @details Outputs: Test pass/fail + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_PRIME_CHECK_STATE; + BUBBLE_STATUS_T ADVBubbleStatus = getBubbleStatus( ADV ); + + if ( BUBBLE_NOT_DETECTED == ADVBubbleStatus ) + { + if ( TRUE == zeroBloodLeak() ) + { + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + } + else + { +#ifndef _RELEASE_ + if ( ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) == SW_CONFIG_ENABLE_VALUE ) ) + { + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + } + else +#endif + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); + } + } + } + else + { + activateAlarmNoData( ALARM_ID_PRE_TREATMENT_WET_PRIME_TEST_FAILURE ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestBloodLeakDetectorState function handles zeroing and + * self-test for blood leak detector. + * @details Inputs: none + * @details Outputs: next self-test state + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + + if ( SELF_TEST_STATUS_PASSED == getBloodLeakSelfTestStatus() ) + { + settleStartTime = getMSTimerCount(); + isValvesSettingSent = FALSE; + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestStartFirstDisplacementState function setups the valves + * and pumps to start first dialysate displacement. + * @details Inputs: settleStartTime, isValvesSettingSent + * @details Outputs: isValvesSettingSent + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + DG_CMD_RESPONSE_T cmdResp; + + if ( FALSE == isValvesSettingSent ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + cmdChangeDGValveSetting( DG_VALVE_SETTING_R1_TO_R2 ); + isValvesSettingSent = TRUE; + settleStartTime = 0; + } + + if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) + { + isValvesSettingSent = FALSE; + + // Re-send command if DG rejects + if ( DG_CMD_REQUEST_REJECT_REASON_NONE == cmdResp.rejectCode ) + { + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestFirstDisplacementState function handles the first + * dialysate displacement from reservoir 1 to reservoir 2. + * @details Inputs: displacementStartTime, fmdIntegratedVolume, settleStartTime + * @details Outputs: settleStartTime, displacementStartTime + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + + // Once we've settled (5 sec), integrate flow to volume over duration of fluid transfer + if ( 0 == settleStartTime ) + { + fmdIntegratedVolume += ( getMeasuredDialInFlowRate() / (F32)( ( SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ); + + if ( TRUE == didTimeout( displacementStartTime, WET_SELF_TEST_FIRST_DISPLACEMENT_TIME_MS ) ) + { + signalDialInPumpHardStop(); + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; + } + } + + // Wait for settle time, then initiate transfer test + if ( ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) && ( settleStartTime != 0 ) ) + { + reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeight( DG_RESERVOIR_1 ); + reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeight( DG_RESERVOIR_2 ); + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0.0F; + settleStartTime = 0; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestFirstDisplacementVerifyState function checks the load cell + * readings and FMD integrated volume after the first dialysate displacement. + * @details Inputs: settleStartTime, fmdIntegratedVolume + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; + F32 resOneDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_1 ] - getReservoirWeight( DG_RESERVOIR_1 ); + F32 resTwoDiffAfterDisplacement = getReservoirWeight( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ]; + F32 averageDisp = ( resOneDiffAfterDisplacement + resTwoDiffAfterDisplacement ) / 2.0F; + F32 integratedVolumeDiff = fabs( fmdIntegratedVolume - averageDisp ); + F32 integratedVolumeToTargetPercent = fabs( 1.0F - ( fmdIntegratedVolume / averageDisp ) ); + F32 integrateVolumeToleranceG = WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_WET_SELF_TEST_WIDER_VOLUME_TOL ) ) + { + integrateVolumeToleranceG = WET_SELF_TEST_INTEGRATED_VOLUME_WIDER_TOLERANCE; + } +#endif + + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_WET_SELF_TEST_DISPLACEMENT_RESULT, resOneDiffAfterDisplacement, resTwoDiffAfterDisplacement ) + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_WET_SELF_TEST_DISPLACEMENT_RESULT, averageDisp, fmdIntegratedVolume ) + + if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement ) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && + ( ( integratedVolumeDiff <= integrateVolumeToleranceG ) || + ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_PCT_TOLERANCE ) ) ) + { + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + } + else + { + if ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) > WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_WET_LC_TEST_FAILURE, resOneDiffAfterDisplacement, resTwoDiffAfterDisplacement ); + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_WET_FLOW_TEST_FAILURE, averageDisp, fmdIntegratedVolume ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementSetupState function setups the valves + * and pumps to start second dialysate displacement. + * @details Inputs: settleStartTime, isValvesSettingSent + * @details Outputs: isValvesSettingSent + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + DG_CMD_RESPONSE_T cmdResp; + + if ( FALSE == isValvesSettingSent ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + cmdChangeDGValveSetting( DG_VALVE_SETTING_R2_TO_R1 ); + isValvesSettingSent = TRUE; + settleStartTime = 0; + } + + if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) + { + isValvesSettingSent = FALSE; + + // Re-send command if DG rejects + if ( DG_CMD_REQUEST_REJECT_REASON_NONE == cmdResp.rejectCode ) + { + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementState function handles the first + * dialysate displacement from reservoir 2 to reservoir 1. + * @details Inputs: displacementStartTime, fmdIntegratedVolume, settleStartTime + * @details Outputs: displacementStartTime + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + + if ( ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) && ( settleStartTime != 0 ) ) + { + reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeight( DG_RESERVOIR_1 ); + reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeight( DG_RESERVOIR_2 ); + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0.0F; + settleStartTime = 0; + } + + if ( 0 == settleStartTime ) + { + fmdIntegratedVolume += ( getMeasuredDialInFlowRate() / (F32)( ( SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ); + + if ( TRUE == didTimeout( displacementStartTime, WET_SELF_TEST_SECOND_DISPLACEMENT_TIME_MS ) ) + { + signalDialInPumpHardStop(); + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementVerifyState function checks the load cell + * readings and FMD integrated volume after the second dialysate displacement. + * @details Inputs: settleStartTime, reservoirVolume[], reservoirs' weights + * @details Outputs: verify correctness of dialysate flow meter and load cell + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; + F32 resOneDiffAfterDisplacement = getReservoirWeight( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ]; + F32 resTwoDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_2 ] - getReservoirWeight( DG_RESERVOIR_2 ); + F32 avgDisp = ( resOneDiffAfterDisplacement + resTwoDiffAfterDisplacement ) / 2.0F; + F32 integratedVolumeDiff = fabs( fmdIntegratedVolume - avgDisp ); + F32 integratedVolumeToTargetPercent = fabs( 1.0F - ( fmdIntegratedVolume / avgDisp ) ); + F32 integrateVolumeToleranceG = WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_WET_SELF_TEST_WIDER_VOLUME_TOL ) ) + { + integrateVolumeToleranceG = WET_SELF_TEST_INTEGRATED_VOLUME_WIDER_TOLERANCE; + } +#endif + + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_WET_SELF_TEST_DISPLACEMENT_RESULT, resOneDiffAfterDisplacement, resTwoDiffAfterDisplacement ) + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_WET_SELF_TEST_DISPLACEMENT_RESULT, avgDisp, fmdIntegratedVolume ) + + if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement ) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && + ( ( integratedVolumeDiff <= integrateVolumeToleranceG ) || + ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_PCT_TOLERANCE ) ) ) + { + state = WET_SELF_TESTS_COMPLETE_STATE; + } + else + { + if ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) > WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_WET_LC_TEST_FAILURE, resOneDiffAfterDisplacement, resTwoDiffAfterDisplacement ); + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_WET_FLOW_TEST_FAILURE, avgDisp, fmdIntegratedVolume ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestStoppedState function handles the stopped wet self-tests + * operation. + * @details Inputs: selfTestsResumeRequested + * @details Outputs: selfTestsResumeRequested + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestStoppedState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_STOPPED_STATE; + + doorClosedRequired( FALSE, FALSE ); + + if ( TRUE == selfTestsResumeRequested ) + { + doorClosedRequired( TRUE, TRUE ); + selfTestsResumeRequested = FALSE; + state = WET_SELF_TESTS_START_STATE; // TODO - should start state make sure there is sufficient/appropriate res volumes to restart wet self-tests? and if not, should it signal res mgmt to drain and fill R1 and R2 before resuming wet self-tests? + } + + return state; +} + /**@}*/