/************************************************************************** * * 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 StatePreTxHeparinSetup.c * * @author (last) Vijay Pamula * @date (last) 06-Jun-2026 * * @author (original) Vijay Pamula * @date (original) 06-Jun-2026 * ***************************************************************************/ #include "AlarmMgmtTD.h" #include "Messaging.h" #include "ModePreTreat.h" #include "OperationModes.h" #include "StatePreTxHeparinSetup.h" #include "SyringePump.h" #include "TxParams.h" /** * @addtogroup StatePreTxHeparinSetup * @{ */ // ********** private definitions ********** /// Enumeration of Pre-Treatment Heparin Setup sub-states. typedef enum { PRE_TX_HEPARIN_SETUP_PRELOAD_STATE = 0, ///< Preload heparin syringe state. PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE, ///< Await syringe load confirmation state. PRE_TX_HEPARIN_SETUP_SEEK_STATE, ///< Seek syringe plunger state. PRE_TX_HEPARIN_SETUP_PRIME_STATE, ///< Prime heparin line state. PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE, ///< Heparin setup occlusion check state. PRE_TX_HEPARIN_SETUP_BOLUS_STATE, ///< Deliver heparin bolus state. PRE_TX_HEPARIN_SETUP_PAUSED_STATE, ///< Paused state. NUM_OF_PRE_TX_HEPARIN_SETUP_STATES ///< Number of pre-treatment heparin setup substates. } PRE_TX_HEPARIN_SETUP_STATE_T; // ********** private data ********** static PRE_TX_HEPARIN_SETUP_STATE_T currentPreTxHeparinSetupState; ///< Current state of the pre-treatment heparin setup state machine. static PRE_TX_HEPARIN_SETUP_STATE_T interruptedPreTxHeparinSetupState; ///< Pre-treatment heparin setup substate interrupted by a recoverable alarm. static BOOL heparinSetupResumeRequested; ///< Flag indicates alarm requesting to resume pre-treatment heparin setup. static BOOL syringeLoadConfirmed; ///< Flag indicates user confirmed syringe load. static BOOL syringeRetractStarted; ///< Flag indicating syringe retract has been initiated. static BOOL syringePreloadStarted; ///< Flag indicating syringe preload has been initiated. // ********** private function prototypes ********** static void resetPreTxHeparinSetupFlags( void ); static void setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_STATE_T state ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPreloadState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinAwaitSyringeLoadConfirmationState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinSeekState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPrimeState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinOcclusionCheckState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinBolusState( void ); static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPausedState( void ); /*********************************************************************//** * @brief * The initPreTxHeparinSetup function initializes the pre-treatment * heparin setup state machine. * @details \b Inputs: none. * @details \b Outputs: currentPreTxHeparinSetupState, * interruptedPreTxHeparinSetupState, syringeRetractStarted, * syringePreloadStarted, heparinSetupResumeRequested, and * syringeLoadConfirmed. * @return none. *************************************************************************/ void initPreTxHeparinSetup( void ) { currentPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; syringeRetractStarted = FALSE; syringePreloadStarted = FALSE; resetPreTxHeparinSetupFlags(); } /*********************************************************************//** * @brief * The transitionToPreTxHeparinSetup function prepares for transition * into the pre-treatment heparin setup state. * @details \b Inputs: currentPreTxHeparinSetupState. * @details \b Outputs: resume alarm user action enabled and current * pre-treatment substate. * @return none. *************************************************************************/ void transitionToPreTxHeparinSetup( void ) { setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setCurrentSubState( (U32)currentPreTxHeparinSetupState ); } /*********************************************************************//** * @brief * The execPreTxHeparinSetup function executes the pre-treatment heparin * setup state machine. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if the current * pre-treatment heparin setup state is invalid. * @details \b Inputs: currentPreTxHeparinSetupState. * @details \b Outputs: currentPreTxHeparinSetupState, current substate, * TD_EVENT_SUB_STATE_CHANGE event, heparinSetupResumeRequested, and * syringeLoadConfirmed. * @return none. *************************************************************************/ void execPreTxHeparinSetup( void ) { PRE_TX_HEPARIN_SETUP_STATE_T priorSubState = currentPreTxHeparinSetupState; switch ( currentPreTxHeparinSetupState ) { case PRE_TX_HEPARIN_SETUP_PRELOAD_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinPreloadState(); break; case PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinAwaitSyringeLoadConfirmationState(); break; case PRE_TX_HEPARIN_SETUP_SEEK_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinSeekState(); break; case PRE_TX_HEPARIN_SETUP_PRIME_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinPrimeState(); break; case PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinOcclusionCheckState(); break; case PRE_TX_HEPARIN_SETUP_BOLUS_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinBolusState(); break; case PRE_TX_HEPARIN_SETUP_PAUSED_STATE: currentPreTxHeparinSetupState = handlePreTxHeparinPausedState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE, currentPreTxHeparinSetupState ); break; } if ( priorSubState != currentPreTxHeparinSetupState ) { setCurrentSubState( (U32)currentPreTxHeparinSetupState ); SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorSubState, currentPreTxHeparinSetupState ); } resetPreTxHeparinSetupFlags(); } /*********************************************************************//** * @brief * The getPreTxHeparinSetupState function returns the current state of the * pre-treatment heparin setup state machine. * @details \b Inputs: currentPreTxHeparinSetupState. * @details \b Outputs: none. * @return Current pre-treatment heparin setup state. *************************************************************************/ U32 getPreTxHeparinSetupState( void ) { return (U32)currentPreTxHeparinSetupState; } /*********************************************************************//** * @brief * The signalResumePreTxHeparinSetup function signals a resume request for * the pre-treatment heparin setup state machine. * @details \b Inputs: none. * @details \b Outputs: heparinSetupResumeRequested. * @return none. *************************************************************************/ void signalResumePreTxHeparinSetup( void ) { heparinSetupResumeRequested = TRUE; } /*********************************************************************//** * @brief * The isPreTxHeparinAwaitingSyringeLoadConfirmation function reports * whether the Heparin Setup state machine is awaiting syringe load * confirmation. * @details \b Inputs: currentPreTxHeparinSetupState. * @details \b Outputs: none. * @return TRUE if awaiting syringe load confirmation, FALSE otherwise. *************************************************************************/ BOOL isPreTxHeparinAwaitingSyringeLoadConfirmation( void ) { return ( PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE == currentPreTxHeparinSetupState ) ? TRUE : FALSE; } /*********************************************************************//** * @brief * The signalPreTxHeparinSyringeLoadConfirmed function signals that the * user confirmed syringe load. * @details \b Inputs: none. * @details \b Outputs: syringeLoadConfirmed. * @return none. *************************************************************************/ void signalPreTxHeparinSyringeLoadConfirmed( void ) { syringeLoadConfirmed = TRUE; } /*********************************************************************//** * @brief * The resetPreTxHeparinSetupFlags function resets all signal flags used by * the pre-treatment heparin setup state machine. * @details \b Inputs: none. * @details \b Outputs: heparinSetupResumeRequested and * syringeLoadConfirmed. * @return none. *************************************************************************/ static void resetPreTxHeparinSetupFlags( void ) { heparinSetupResumeRequested = FALSE; syringeLoadConfirmed = FALSE; } /*********************************************************************//** * @brief * The setupPreTxHeparinState function configures the syringe pump for the * specified pre-treatment heparin setup state. * @details \b Inputs: none. * @details \b Outputs: syringe pump operating state. * @param state Pre-treatment heparin setup state to configure. * @return none. *************************************************************************/ static void setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_STATE_T state ) { stopSyringePump(); switch ( state ) { case PRE_TX_HEPARIN_SETUP_PRELOAD_STATE: // Retract and preload sequencing is handled by // handlePreTxHeparinPreloadState(). break; case PRE_TX_HEPARIN_SETUP_SEEK_STATE: seekSyringePlunger(); break; case PRE_TX_HEPARIN_SETUP_PRIME_STATE: primeSyringePump(); break; case PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE: // No additional setup required. break; case PRE_TX_HEPARIN_SETUP_BOLUS_STATE: startHeparinBolus(); break; case PRE_TX_HEPARIN_SETUP_PAUSED_STATE: // Syringe pump already stopped above. break; default: break; } } /*********************************************************************//** * @brief * The handlePreTxHeparinPreloadState function handles the syringe pump * retract and preload sequence. * @details \b Alarm: ALARM_ID_UI_RESERVED_127 when syringe preload is * complete and syringe loading confirmation is required. * @details \b Inputs: syringeRetractStarted, syringePreloadStarted, * alarm stop status, syringe pump position, preload status, and syringe * pump operating status. * @details \b Outputs: interruptedPreTxHeparinSetupState, * syringeRetractStarted, syringePreloadStarted, syringe pump operating * state, and preload status. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPreloadState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( TRUE == isSyringePumpPreLoaded() ) { activateAlarmNoData( ALARM_ID_UI_RESERVED_127 ); state = PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE; } else if ( FALSE == isSyringePumpPositionKnown() ) { if ( ( FALSE == syringeRetractStarted ) && ( FALSE == isSyringePumpRunning() ) ) { syringeRetractStarted = retractSyringePump(); } } else if ( FALSE == syringePreloadStarted ) { if ( FALSE == isSyringePumpRunning() ) { resetPreLoadStatus(); syringePreloadStarted = preloadSyringePlunger(); } } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinAwaitSyringeLoadConfirmationState function handles * the await syringe load confirmation state. * @details \b Inputs: syringeLoadConfirmed and alarm stop status. * @details \b Outputs: interruptedPreTxHeparinSetupState and syringe * pump operating state. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinAwaitSyringeLoadConfirmationState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( TRUE == syringeLoadConfirmed ) { setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_SEEK_STATE ); state = PRE_TX_HEPARIN_SETUP_SEEK_STATE; } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinSeekState function handles the syringe plunger * seek state. * @details \b Inputs: alarm stop status, syringe plunger status, and * syringe volume adequacy status. * @details \b Outputs: interruptedPreTxHeparinSetupState and syringe * pump operating state. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinSeekState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_SEEK_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_SEEK_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( TRUE == isSyringePlungerFound() ) { if ( TRUE == isSyringeVolumeAdequate() ) { setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PRIME_STATE ); state = PRE_TX_HEPARIN_SETUP_PRIME_STATE; } else { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_SEEK_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinPrimeState function handles the syringe pump * prime state. * @details \b Inputs: alarm stop status and syringe pump prime status. * @details \b Outputs: interruptedPreTxHeparinSetupState and syringe * pump operating state. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPrimeState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_PRIME_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_PRIME_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( TRUE == isSyringePumpPrimed() ) { setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE ); state = PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE; } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinOcclusionCheckState function handles the heparin * pump occlusion check state. * @details \b Alarm: ALARM_ID_TD_SYRINGE_PUMP_OCCLUSION if the syringe * pump occlusion check fails. * @details \b Inputs: alarm stop status, syringe pump occlusion status, * and TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME. * @details \b Outputs: interruptedPreTxHeparinSetupState, syringe pump * operating state, and pre-treatment continuation request. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinOcclusionCheckState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( FALSE == checkForSyringeOcclusion( FALSE ) ) { // Occlusion check passed. Continue to bolus if prescribed; otherwise continue to Patient Connection. if ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ) > 0.0F ) { setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_BOLUS_STATE ); state = PRE_TX_HEPARIN_SETUP_BOLUS_STATE; } else { PreTxRequestContinueFromHeparinSetupRequested(); } } else { // Occlusion check failed. Alarm is handled by checkForSyringeOcclusion(). interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinBolusState function handles the heparin bolus * state. * @details \b Inputs: alarm stop status and syringe pump stop status. * @details \b Outputs: interruptedPreTxHeparinSetupState, syringe pump * operating state, and pre-treatment continuation request. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinBolusState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_BOLUS_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { interruptedPreTxHeparinSetupState = PRE_TX_HEPARIN_SETUP_BOLUS_STATE; setupPreTxHeparinState( PRE_TX_HEPARIN_SETUP_PAUSED_STATE ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; } else if ( TRUE == isSyringePumpStopped() ) { PreTxRequestContinueFromHeparinSetupRequested(); } return state; } /*********************************************************************//** * @brief * The handlePreTxHeparinPausedState function handles the paused * pre-treatment heparin setup state. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if the interrupted * pre-treatment heparin setup state is invalid. * @details \b Inputs: heparinSetupResumeRequested and * interruptedPreTxHeparinSetupState. * @details \b Outputs: syringeRetractStarted, syringePreloadStarted, * preload status, and syringe pump operating state. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPausedState( void ) { PRE_TX_HEPARIN_SETUP_STATE_T state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; if ( TRUE == heparinSetupResumeRequested ) { switch ( interruptedPreTxHeparinSetupState ) { // If interrupted before Seek is complete, retract the syringe // and restart the heparin setup sequence from Preload. case PRE_TX_HEPARIN_SETUP_PRELOAD_STATE: case PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE: case PRE_TX_HEPARIN_SETUP_SEEK_STATE: syringeRetractStarted = FALSE; syringePreloadStarted = FALSE; resetPreLoadStatus(); syringeRetractStarted = retractSyringePump(); state = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; break; // If interrupted after Seek is complete, resume from the // heparin setup state that was active before the alarm. case PRE_TX_HEPARIN_SETUP_PRIME_STATE: case PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE: case PRE_TX_HEPARIN_SETUP_BOLUS_STATE: state = interruptedPreTxHeparinSetupState; setupPreTxHeparinState( state ); break; // An unexpected interrupted state indicates a software fault. default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE, interruptedPreTxHeparinSetupState ); state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; break; } } return state; } /**@}*/