/************************************************************************** * * 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 DrySelfTests.c * * @author (last) Varshini Nagabooshanam * @date (last) 19-Aug-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 26-May-2026 * ***************************************************************************/ #include "AirPump.h" #include "AirTrap.h" #include "BloodFlow.h" #include "Bubbles.h" #include "Buttons.h" #include "Common.h" #include "DDInterface.h" #include "DrySelfTests.h" #include "FpgaTD.h" #include "LevelSensors.h" #include "Messaging.h" #include "ModePreTreat.h" #include "ModeTreatment.h" #include "OperationModes.h" #include "PinchValve.h" #include "Pressures.h" #include "Switches.h" #include "TaskGeneral.h" #include "TDCommon.h" #include "Timers.h" #include "TxParams.h" #include "Utilities.h" #include "Valves.h" #include "Valve3Way.h" /** * @addtogroup DrySelfTests * @{ */ // ********** private definitions ********** // 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_MS ( 5 * MS_PER_SECOND ) ///< Time to monitor venous pressure decay (leak check). //#define ARTERIAL_PRESSURE_LEAK_CHECK_TIME_MS ( 5 * MS_PER_SECOND ) ///< Time to monitor arterial pressure decay (leak check). #define TUBING_SET_INSERT_PRESSURE_SETTLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Time required for pressure settling after tubing 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 PRESSURE_RELIEF_CHECK_TIME_MS ( 30 * MS_PER_SECOND ) ///< Pressure Relief check time in ms. //#define ARTERIAL_PRESSURE_SETTLE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Arterial pressure settle time in ms #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 TUBING_SET_AUTH_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Tubing 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 5.0F ///< Venous pressure must return within this threshold after relief. //#define ARTERIAL_PRESSURE_RELIEF_THRESHOLD_MMHG 5.0F ///< Arterial pressure must return within this threshold after relief. // New // Pressure self-test timing #define PRE_NORMAL_PRESSURE_DELAY_MS ( 5 * MS_PER_SECOND ) ///< Delay before zeroing pressure sensors. #define PRESSURE_BUILD_TIMEOUT_MS ( 40 * MS_PER_SECOND ) ///< Maximum pressure build time. #define PRESSURE_STABILIZATION_TIME_MS ( 1 * MS_PER_SECOND ) ///< Pressure stabilization time. #define PRESSURE_DECAY_CHECK_TIME_MS ( 2 * MS_PER_SECOND ) ///< Pressure decay monitoring time. #define PRESSURE_RELIEF_CHECK_TIME_MS ( 2 * MS_PER_SECOND ) ///< Pressure relief verification time. // Pressure thresholds #define PRESSURE_SELF_TEST_H4_SPEED_RPM 1500 ///< H4 blood pump speed during pressure self-test #define ZERO_PRESSURE_THRESHOLD_MMHG 15.0F ///< Zeroing the pressure #define NEG_ART_PRESSURE_TARGET_MMHG -250.0F ///< Negative arterial pressure generation targets #define POS_VEN_PRESSURE_TARGET_MMHG 375.0F ///< Positive venous pressure generation targets #define NEG_ART_STABILIZED_PRESSURE_MMHG -200.0F ///< Minimum arterial pressure that must remain after stabilization #define POS_VEN_STABILIZED_PRESSURE_MMHG 250.0F ///< Minimum venous pressure that must remain after stabilization #define POS_ART_PRESSURE_TARGET_MMHG 200.0F ///< Positive arterial pressure generation target #define POS_ART_STABILIZED_PRESSURE_MMHG 180.0F ///< Minimum positive arterial pressure after stabilization #define PRESSURE_DECAY_TOLERANCE_MMHG 2.5F ///< Maximum pressure change allowed during decay checks #define PRESSURE_RELIEF_THRESHOLD_MMHG 5.0F ///< Pressure must return within +/-5 mmHg during relief /// Payload record structure for dry self-test authentication response typedef struct { U32 validTubingSet; ///< Tubing set barcode is valid U32 modalityTube; ///< Tubing set modality from barcode } UI_TUBING_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 U32 selfTestStartTime; ///< Start time of dry self-tests //static BOOL doorStateAfterTubingSetInstall; ///< Tracks door transition after tubing set install //static BOOL selfTestsResumeRequested; ///< Resume requested from STOPPED state //static BOOL tubingSetLeakChecksStarted; ///< Indicates tubing set leak check started //static BOOL barcodeScanResponseReceived; ///< Barcode response received flag //static U32 authenticationStartTime; ///< Authentication start timer //static BOOL authResponseReceived; ///< Indicates UI auth response received //static BOOL authResponseValidTubingSet; ///< Indicates tubing set is valid //static BOOL authResponseModalityAccepted; ///< Indicates tubing set modality is accepted // //// Pressure normal //static U32 pressureSelfTestPreNormalStartTime; ///< Start time for pre-normal pressure setup delay // //// Venous pressure //static U32 venousSetupStartTime; ///< Venous setup start time //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 // //// Arterial pressure //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 // //// Used to avoid comparing pump running pressure against immediate post hard stop pressure. //static U32 arterialPressureSettleStartTime; ///< Arterial pressure settle start time //static BOOL arterialPressureBaselineCaptured; ///< Arterial Pressure base captured static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current Dry Self-Test state. static U32 selfTestPreviousPublishDataTime; ///< Previous progress publish time. static U32 selfTestStartTime; ///< Dry Self-Test start time. static BOOL doorStateAfterTubingSetInstall; ///< Door transition after tubing set installation. static BOOL selfTestsResumeRequested; ///< Resume request from STOPPED state. static BOOL tubingSetLeakChecksStarted; ///< Pressure/leak testing started. static BOOL barcodeScanResponseReceived; ///< Barcode scan response received. static U32 authenticationStartTime; ///< Tubing authentication start time. static BOOL authResponseReceived; ///< Authentication response received. static BOOL authResponseValidTubingSet; ///< Tubing set valid. static BOOL authResponseModalityAccepted; ///< Tubing modality accepted. // Pressure normal static U32 pressureSelfTestPreNormalStartTime; ///< Pressure normal setup start time. // Negative arterial / positive venous static U32 negArtPosVenSetupStartTime; ///< Combined pressure build start time. static U32 negArtPosVenStabilizationStartTime; ///< Combined stabilization start time. static U32 negArtPosVenDecayStartTime; ///< Combined decay check start time. static F32 negArtPressureP1; ///< Negative arterial first pressure sample. static F32 negArtPressureP2; ///< Negative arterial second pressure sample. static F32 posVenPressureP1; ///< Positive venous first pressure sample. static F32 posVenPressureP2; ///< Positive venous second pressure sample. // Positive arterial static U32 posArtSetupStartTime; ///< Positive arterial build start time. static U32 posArtStabilizationStartTime; ///< Positive arterial stabilization start time. static U32 posArtDecayStartTime; ///< Positive arterial decay start time. static F32 posArtPressureP1; ///< Positive arterial first pressure sample. static F32 posArtPressureP2; ///< Positive arterial second pressure sample. // Pressure relief static U32 pressureReliefStartTime; ///< Pressure relief start time. // ********** private function prototypes ********** static void publishDrySelfTestProgress( void ); static void resetSelfTestsFlags( void ); static void setAlarmResumePerDoor( void ); static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedTubingSetCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubingSetLoadedCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubingSetAuthenticationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorNormalSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenPressureSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenStabilizationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenDecayCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtPressureSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtStabilizationState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtDecayCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureReliefState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); /*********************************************************************//** * @brief * The initDrySelfTests function initializes the DrySelfTests unit. * @details \b Inputs: none * @details \b Outputs: DrySelfTests unit initialized. * @return none *************************************************************************/ void initDrySelfTests( void ) { currentDrySelfTestsState = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; selfTestStartTime = 0; selfTestPreviousPublishDataTime = 0; pressureSelfTestPreNormalStartTime = 0; authenticationStartTime = 0; doorStateAfterTubingSetInstall = TRUE; selfTestsResumeRequested = FALSE; tubingSetLeakChecksStarted = FALSE; barcodeScanResponseReceived = FALSE; authResponseReceived = FALSE; authResponseValidTubingSet = FALSE; authResponseModalityAccepted = FALSE; negArtPosVenSetupStartTime = 0; negArtPosVenStabilizationStartTime = 0; negArtPosVenDecayStartTime = 0; negArtPressureP1 = 0.0F; negArtPressureP2 = 0.0F; posVenPressureP1 = 0.0F; posVenPressureP2 = 0.0F; posArtSetupStartTime = 0; posArtStabilizationStartTime = 0; posArtDecayStartTime = 0; posArtPressureP1 = 0.0F; posArtPressureP2 = 0.0F; pressureReliefStartTime = 0; } /*********************************************************************//** * @brief * The transitionToDrySelfTests function resets anything required before * the start of dry self-tests. * @details \b Inputs: currentDrySelfTestsState * @details \b Outputs: selfTestStartTime, selfTestPreviousPublishDataTime, * selfTestsResumeRequested * @return none *************************************************************************/ void transitionToDrySelfTests( void ) { selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); doorClosedRequired( TRUE ); endAirTrapControl(); setCurrentSubState( (U32)currentDrySelfTestsState ); // To configure actuators for the initial Dry Self-Test state. transitionToDrySelfTestsState( currentDrySelfTestsState ); } /*********************************************************************//** * @brief * The execDrySelfTests function executes the dry self-tests state machine. * @details \b Inputs: currentDrySelfTestsState * @details \b Outputs: currentDrySelfTestsState * @return none *************************************************************************/ void execDrySelfTests( void ) { DRY_SELF_TESTS_STATE_T priorSubState = currentDrySelfTestsState; switch ( currentDrySelfTestsState ) { case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: currentDrySelfTestsState = handleDrySelfTestWaitForDoorCloseState(); break; case DRY_SELF_TESTS_USED_TUBING_SET_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestUsedTubingSetCheckState(); break; case DRY_SELF_TESTS_TUBING_SET_LOADED_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestTubingSetLoadedCheckState(); break; case DRY_SELF_TESTS_TUBING_SET_AUTHENTICATION_STATE: currentDrySelfTestsState = handleDrySelfTestTubingSetAuthenticationState(); break; case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestPressureSensorNormalSetupState(); break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_PRESSURE_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestNegArtPosVenPressureSetupState(); break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_STABILIZATION_STATE: currentDrySelfTestsState = handleDrySelfTestNegArtPosVenStabilizationState(); break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_DECAY_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestNegArtPosVenDecayCheckState(); break; case DRY_SELF_TESTS_POS_ART_PRESSURE_SETUP_STATE: currentDrySelfTestsState = handleDrySelfTestPosArtPressureSetupState(); break; case DRY_SELF_TESTS_POS_ART_STABILIZATION_STATE: currentDrySelfTestsState = handleDrySelfTestPosArtStabilizationState(); break; case DRY_SELF_TESTS_POS_ART_DECAY_CHECK_STATE: currentDrySelfTestsState = handleDrySelfTestPosArtDecayCheckState(); break; case DRY_SELF_TESTS_PRESSURE_RELIEF_STATE: currentDrySelfTestsState = handleDrySelfTestPressureReliefState(); 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; } if ( priorSubState != currentDrySelfTestsState ) { transitionToDrySelfTestsState( currentDrySelfTestsState ); setCurrentSubState( (U32)currentDrySelfTestsState ); SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDrySelfTestsState ); } publishDrySelfTestProgress(); } /*********************************************************************//** * @brief * The publishDrySelfTestProgress function publishes dry self-test progress. * @details \b Message \b Sent: MSG_ID_TD_DRY_SELF_TEST_PROGRESS_DATA * @details \b Inputs: selfTestPreviousPublishDataTime, selfTestStartTime, * currentDrySelfTestsState * @details \b Outputs: selfTestPreviousPublishDataTime * @return none *************************************************************************/ static void publishDrySelfTestProgress( void ) { 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.substate = currentDrySelfTestsState; 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 signalResumeDrySelfTests function signals the self-tests to resume * previous operation. * @details \b Inputs: none * @details \b Outputs: selfTestsResumeRequested * @return none *************************************************************************/ void signalResumeDrySelfTests( void ) { selfTestsResumeRequested = TRUE; } /*********************************************************************//** * @brief * The resetSelfTestsFlags function resets all self-tests signal flags. * @details \b Inputs: none * @details \b Outputs: selfTestsResumeRequested * @return none *************************************************************************/ static void resetSelfTestsFlags( void ) { selfTestsResumeRequested = FALSE; } /*********************************************************************//** * @brief * The setAlarmResumePerDoor function sets the Resume alarm action * based on the front door state. * @details \b Inputs: doorClosed * @details \b Outputs: none * @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 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 handleDrySelfTestWaitForDoorCloseState function makes sure door is * closed before starting self-tests. * @details \b Inputs: door * @details \b Outputs: doorStateAfterTubingSetInstall * @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 ); // Want to pinch off saline once door closed after tubing set install handleDoorCloseAfterTubingSetInsertion(); if ( STATE_CLOSED == door ) { // TODO Later - Current temporary sequential test flow bypasses tubing-set barcode/authentication states state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestUsedTubingSetCheckState function verifies that * no fluid is detected in the tubing set before continuing dry self-tests. * @details \b Inputs: none * @details \b Outputs: barcodeScanResponseReceived * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedTubingSetCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_TUBING_SET_CHECK_STATE; BUBBLE_STATE_T bubble = getBubbleDetectedState( H18_BBLD ); AIR_TRAP_LEVELS_T lower = getLevelSensorState( H17_LEVL ); AIR_TRAP_LEVELS_T upper = getLevelSensorState( H16_LEVL ); U32 bubbleState = (U32)bubble; U32 lowerLevelState = (U32)lower; if ( ( BUBBLE_DETECTED == bubble ) && ( AIR_TRAP_LEVEL_AIR == lower ) && ( AIR_TRAP_LEVEL_AIR == upper ) ) { resetArtVenPressureOffsets(); // TODO: Send barcode scan command through FPGA interface barcodeScanResponseReceived = TRUE; state = DRY_SELF_TESTS_TUBING_SET_LOADED_CHECK_STATE; } else { // Allow wet tubing set only for test configuration if ( TRUE == getTestConfigStatus( TEST_CONFIG_USE_WET_TUBING_SET ) ) { // TODO: Send barcode scan command through FPGA interface barcodeScanResponseReceived = TRUE; state = DRY_SELF_TESTS_TUBING_SET_LOADED_CHECK_STATE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_INSTALL_NEW_BLOOD_TUBING_SET, bubbleState, lowerLevelState ); PreTxRequestTubeSetInstall(); } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestTubingSetLoadedCheckState function handles barcode * scan result and transitions to authentication state if scan succeeded. * @details \b Message \b Sent: MSG_ID_TD_TUBE_SET_AUTHENTICATION_REQUEST * if barcode scan response is received * @details \b Inputs: barcodeScanResponseReceived * @details \b Outputs: barcodeScanResponseReceived, authenticationStartTime * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubingSetLoadedCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_TUBING_SET_LOADED_CHECK_STATE; if ( TRUE == barcodeScanResponseReceived ) { barcodeScanResponseReceived = FALSE; // TODO: Send barcode for authentication when UI flow is ready sendMessage( MSG_ID_TD_TUBE_SET_AUTHENTICATION_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_UI, NULL, 0 ); // TODO: Remove these once UI responds to authentication request // authResponseReceived = TRUE; // authResponseValidTubingSet = TRUE; // authResponseModalityAccepted = TRUE; authenticationStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_TUBING_SET_AUTHENTICATION_STATE; } else { activateAlarmNoData( ALARM_ID_TD_INSTALL_NEW_BLOOD_TUBING_SET ); PreTxRequestTubeSetInstall(); } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestTubingSetAuthenticationState function handles tubing set * authentication and processes the authentication response. * @details \b Inputs: authResponseReceived, authResponseValidTubingSet, * authResponseModalityAccepted, authenticationStartTime * @details \b Outputs: authResponseReceived * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubingSetAuthenticationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_TUBING_SET_AUTHENTICATION_STATE; if ( TRUE == authResponseReceived ) { authResponseReceived = FALSE; if ( FALSE == authResponseValidTubingSet ) { activateAlarmNoData( ALARM_ID_TD_INVALID_TUBING_SET ); PreTxRequestTubeSetInstall(); } else if ( FALSE == authResponseModalityAccepted ) { PreTxRequestTubeSetInstall(); } else { state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; } } else if ( TRUE == didTimeout( authenticationStartTime, TUBING_SET_AUTH_TIMEOUT_MS ) ) { activateAlarmNoData( ALARM_ID_TD_TUBING_SET_AUTHENTICATION_TIMEOUT ); state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPressureSensorNormalSetupState function verifies * arterial and venous pressures before pressure sensor zeroing. * @details \b Inputs: pressureSelfTestPreNormalStartTime * @details \b Outputs: none * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorNormalSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_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(); state = DRY_SELF_TESTS_NEG_ART_POS_VEN_PRESSURE_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 handleDrySelfTestNegArtPosVenPressureSetupState function monitors * negative arterial and positive venous pressure generation. * @details \b Inputs: negArtPosVenSetupStartTime, * @details \b Outputs: none * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenPressureSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_NEG_ART_POS_VEN_PRESSURE_SETUP_STATE; F32 art = getFilteredArterialPressure(); F32 ven = getFilteredVenousPressure(); if ( ( art <= NEG_ART_PRESSURE_TARGET_MMHG ) && ( ven >= POS_VEN_PRESSURE_TARGET_MMHG ) ) { state = DRY_SELF_TESTS_NEG_ART_POS_VEN_STABILIZATION_STATE; } else if ( TRUE == didTimeout( negArtPosVenSetupStartTime, PRESSURE_BUILD_TIMEOUT_MS ) ) { if ( art > NEG_ART_PRESSURE_TARGET_MMHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURIZATION_TIMEOUT, art ); } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURIZATION_TIMEOUT, ven ); } state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestNegArtPosVenStabilizationState function verifies * negative arterial and positive venous pressure after stabilization. * @details \b Inputs: negArtPosVenStabilizationStartTime, * @details \b Outputs: negArtPressureP1, posVenPressureP1 * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenStabilizationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_NEG_ART_POS_VEN_STABILIZATION_STATE; if ( TRUE == didTimeout( negArtPosVenStabilizationStartTime, PRESSURE_STABILIZATION_TIME_MS ) ) { F32 art = getFilteredArterialPressure(); F32 ven = getFilteredVenousPressure(); if ( ( art <= NEG_ART_STABILIZED_PRESSURE_MMHG ) && ( ven >= POS_VEN_STABILIZED_PRESSURE_MMHG ) ) { negArtPressureP1 = art; posVenPressureP1 = ven; state = DRY_SELF_TESTS_NEG_ART_POS_VEN_DECAY_CHECK_STATE; } else { if ( art > NEG_ART_STABILIZED_PRESSURE_MMHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_DECAY, art ); } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_DECAY, ven ); } state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestNegArtPosVenDecayCheckState function verifies * arterial and venous pressure decay. * @details \b Inputs: negArtPosVenDecayStartTime, negArtPressureP1, * posVenPressureP1 * @details \b Outputs: negArtPressureP2, posVenPressureP2 * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestNegArtPosVenDecayCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_NEG_ART_POS_VEN_DECAY_CHECK_STATE; if ( TRUE == didTimeout( negArtPosVenDecayStartTime, PRESSURE_DECAY_CHECK_TIME_MS ) ) { F32 artDiff; F32 venDiff; negArtPressureP2 = getFilteredArterialPressure(); posVenPressureP2 = getFilteredVenousPressure(); artDiff = fabs( negArtPressureP1 - negArtPressureP2 ); venDiff = fabs( posVenPressureP1 - posVenPressureP2 ); if ( ( artDiff <= PRESSURE_DECAY_TOLERANCE_MMHG ) && ( venDiff <= PRESSURE_DECAY_TOLERANCE_MMHG ) ) { state = DRY_SELF_TESTS_POS_ART_PRESSURE_SETUP_STATE; } else { if ( artDiff > PRESSURE_DECAY_TOLERANCE_MMHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_LEAK, artDiff ); } else { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_LEAK, posVenPressureP1, posVenPressureP2 ); } state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPosArtPressureSetupState function monitors * positive arterial pressure generation. * @details \b Inputs: posArtSetupStartTime * @details \b Outputs: none * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtPressureSetupState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_POS_ART_PRESSURE_SETUP_STATE; F32 art = getFilteredArterialPressure(); if ( art >= POS_ART_PRESSURE_TARGET_MMHG ) { state = DRY_SELF_TESTS_POS_ART_STABILIZATION_STATE; } else if ( TRUE == didTimeout( posArtSetupStartTime, PRESSURE_BUILD_TIMEOUT_MS ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURIZATION_TIMEOUT, art ); state = DRY_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPosArtStabilizationState function verifies * positive arterial pressure after stabilization. * @details \b Inputs: posArtStabilizationStartTime * @details \b Outputs: posArtPressureP1 * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtStabilizationState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_POS_ART_STABILIZATION_STATE; if ( TRUE == didTimeout( posArtStabilizationStartTime, PRESSURE_STABILIZATION_TIME_MS ) ) { F32 art = getFilteredArterialPressure(); if ( art >= POS_ART_STABILIZED_PRESSURE_MMHG ) { posArtPressureP1 = art; state = DRY_SELF_TESTS_POS_ART_DECAY_CHECK_STATE; } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_DECAY, art ); state = DRY_SELF_TESTS_STOPPED_STATE; } } return state; } /*********************************************************************//** * @brief * The handleDrySelfTestPosArtDecayCheckState function verifies positive * arterial pressure decay. * @details \b Inputs: posArtDecayStartTime, posArtPressureP1 * @details \b Outputs: posArtPressureP2 * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPosArtDecayCheckState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_POS_ART_DECAY_CHECK_STATE; if ( TRUE == didTimeout( posArtDecayStartTime, PRESSURE_DECAY_CHECK_TIME_MS ) ) { F32 diff; posArtPressureP2 = getFilteredArterialPressure(); diff = fabs( posArtPressureP1 - posArtPressureP2 ); if ( diff <= PRESSURE_DECAY_TOLERANCE_MMHG ) { state = DRY_SELF_TESTS_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 handleDrySelfTestPressureReliefState function verifies arterial * and venous pressure relief. * @details \b Inputs: pressureReliefStartTime * @details \b Outputs: none * @return next Dry Self-Test state *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureReliefState( void ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_RELIEF_STATE; if ( TRUE == didTimeout( pressureReliefStartTime, PRESSURE_RELIEF_CHECK_TIME_MS ) ) { F32 art = getFilteredArterialPressure(); F32 ven = getFilteredVenousPressure(); if ( ( fabs( art ) <= PRESSURE_RELIEF_THRESHOLD_MMHG ) && ( fabs( ven ) <= PRESSURE_RELIEF_THRESHOLD_MMHG ) ) { state = DRY_SELF_TESTS_COMPLETE_STATE; } else { if ( fabs( art ) > PRESSURE_RELIEF_THRESHOLD_MMHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_RELIEF, art ); } else { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_RELIEF, 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: venousSetupStartTime //* @details \b Outputs: peakVenousPressure, 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; // 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(); // 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 // * @details \b Outputs: venousPressureP1, venousPressureLeakCheckStartTime // * @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 ) ) // { // venousPressureP1 = getFilteredVenousPressure(); // venousPressureLeakCheckStartTime = getMSTimerCount(); // state = DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE; // } // // return state; //} // ///*********************************************************************//** // * @brief // * The handleDrySelfTestVenousPressureLeakCheckState function handles // * venous pressure leak check. // * @details \b Inputs: venousPressureLeakCheckStartTime, venousPressureP1 // * @details \b Outputs: venousPressureP2, venousPressureReliefStartTime // * @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_MS ) ) // { // F32 diff; // // venousPressureP2 = getFilteredVenousPressure(); // 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_2_F32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_LEAK, venousPressureP1, venousPressureP2 ); // 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, PRESSURE_RELIEF_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: pressureSelfTestArterialStartTime // * @details \b Outputs: none // * @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; // F32 art = getFilteredArterialPressure(); // // if ( art <= ARTERIAL_PRESSURE_TARGET_MMHG ) // { // state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE; // } // else if ( TRUE == didTimeout( pressureSelfTestArterialStartTime, ARTERIAL_PRESSURE_TIMEOUT_MS ) ) // { // SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURIZATION_TIMEOUT, art ); // 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, peakArterialPressure, // * arterialPressureStabilizationStartTime, arterialPressureBaselineCaptured, // * @details \b Outputs: peakArterialPressure, arterialPressureP1, // * arterialPressureLeakCheckStartTime, arterialPressureBaselineCaptured, // * arterialPressureStabilizationStartTime // * @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 ( FALSE == arterialPressureBaselineCaptured ) // { // if ( TRUE == didTimeout( arterialPressureSettleStartTime, ARTERIAL_PRESSURE_SETTLE_TIME_MS ) ) // { // peakArterialPressure = getFilteredArterialPressure(); // arterialPressureStabilizationStartTime = getMSTimerCount(); // arterialPressureBaselineCaptured = TRUE; // } // } // else 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, ARTERIAL_PRESSURE_LEAK_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; // F32 art = getFilteredArterialPressure(); // // if ( fabs( art ) <= ARTERIAL_PRESSURE_RELIEF_THRESHOLD_MMHG ) // { // state = DRY_SELF_TESTS_COMPLETE_STATE; // } // else if ( TRUE == didTimeout( arterialPressureReliefStartTime, PRESSURE_RELIEF_CHECK_TIME_MS ) ) // { // SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_ARTERIAL_PRESSURE_RELIEF, art ); // state = DRY_SELF_TESTS_STOPPED_STATE; // } // // return state; //} /*********************************************************************//** * @brief * The handleDrySelfTestStoppedState function handles the stopped dry self-tests * operation. * @details \b Inputs: selfTestsResumeRequested, tubingSetLeakChecksStarted * @details \b Outputs: selfTestsResumeRequested, selfTestStartTime * @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 resume request, resume dry self-tests if ( TRUE == selfTestsResumeRequested ) { // Restart self-test start time selfTestsResumeRequested = FALSE; selfTestStartTime = getMSTimerCount(); doorClosedRequired( TRUE ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); if ( TRUE == tubingSetLeakChecksStarted ) { pressureSelfTestPreNormalStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; } else { state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } return state; } /*********************************************************************//** * @brief * The drySelfTestHandleTubingSetAuthResponse 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: authResponseValidTubingSet, authResponseModalityAccepted, * authResponseReceived * @return TRUE if request is valid, FALSE otherwise *************************************************************************/ BOOL drySelfTestHandleTubingSetAuthResponse( MESSAGE_T *message ) { BOOL result = FALSE; if ( sizeof( UI_TUBING_SET_AUTH_RESPONSE_PAYLOAD_T ) == message->hdr.payloadLen ) { UI_TUBING_SET_AUTH_RESPONSE_PAYLOAD_T payload; memcpy( &payload, message->payload, sizeof( payload ) ); authResponseValidTubingSet = (BOOL)payload.validTubingSet; if ( payload.modalityTube == getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_MODALITY ) ) { authResponseModalityAccepted = TRUE; } else { authResponseModalityAccepted = FALSE; } authResponseReceived = TRUE; result = TRUE; } return result; } /*********************************************************************//** * @brief * The transitionToDrySelfTestsState function handles the transition to * dry self-test states by setting actuators. * @details \b Inputs: newState * @details \b Outputs: none * @param newState the targeted dry self-test state * @return none *************************************************************************/ static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ) { SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_OPERATION_STATUS, (U32)newState, 0 ); switch ( newState ) { 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 ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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_TUBING_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 ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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_TUBING_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 ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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_TUBING_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 ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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 ); if ( DRY_SELF_TESTS_TUBING_SET_AUTHENTICATION_STATE == newState ) { authenticationStartTime = getMSTimerCount(); } } break; case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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 ); resetArtVenPressureOffsets(); pressureSelfTestPreNormalStartTime = getMSTimerCount(); tubingSetLeakChecksStarted = TRUE; } break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_PRESSURE_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); setH4Direction( MOTOR_DIR_FORWARD ); setH4SetSpeed( PRESSURE_SELF_TEST_H4_SPEED_RPM ); setH4Enabled( TRUE ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); // H12 + H13 create positive venous pressure. setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_DUTY_CYCLE_MAX ); 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 ); SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_PRESSURE_RESULT, (U32)DRY_SELF_TESTS_NEG_ART_POS_VEN_PRESSURE_SETUP_STATE, 0 ); negArtPosVenSetupStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_STABILIZATION_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); 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 ); negArtPosVenStabilizationStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_NEG_ART_POS_VEN_DECAY_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); 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 ); negArtPosVenDecayStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_POS_ART_PRESSURE_SETUP_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); setH4Direction( MOTOR_DIR_REVERSE ); setH4SetSpeed( PRESSURE_SELF_TEST_H4_SPEED_RPM ); setH4Enabled( TRUE ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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 ); SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_PRESSURE_RESULT, (U32)DRY_SELF_TESTS_POS_ART_PRESSURE_SETUP_STATE, 0 ); posArtSetupStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_POS_ART_STABILIZATION_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); 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 ); posArtStabilizationStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_POS_ART_DECAY_CHECK_STATE: { U32 targetDialysateFlowMLPM = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); 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 ); posArtDecayStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_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 ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); 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 ); pressureReliefStartTime = getMSTimerCount(); } break; case DRY_SELF_TESTS_COMPLETE_STATE: signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); cmdChangeQuf( 0.0F ); break; case DRY_SELF_TESTS_STOPPED_STATE: signalBloodPumpHardStop(); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_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 handleDoorCloseAfterTubingSetInsertion function handles the check * for door close after tubing set install so that saline line can be pinched. * @details Inputs: none * @details Outputs: doorStateAfterTubingSetInstall * @return none *************************************************************************/ void handleDoorCloseAfterTubingSetInsertion( void ) { OPN_CLS_STATE_T door = getSwitchState( H9_SWCH ); if ( STATE_OPEN == door ) { doorStateAfterTubingSetInstall = FALSE; } if ( ( STATE_CLOSED == door ) && ( FALSE == doorStateAfterTubingSetInstall ) ) { if ( VALVE_STATE_IDLE == getValveState( H1_VALV ) ) { if ( TRUE == setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ) ) { doorStateAfterTubingSetInstall = TRUE; } } } } /**@}*/