/************************************************************************** * * Copyright (c) 2025-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 TubeSetInstall.c * * @author (last) Praneeth Bunne * @date (last) 28-Apr-2026 * * @author (original) Praneeth Bunne * @date (Original) 28-Apr-2026 * ***************************************************************************/ #include "AlarmMgmt.h" #include "BloodFlow.h" #include "Messaging.h" #include "OperationModes.h" #include "PeristalticPump.h" #include "Switches.h" #include "TaskGeneral.h" #include "TDDefs.h" #include "Timers.h" #include "StateServices/TubeSetInstall.h" /** * @addtogroup TubeSetInstall * @{ */ // ********** private definitions ********** ///< BP timeout interval (ms/task time) #define BLOOD_PUMP_TIMEOUT_INTERVAL ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) //< Blood pump flow rate (mL/min) for Auto-Load operation #define AUTO_LOAD_BLOOD_FLOW_RATE_ML_MIN 100U /// Blood pump torque threshold (mN.m) above which a tube-set jam is declared #define INSTALL_AUTO_LOAD_TORQUE_LIMIT_MNM 9999.0F // TODO: Replace with lab characterized value // ********** private data ********** static BOOL confirmTubesetPlaced; ///< Flag indicating user has confirmed tubeset is placed static U32 bloodPumpTimerCounter; ///< Blood Pump timer counter static BOOL installComplete; ///< True once the service has finished successfully static TUBE_SET_INSTALL_STATE_T currentInstallState; ///< Current Tubing Set Install sub-state // ********** private function prototypes ********** static TUBE_SET_INSTALL_STATE_T handleAwaitTubesetConfirmationState( void ); ///< Handle Await Tubset Install Confirmation sub-state static TUBE_SET_INSTALL_STATE_T handleAutoLoadState( void ); ///< Handle Auto-Load sub-state static TUBE_SET_INSTALL_STATE_T handleAutoLoadBackOffState( void ); ///< Handle Auto-Load Back-off sub-state /*********************************************************************//** * @brief * The initTubeSetInstall function initializes the Tube Set Install service. * @details Inputs: none * @details Outputs: Resets the flags, counters and sets the initial * Tube Set Install sub-state. * @return none **************************************************************************/ void initTubeSetInstall( void ) { currentInstallState = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; confirmTubesetPlaced = FALSE; bloodPumpTimerCounter = 0; installComplete = FALSE; } /*********************************************************************//** * @brief * The execTubeSetInstall function executes the Tube Set Install * state machine. * @details Inputs: currentInstallState * @details Outputs: currentInstallState, installComplete. Advances the * Tube Set Install sub-state * @return none *************************************************************************/ void execTubeSetInstall( void ) { if( TRUE == installComplete ) { return; } switch( currentInstallState ) { case TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION: currentInstallState = handleAwaitTubesetConfirmationState(); break; case TUBE_SET_INSTALL_STATE_AUTO_LOAD: currentInstallState = handleAutoLoadState(); break; case TUBE_SET_INSTALL_STATE_AUTO_LOAD_BACK_OFF: currentInstallState = handleAutoLoadBackOffState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TX_INSTALL_INVALID_STATE, (U32)currentInstallState ); break; } } /*********************************************************************//** * @brief * The handleAwaitTubesetConfirmationState function handles the Await * tubeset confirmation state of Tubing Set install state machine. * Should wait for the user to confirm the tubeset is placed, and * verifies that the blood pump door (H9) is closed. * @details Inputs: confirmTubsetPlaced, H9_SWCH state * @details Outputs: confirmTubesetPlaced * return next Pre-Treatment Install sub-state *************************************************************************/ static TUBE_SET_INSTALL_STATE_T handleAwaitTubesetConfirmationState( void ) { TUBE_SET_INSTALL_STATE_T state = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; if ( TRUE == confirmTubesetPlaced ) { // Door closed required from Auto-loading onwards, set to false if not required in subsequent states doorClosedRequired( TRUE ); if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) { confirmTubesetPlaced = FALSE; setBloodPumpTargetFlowRate( AUTO_LOAD_BLOOD_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); state = TUBE_SET_INSTALL_STATE_AUTO_LOAD; } } return state; } /*********************************************************************//** * @brief * The handleAutoLoadState function handles the Auto-Load state of * Tube Set install state. * @details Inputs: bloodPumpTimerCounter, getMeasuredBloodPumpTorque() * isPeristalticPumpHome() * @details Outputs: bloodPumpTimerCounter, installComplete * return next Pre-Treatment Install sub-state *************************************************************************/ static TUBE_SET_INSTALL_STATE_T handleAutoLoadState( void ) { TUBE_SET_INSTALL_STATE_T state = TUBE_SET_INSTALL_STATE_AUTO_LOAD; F32 bpTorque = getMeasuredBloodPumpTorque(); // Timeout check if ( ++bloodPumpTimerCounter >= BLOOD_PUMP_TIMEOUT_INTERVAL ) { signalBloodPumpHardStop(); SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_AUTO_LOAD_EJECT_BP_TIMEOUT, isPeristalticPumpHome(), bloodPumpTimerCounter ); } else if ( bpTorque > INSTALL_AUTO_LOAD_TORQUE_LIMIT_MNM ) { signalBloodPumpHardStop(); SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_AUTO_LOAD_BLOOD_TUBE_SET_FAILURE, bpTorque ); setBloodPumpTargetFlowRate( AUTO_LOAD_BLOOD_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); bloodPumpTimerCounter = 0; state = TUBE_SET_INSTALL_STATE_AUTO_LOAD_BACK_OFF; } else if ( TRUE == isPeristalticPumpHome() ) { signalBloodPumpHardStop(); bloodPumpTimerCounter = 0; installComplete = TRUE; state = NUM_OF_TUBE_SET_INSTALL_SUB_STATES; } return state; } /*********************************************************************//** * @brief * The handleAutoLoadBackOffState function handles the Auto-Load Back-Off * state of Tube Set install state. * @details Inputs: bloodPumpTimerCounter, isPeristalticPumpHome() * @details Outputs: bloodPumpTimerCounter * return next install sub-state *************************************************************************/ static TUBE_SET_INSTALL_STATE_T handleAutoLoadBackOffState( void ) { TUBE_SET_INSTALL_STATE_T state = TUBE_SET_INSTALL_STATE_AUTO_LOAD_BACK_OFF; if ( bloodPumpTimerCounter >= BLOOD_PUMP_TIMEOUT_INTERVAL ) { signalBloodPumpHardStop(); SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_AUTO_LOAD_EJECT_BP_TIMEOUT, isPeristalticPumpHome(), bloodPumpTimerCounter ); } else if ( TRUE == isPeristalticPumpHome() ) { clearAlarmTD( ALARM_ID_TD_AUTO_LOAD_BLOOD_TUBE_SET_FAILURE ); if ( FALSE == isAlarmActive( ALARM_ID_TD_AUTO_LOAD_BLOOD_TUBE_SET_FAILURE ) ) { signalBloodPumpHardStop(); bloodPumpTimerCounter = 0; state = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; } } return state; } /*********************************************************************//** * @brief * The isTubeSetInstallComplete function reports whether the install * service has finished successfully. * @details \b Inputs: installComplete * @details \b Outputs: none * @return TRUE if auto-load completed and pump is at home, FALSE otherwise. *************************************************************************/ BOOL isTubeSetInstallComplete( void ) { return installComplete; } /*********************************************************************//** * @brief * The handleAutoLoadRequest function handles a UI request to * confirm tubeset installation. * @details Inputs: none * @details Outputs: confirmTubesetPlaced * @param message UI message which includes the user confirmation of * tubset installation. * @return TRUE if confirmation/rejection accepted, FALSE if not *************************************************************************/ BOOL handleAutoLoadRequest( MESSAGE_T *message ) { BOOL result = FALSE; BOOL modeValid = FALSE; TD_OP_MODE_T mode = getCurrentOperationMode(); UI_RESPONSE_PAYLOAD_T response; response.rejectionReason = REQUEST_REJECT_REASON_NONE; if ( 0 == message->hdr.payloadLen ) { modeValid = ( ( MODE_PRET == mode ) || ( MODE_TREA == mode ) ? TRUE : FALSE ); if ( ( TRUE != modeValid ) || ( TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION != currentInstallState ) ) { response.rejectionReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } else { confirmTubesetPlaced = TRUE; result = TRUE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_MESSAGE_PAYLOAD_LENGTH, (U32)message->hdr.payloadLen ); } response.accepted = result; sendMessage( MSG_ID_TD_ADJUST_DISPOSABLES_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( UI_RESPONSE_PAYLOAD_T ) ); return result; } /**@}*/