/************************************************************************** * * Copyright (c) 2026-2026 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 StatePreTxDrySelfTests.c * * @author (last) Varshini Nagabooshanam * @date (last) 01-Apr-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 01-Apr-2026 * ***************************************************************************/ #include "AirPump.h" #include "AirTrap.h" #include "BloodFlow.h" #include "Bubbles.h" #include "Buttons.h" #include "Common.h" #include "DDInterface.h" #include "LevelSensors.h" #include "Messaging.h" #include "ModePreTreat.h" #include "ModeTreatment.h" #include "OperationModes.h" #include "Pressures.h" #include "RotaryValve.h" #include "StatePreTxDrySelfTests.h" #include "Switches.h" #include "TaskGeneral.h" #include "Timers.h" #include "TDCommon.h" #include "TxParams.h" #include "Utilities.h" #include "Valves.h" #include "Valve3Way.h" /** * @addtogroup StatePreTxDrySelfTests * @{ */ // ********** private definitions ********** // Syringe pump #define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay before checking syringe pump occlusion after prime. // Pressure self-test timing #define PRE_NORMAL_PRESSURE_DELAY_MS ( 5 * MS_PER_SECOND ) ///< Delay before capturing baseline arterial and venous pressures. #define STABILITY_PRESSURE_CHECK_TIME_MS ( 4 * MS_PER_SECOND ) ///< Time allowed for pressure stabilization. #define VENOUS_PRESSURE_LEAK_CHECK_TIME ( 4 * MS_PER_SECOND ) ///< Time to monitor venous pressure decay (leak check). #define ARTERIAL_PRESSURE_LEAK_CHECK_TIME ( 4 * MS_PER_SECOND ) ///< Time to monitor arterial pressure decay (leak check). #define TUBESET_INSERT_PRESSURE_SETTLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Time required for pressure settling after tube set insertion. #define VENOUS_PRESSURE_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Max time allowed to reach venous pressure target. #define ARTERIAL_PRESSURE_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Max time allowed to reach arterial pressure target. #define MAX_DRY_SELF_TEST_TIME ( 12 * SEC_PER_MIN ) ///< Maximum total dry self-test duration. #define SELF_TEST_TIME_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND ) ///< Interval for publishing self-test progress data. #define TUBE_SET_AUTH_TIMEOUT_MS         ( 5 * MS_PER_SECOND ) ///< Tube set authentication timeout //Pressure self-test pump flow #define BLOOD_PUMP_PRESSURE_SELF_TEST_FLOW 100 ///< Blood pump flow rate during arterial pressure self-test (mL/min). // Pressure thresholds #define ZERO_PRESSURE_THRESHOLD_MMHG 15.0F ///< Zeroing the pressure #define VENOUS_PRESSURE_TARGET_MMHG 250.0F ///< Target venous pressure threshold during pressure build. #define ARTERIAL_PRESSURE_TARGET_MMHG -200.0F ///< Target arterial pressure threshold during pressure build. #define VENOUS_PRESSURE_STABILITY_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed venous pressure variation during stabilization. #define ARTERIAL_PRESSURE_STABILITY_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed arterial pressure variation during stabilization. #define VENOUS_PRESSURE_LEAK_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed venous pressure difference during leak check. #define ARTERIAL_PRESSURE_LEAK_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed arterial pressure difference during leak check. #define VENOUS_PRESSURE_RELIEF_THRESHOLD_MMHG 20.0F ///< Venous pressure must return within this threshold after relief. #define ARTERIAL_PRESSURE_RELIEF_THRESHOLD_MMHG 20.0F ///< Arterial pressure must return within this threshold after relief. /// Payload record structure for dry self-test authentication response typedef struct { U32 validTubeSet; U32 modalityMatch; } UI_TUBE_SET_AUTH_RESPONSE_PAYLOAD_T; /// Payload record structure for dry self-test authentication response typedef struct { U32 accepted; U32 modality; } TD_TUBE_SET_AUTH_RESPONSE_PAYLOAD_T; // ********** private data ********** static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of Dry Self-Test state machine static U32 selfTestPreviousPublishDataTime; ///< Last progress data publish time static BOOL doorStateAfterTubeSetInstall; ///< Tracks door transition after tube set install static U32 selfTestStartTime; ///< Start time of dry self-tests static U32 selfTestTubeSetSettleTime; ///< Delay after tube set insertion static BOOL selfTestsResumeRequested; ///< Resume requested from STOPPED state static BOOL tubeSetUsedTestRun; ///< Indicates tube set used test executed static BOOL barcodeScanResponseReceived; ///< Barcode response received flag static BOOL barcodeScanSuccessfull; ///< Barcode scan result static U32  authStartTime; ///< Authentication start timer static BOOL authResponseReceived; ///< Indicates UI auth response received static BOOL authResponseValidTubeSet; ///< Indicates tube set is valid static BOOL authResponseModalityAccepted; ///< Indicates tube set modality is accepted static U32 pressureSelfTestPreNormalStartTime; ///< Start time for pre-normal pressure setup delay static U32 venousSetupStartTime; ///< Venous setup start time static BOOL venousSetupStateEntered; ///< Venous pressure setup state entry static F32 peakVenousPressure; ///< Peak venous pressure during stabilization static U32 venousPressureStabilizationStartTime; ///< Start time for venous stabilization static F32 venousPressureP1; ///< First stable venous pressure sample static F32 venousPressureP2; ///< Second venous pressure sample for leak check static U32 venousPressureLeakCheckStartTime; ///< Start time for venous leak check static U32 venousPressureReliefStartTime; ///< Start time for venous pressure relief static BOOL arterialSetupStateEntered; ///< Arterial setup start time static U32 arterialSetupStartTime; ///< Arterial pressure setup state entry static U32 pressureSelfTestArterialStartTime; ///< Start time for arterial pressure build-up static F32 peakArterialPressure; ///< Peak arterial pressure during stabilization static U32 arterialPressureStabilizationStartTime; ///< Start time for arterial stabilization static F32 arterialPressureP1; ///< First stable arterial pressure sample static F32 arterialPressureP2; ///< Second arterial pressure sample for leak check static U32 arterialPressureLeakCheckStartTime; ///< Start time for arterial leak check static U32 arterialPressureReliefStartTime; ///< Start time for arterial pressure relief static BOOL useHeparin; ///< Indicates whether heparin is enabled static U32 syringeOcclusionDelayStartTime; ///< Delay before syringe occlusion check static BOOL heparinOcclusionTestRun; ///< Indicates heparin occlusion test executed static BOOL dryPressureTestsCompleted; ///< Indicates dry pressure tests completed static BOOL occlusionBaselineWasSet; ///< Indicates occlusion baseline established // ********** private function prototypes ********** static void resetSelfTestsFlags( void ); static void setAlarmResumePerDoor( void ); static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStartState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedTubeSetCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubeSetLoadedCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubeSetAuthenticationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpSeekState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorNormalSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureStabilizationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureLeakCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureReliefState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureStabilizationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureLeakCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureReliefState( 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 ); /*********************************************************************//** * @brief * The signalResumeSelfTests function signals the self-tests to resume * previous operation. * @details \b Inputs: none * @details \b Outputs: primeResumeRequested * @return none *************************************************************************/ void signalResumeSelfTests( void ) { selfTestsResumeRequested = TRUE; } /*********************************************************************//** * @brief * The resetSelfTestsFlags function resets all self-tests signal flags. * @details \b Inputs: none * @details \b Outputs: signal flags set to FALSE * @return none *************************************************************************/ static void resetSelfTestsFlags( void ) { selfTestsResumeRequested = FALSE; } /*********************************************************************//** * @brief * The setAlarmResumePerDoor function enables resume only when * required conditions are satisfied. * @details \b Inputs: Front door switch state * @details \b Outputs: resume alarm enabled/disabled * @return none *************************************************************************/ static void setAlarmResumePerDoor( void ) { BOOL doorClosed = FALSE; doorClosed = ( STATE_CLOSED == getSwitchState( H9_SWCH ) ); if ( TRUE == doorClosed ) { setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); } else { setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); } } /*********************************************************************//** * @brief * The initSelfTests function initializes the SelfTests module. * @details \b Inputs: none * @details \b Outputs: SelfTests module initialized. * @return none *************************************************************************/ void initSelfTests( void ) { currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; selfTestStartTime = 0; selfTestPreviousPublishDataTime = 0; selfTestTubeSetSettleTime = 0; pressureSelfTestPreNormalStartTime = 0; venousSetupStartTime = 0; venousPressureStabilizationStartTime = 0; venousPressureLeakCheckStartTime = 0; venousPressureReliefStartTime = 0; pressureSelfTestArterialStartTime = 0; arterialPressureStabilizationStartTime = 0; arterialPressureLeakCheckStartTime = 0; arterialPressureReliefStartTime = 0; syringeOcclusionDelayStartTime = 0; authStartTime = 0; doorStateAfterTubeSetInstall = TRUE; selfTestsResumeRequested = FALSE; tubeSetUsedTestRun = FALSE; barcodeScanResponseReceived = FALSE; barcodeScanSuccessfull = FALSE; authResponseReceived = FALSE; authResponseValidTubeSet = FALSE; authResponseModalityAccepted = FALSE; venousSetupStateEntered = FALSE; arterialSetupStateEntered = FALSE; useHeparin = FALSE; heparinOcclusionTestRun = FALSE; dryPressureTestsCompleted = FALSE; occlusionBaselineWasSet = FALSE; peakVenousPressure = 0.0F; venousPressureP1 = 0.0F; venousPressureP2 = 0.0F; peakArterialPressure = 0.0F; arterialPressureP1 = 0.0F; arterialPressureP2 = 0.0F; } /*********************************************************************//** * @brief * The transitionToDrySelfTests function resets anything required before * the start of dry self-tests. * @details \b Inputs: front door state * @details \b Outputs: Dry self-tests re-initialized, changed depending * on front door state * @return none *************************************************************************/ void transitionToDrySelfTests( void ) { selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); selfTestTubeSetSettleTime = getMSTimerCount(); doorClosedRequired( TRUE ); setCurrentSubState( (U32)currentDrySelfTestsState ); transitionToDrySelfTestsState( currentDrySelfTestsState ); signalBloodPumpHardStop(); // stopSyringePump(); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); } else { setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); } resetSelfTestsFlags(); } /*********************************************************************//** * @brief * The execDrySelfTests function executes the dry self-tests state machine. * @details \b Inputs: currentDrySelfTestsState * @details \b Outputs: currentDrySelfTestsState, pressureSelfTestPreNormalStartTime * @return none *************************************************************************/ void execDrySelfTests( void ) { DRY_SELF_TESTS_STATE_T priorSubState = currentDrySelfTestsState; 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_TUBE_SET_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestUsedTubeSetCheckState(); break; case DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestTubeSetLoadedCheckState(); break; case DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE: currentDrySelfTestsState = handleDrySelfTestTubeSetAuthenticationState(); break; case DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE: currentDrySelfTestsState = handleDrySelfTestSyringePumpSeekState(); break; case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestPressureSensorNormalSetupState(); break; case DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestVenousPressureSetupState(); break; case DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE: currentDrySelfTestsState = handleDrySelfTestVenousPressureStabilizationState(); break; case DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestVenousPressureLeakCheckState(); break; case DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE: currentDrySelfTestsState = handleDrySelfTestVenousPressureReliefState(); break; case DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestArterialPressureSetupState(); break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE: currentDrySelfTestsState = handleDrySelfTestArterialPressureStabilizationState(); break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestArterialPressureLeakCheckState(); break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE: currentDrySelfTestsState = handleDrySelfTestArterialPressureReliefState(); break; case DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE: currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); break; case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestSyringePumpOcclusionDetectionState(); break; case DRY_SELF_TESTS_STOPPED_STATE: currentDrySelfTestsState = handleDrySelfTestStoppedState(); break; case DRY_SELF_TESTS_COMPLETE_STATE: break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_DRY_SELF_TEST_STATE, currentDrySelfTestsState ); break; } // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); if ( priorSubState != currentDrySelfTestsState ) { setCurrentSubState( (U32)currentDrySelfTestsState ); SEND_EVENT_WITH_2_U32_DATA( TD_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 = ( elapsedSelfTestTimeInSecs <= MAX_DRY_SELF_TEST_TIME ? ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) : 0 ); broadcastData( MSG_ID_TD_DRY_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_DRY_PAYLOAD_T ) ); } } /*********************************************************************//** * @brief * The getDrySelfTestsState function returns the current state of dry self-tests sub-mode. * @details \b Inputs: currentDrySelfTestsState * @details \b Outputs: none * @return current dry self-tests state *************************************************************************/ U32 getDrySelfTestsState( void ) { return (U32)currentDrySelfTestsState; } /*********************************************************************//** * @brief * The handleDrySelfTestStartState function makes sure door is * closed before starting self-tests. * @details \b Inputs: none * @details \b 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 door = getSwitchState( H9_SWCH ); // Want to pinch off saline once door closed after tube set install handleDoorCloseAfterTubeSetInsertion(); if ( STATE_CLOSED == door ) { // Ensure occlusion sensor has time to settle after TubeSet insertion before starting dry self-tests if ( TRUE == didTimeout( selfTestTubeSetSettleTime, TUBESET_INSERT_PRESSURE_SETTLE_TIME_MS ) ) { doorClosedRequired( TRUE ); state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestWaitForDoorCloseState function makes sure door is * closed before starting self-tests. * @details \b Inputs: none * @details \b Outputs: selfTestStartTime * @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 door = getSwitchState( H9_SWCH ); // Restart self-test start time selfTestStartTime = getMSTimerCount(); if ( STATE_CLOSED == door ) { state = DRY_SELF_TESTS_USED_TUBE_SET_CHECK_STATE; } if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestUsedTubeSetCheckState function verify no fluid is * detected by bubble detectors to ensure the tube set is new. * @details \b Inputs: none * @details \b Outputs: tubeSetUsedTestRun * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedTubeSetCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_TUBE_SET_CHECK_STATE; BUBBLE_STATE_T bubbleStatus = getBubbleDetectedState( H18_BBLD ); AIR_TRAP_LEVELS_T lowerAirTrap = getLevelSensorState( H17_LEVL ); AIR_TRAP_LEVELS_T upperAirTrap = getLevelSensorState( H16_LEVL ); // Check if tube set is dry if ( ( BUBBLE_DETECTED == bubbleStatus ) && ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_AIR == upperAirTrap ) ) { resetArtVenPressureOffsets(); // Request barcode scan U32 requestScan = TRUE; sendMessage( MSG_ID_TD_TUBING_SET_BARCODE_SCAN_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)&requestScan, sizeof(U32) ); state = DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE; } else { // Allow wet tube set only for test configuration if ( TRUE == getTestConfigStatus( TEST_CONFIG_USE_WET_TUBE_SET ) ) { state = DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE; tubeSetUsedTestRun = TRUE; } else { // If tube set is invalid it triggers an alarm activateAlarmNoData( ALARM_ID_TD_INSTALL_NEW_BLOOD_TUBING_SET ); } } if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestTubeSetLoadedCheckState function handles barcode * scan result and transitions to authentication state if scan succeeded. * @details \b Inputs: barcodeScanResponseReceived, barcodeScanSuccessfull * @details \b Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubeSetLoadedCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE; if ( TRUE == barcodeScanResponseReceived ) { barcodeScanResponseReceived = FALSE; SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_TUBESET_RESULT, (U32)barcodeScanSuccessfull, 0 ); if ( TRUE == barcodeScanSuccessfull ) { authStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE; } else { // If barcode authentication is failed trigger an alarm activateAlarmNoData( ALARM_ID_TD_INSTALL_NEW_BLOOD_TUBING_SET ); } } if ( TRUE == doesAlarmStatusIndicateStop() ) { if ( TRUE == isAlarmActive( ALARM_ID_TD_TUBE_SET_NOT_DETECTED ) ) { occlusionBaselineWasSet = FALSE; } state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestTubeSetAuthenticationState function handles tube set * authentication and processes the authentication response. * @details \b Inputs: authResponseReceived, authResponseValidTubeSet, * authResponseModalityAccepted * @details \b Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubeSetAuthenticationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE; // Response received if ( TRUE == authResponseReceived ) { authResponseReceived = FALSE; if ( FALSE == authResponseValidTubeSet ) { activateAlarmNoData( ALARM_ID_TD_INVALID_TUBING_SET ); } else if ( FALSE == authResponseModalityAccepted ) { state = TD_PRE_TREATMENT_CART_INSTALL_STATE; } else { if ( getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ) > 0 ) { state = DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE; } else { state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; } } } // Timeout alarm else if ( TRUE == didTimeout( authStartTime, TUBE_SET_AUTH_TIMEOUT_MS ) ) { activateAlarmNoData( ALARM_ID_TD_TUBE_SET_AUTHENTICATION_TIMEOUT ); state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestSyringePumpSeekState function handles the syringe * pump seek dry self-test state. * @details \b Inputs: useHeparin * @details \b Outputs: pressureSelfTestPreNormalStartTime * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpSeekState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE; // BOOL done = FALSE; if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } // else // { // using Heparin? // if ( TRUE == useHeparin ) // { // syringe pump is not busy? // if ( FALSE == isSyringePumpRunning() ) // { // seek completed? // if ( TRUE == isSyringePlungerFound() ) // { // move on when seek completed // done = TRUE; // } // else // { // pre-load completed? // if ( TRUE == isSyringePumpPreLoaded() ) // { // initiate seek plunger operation // seekSyringePlunger(); // } // else // { // pre-load syringe // preloadSyringePlunger(); // } // } // } // } // else // { // not using Heparin, so move on // done = TRUE; // } // } // } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureSensorNormalSetupState function handles the setup * for pressure sensors dry self-test. * @details \b Inputs: pressureSelfTestPreNormalStartTime * @details \b Outputs: previousNormalArterialPressure, previousNormalVenousPressure * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorNormalSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } if ( TRUE == didTimeout( pressureSelfTestPreNormalStartTime, PRE_NORMAL_PRESSURE_DELAY_MS ) ) { F32 art = getFilteredArterialPressure(); F32 ven = getFilteredVenousPressure(); if ( ( fabs(art) < ZERO_PRESSURE_THRESHOLD_MMHG ) && ( fabs(ven) < ZERO_PRESSURE_THRESHOLD_MMHG ) ) { setArtVenPressureOffsets(); venousSetupStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE; } else { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRESSURE_TOO_HIGH_TO_ZERO, art, ven ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestVenousPressureSetupState function handles the setup * for the venous pressure sensor dry self-test. * @details \b Inputs: none * @details \b Outputs: venousPressureStabilizationStartTime * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE; // Execute once on state entry if ( FALSE == venousSetupStateEntered ) { SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_PRESSURE_RESULT, (U32)DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE, 0 ); venousSetupStartTime = getMSTimerCount(); venousSetupStateEntered = TRUE; } F32 ven = getFilteredVenousPressure(); // If it reaches to traget venous pressure >= 250 mmHg then the transition to venous pressure stablization state if ( ven >= VENOUS_PRESSURE_TARGET_MMHG ) { peakVenousPressure = ven; venousPressureStabilizationStartTime = getMSTimerCount(); venousSetupStateEntered = FALSE; state = DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE; } // Time out alarm if it does not reach within 60 sec tolerance else if ( TRUE == didTimeout( venousSetupStartTime, VENOUS_PRESSURE_TIMEOUT_MS ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURIZATION_TIMEOUT, ven ); state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestVenousPressureStabilizationState function handles * venous pressure stabilization check. * @details \b Inputs: venousPressureStabilizationStartTime, peakVenousPressure * @details \b Outputs: venousPressureP1 * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureStabilizationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE; if ( TRUE == didTimeout( venousPressureStabilizationStartTime, STABILITY_PRESSURE_CHECK_TIME_MS ) ) { F32 currentVenousPressure = getFilteredVenousPressure(); F32 diff = fabs( peakVenousPressure - currentVenousPressure ); if ( diff <= VENOUS_PRESSURE_STABILITY_DIFF_TOLERANCE_MMHG ) { venousPressureP1 = currentVenousPressure; venousPressureLeakCheckStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_DECAY, diff ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestVenousPressureLeakCheckState function handles * venous pressure leak check. * @details \b Inputs: venousPressureLeakCheckStartTime, venousPressureP1 * @details \b Outputs: venousPressureP2 * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureLeakCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE; if ( TRUE == didTimeout( venousPressureLeakCheckStartTime, VENOUS_PRESSURE_LEAK_CHECK_TIME ) ) { venousPressureP2 = getFilteredVenousPressure(); F32 diff = fabs( venousPressureP1 - venousPressureP2 ); if ( diff <= VENOUS_PRESSURE_LEAK_DIFF_TOLERANCE_MMHG ) { venousPressureReliefStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_LEAK, diff ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestVenousPressureReliefState function handles * venous pressure relief state. * @details \b Inputs: venousPressureReliefStartTime * @details \b Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureReliefState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE; if ( TRUE == didTimeout( venousPressureReliefStartTime, STABILITY_PRESSURE_CHECK_TIME_MS ) ) { F32 ven = getFilteredVenousPressure(); if ( fabs( ven ) <= VENOUS_PRESSURE_RELIEF_THRESHOLD_MMHG ) { arterialSetupStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_RELIEF, ven ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureArterialSetupState function handles the setup * for the arterial pressure sensor dry self-test. * @details \b Inputs: none * @details \b Outputs: pressureSelfTestArterialStartTime * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE; // Log only once on entry if ( FALSE == arterialSetupStateEntered ) { SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_PRESSURE_RESULT, (U32)DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE, 0 ); pressureSelfTestArterialStartTime = getMSTimerCount(); arterialSetupStateEntered = TRUE; } F32 art = getFilteredArterialPressure(); // Check the target for arterial pressure <= -200 mmHg and then transition to arterial pressure stabilization state if ( art <= ARTERIAL_PRESSURE_TARGET_MMHG ) { peakArterialPressure = art; arterialPressureStabilizationStartTime = getMSTimerCount(); arterialSetupStateEntered = FALSE; state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE; } // Time out alarm if it does not reach within 30 sec tolerance else if ( TRUE == didTimeout( pressureSelfTestArterialStartTime, ARTERIAL_PRESSURE_TIMEOUT_MS ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURIZATION_TIMEOUT, art ); arterialSetupStateEntered = FALSE; state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestArterialPressureStabilizationState function monitors * arterial pressure, verifies target pressure is reached, and records P1 * after stabilization. * @details \b Inputs: pressureSelfTestArterialStartTime, * arterialPressureStabilizationStartTime * @details \b Outputs: peakArterialPressure, arterialPressureP1, * arterialPressureLeakCheckStartTime * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureStabilizationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE; if ( TRUE == didTimeout( arterialPressureStabilizationStartTime, STABILITY_PRESSURE_CHECK_TIME_MS ) ) { F32 currentArterialPressure = getFilteredArterialPressure(); F32 diff = fabs( peakArterialPressure - currentArterialPressure ); if ( diff <= ARTERIAL_PRESSURE_STABILITY_DIFF_TOLERANCE_MMHG ) { arterialPressureP1 = currentArterialPressure; arterialPressureLeakCheckStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_DECAY, diff ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestArterialPressureLeakCheckState function verifies * arterial pressure leak by comparing P1 and P2. * @details \b Inputs: arterialPressureLeakCheckStartTime, arterialPressureP1 * @details \b Outputs: arterialPressureP2 * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureLeakCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE; if ( TRUE == didTimeout( arterialPressureLeakCheckStartTime, STABILITY_PRESSURE_CHECK_TIME_MS ) ) { arterialPressureP2 = getFilteredArterialPressure(); F32 diff = fabs( arterialPressureP1 - arterialPressureP2 ); if ( diff <= ARTERIAL_PRESSURE_LEAK_DIFF_TOLERANCE_MMHG ) { arterialPressureReliefStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_LEAK, diff ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestArterialPressureReliefState function relieves * arterial pressure and verifies return to baseline. * @details \b Inputs: arterialPressureReliefStartTime * @details \b Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureReliefState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE; if ( TRUE == didTimeout( arterialPressureReliefStartTime, STABILITY_PRESSURE_CHECK_TIME_MS ) ) { F32 art = getFilteredArterialPressure(); if ( fabs( art ) <= ARTERIAL_PRESSURE_RELIEF_THRESHOLD_MMHG ) { state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_RELIEF, art ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestSyringePumpPrimeState function handles the prime * operation for syringe pump. * @details \b Inputs: none * @details \b 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; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestSyringePumpOcclusionDetectionState function handles * occlusion detection after prime has completed. * @details \b Inputs: syringeOcclusionDelayStartTime * @details \b Outputs: heparinOcclusionTestRun * @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_CHECK_STATE; if ( TRUE == didTimeout( syringeOcclusionDelayStartTime, SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ) ) { // if ( FALSE == checkForSyringeOcclusion( FALSE ) ) // transition to complete state only when occlusion is removed // { // state = DRY_SELF_TESTS_COMPLETE_STATE; // } heparinOcclusionTestRun = TRUE; } if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestStoppedState function handles the stopped dry self-tests * operation. * @details \b Inputs: selfTestsResumeRequested, occlusionBaselineWasSet, * dryPressureTestsCompleted, tubeSetUsedTestRun, heparinOcclusionTestRun * @details \b Outputs: selfTestsResumeRequested, selfTestStartTime, selfTestTubeSetSettleTime * @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; setAlarmResumePerDoor(); doorClosedRequired( FALSE ); // if not enough heparin alarm, pre-load pusher after retract completes if ( TRUE == isAlarmActive( ALARM_ID_TD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM ) ) { // prevent resume until syringe is retracted and pre-loaded setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); // if ( TRUE != isSyringePumpRunning() ) // { // if ( TRUE == isSyringePumpHome() ) // { // preloadSyringePlunger(); // } // else if ( TRUE == isSyringePumpPreLoaded() ) // { // setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); // } // } } // if heparin occlusin alarm, keep calling check function so alarm condition will clear when resolved if ( TRUE == isAlarmActive( ALARM_ID_TD_SYRINGE_PUMP_OCCLUSION ) ) // { // checkForSyringeOcclusion( FALSE ); // } // depressurized the line from failed pressure self tests. if ( FALSE == dryPressureTestsCompleted ) { if ( getFilteredVenousPressure() <= VENOUS_PRESSURE_LEAK_DIFF_TOLERANCE_MMHG ) { setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); } } // if resume request, resume dry self-tests if ( TRUE == selfTestsResumeRequested ) { // Restart self-test start time selfTestsResumeRequested = FALSE; selfTestStartTime = getMSTimerCount(); selfTestTubeSetSettleTime = getMSTimerCount(); doorClosedRequired( TRUE ); if ( TRUE == heparinOcclusionTestRun ) { state = DRY_SELF_TESTS_COMPLETE_STATE; } else if ( TRUE == dryPressureTestsCompleted ) { state = ALARM_ID_TD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM; } else { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); if ( TRUE == tubeSetUsedTestRun ) { resetArtVenPressureOffsets(); state = DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE; } else if ( TRUE != occlusionBaselineWasSet ) { selfTestTubeSetSettleTime = getMSTimerCount(); state = DRY_SELF_TESTS_START_STATE; } else { state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } } return state; } /*********************************************************************//** * @brief * The drySelfTestHandleBarcodeScanResponse function handles the UI * barcode scan response. * @details \b Message \b Received: MSG_ID_UI_TUBE_SET_AUTHENTICATION_ACK * @details \b Message \b Sent: MSG_ID_TD_TUBE_SET_AUTHENTICATION_ACK * @details \b Inputs: message containing barcode scan success status * @details \b Outputs: barcodeScanSuccessfull, barcodeScanResponseReceived * @return TRUE if request is valid, FALSE otherwise *************************************************************************/ BOOL drySelfTestHandleTubeSetAuthResponse( MESSAGE_T *message ) { BOOL result = FALSE; UI_RESPONSE_PAYLOAD_T response; if ( sizeof( UI_TUBE_SET_AUTH_RESPONSE_PAYLOAD_T ) == message->hdr.payloadLen ) { UI_TUBE_SET_AUTH_RESPONSE_PAYLOAD_T payload; memcpy(&payload, message->payload, sizeof(payload)); authResponseValidTubeSet = (BOOL)payload.validTubeSet; authResponseModalityAccepted = (BOOL)payload.modalityMatch; authResponseReceived = TRUE; result = TRUE; } response.accepted = result; response.rejectionReason = REQUEST_REJECT_REASON_NONE; sendMessage( MSG_ID_TD_TUBE_SET_AUTHENTICATION_ACK_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)&response, sizeof( response ) ); return result; } /*********************************************************************//** * @brief * The transitionToDrySelfTestsState function handles the transition to * dry self-test states by setting actuators. * @details \b Inputs: none * @details \b Outputs: none * @param newState the targeted dry self-test state * @return none *************************************************************************/ static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ) { switch ( newState ) { case DRY_SELF_TESTS_START_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_USED_TUBE_SET_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_TUBE_SET_LOADED_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); startAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); setBloodPumpTargetFlowRate( BLOOD_PUMP_PRESSURE_SELF_TEST_FLOW, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); endAirTrapControl(); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdBypassDialyzer( TRUE ); cmdChangeQd( targetDialysateFlowMLPM ); cmdChangeQuf( 0.0F ); } break; case DRY_SELF_TESTS_COMPLETE_STATE: signalBloodPumpHardStop(); endAirTrapControl(); cmdChangeQuf( 0.0F ); break; case DRY_SELF_TESTS_STOPPED_STATE: { signalBloodPumpHardStop(); endAirTrapControl(); // Set valves for stop set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); // Vent pressure only during dry self-test if pressure tests not completed if ( ( TD_PRE_TREATMENT_SELF_TEST_DRY_STATE == getPreTreatmentSubState() ) && ( FALSE == dryPressureTestsCompleted ) ) { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); } else { setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); } setAlarmResumePerDoor(); doorClosedRequired( FALSE ); } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_DRY_SELF_TEST_STATE, (U32)newState ); break; } } /*********************************************************************//** * @brief * The handleDoorCloseAfterTubeSetInsertion function handles the check * for door close after tube set install so that saline line can be pinched. * @details Inputs: door states * @details Outputs: doorStateAfterTubeSetInstall * @return none *************************************************************************/ void handleDoorCloseAfterTubeSetInsertion( void ) { OPN_CLS_STATE_T door = getSwitchState( H9_SWCH ); if ( STATE_OPEN == door ) { doorStateAfterTubeSetInstall = FALSE; } if ( ( STATE_CLOSED == door ) && ( FALSE == doorStateAfterTubeSetInstall ) ) { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); doorStateAfterTubeSetInstall = TRUE; } } /**@}*/