/************************************************************************** * * 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 StatePreTxRecirculate.c * * @author (last) Vijay Pamula * @date (last) 02-June-2026 * * @author (original) Vijay Pamula * @date (original) 06-June-2026 * ***************************************************************************/ #include "TDCommon.h" #include "DDInterface.h" #include "AirPump.h" #include "BloodFlow.h" #include "Common.h" #include "Ejector.h" #include "Messaging.h" #include "OperationModes.h" #include "StatePreTxRecirculate.h" #include "Switches.h" #include "SyringePump.h" #include "Timers.h" #include "Valve3Way.h" #include "Valves.h" /** * @addtogroup StatePreTxRecirculate * @{ */ // ********** private definitions ********** #define PRE_TX_RECIRC_BLOOD_FLOW_RATE_ML_MIN 100 ///< Blood pump flow rate during recirculation in mL/min. #define PRE_TX_RECIRC_DIALYSATE_FLOW_RATE_ML_MIN 250 ///< Dialysate flow rate during recirculation in mL/min. #define RECIRC_MEDIUM_TIME_MS ( 90 * SEC_PER_MIN * MS_PER_SECOND ) ///< Pre-Treatment recirc time before medium priority warning in min. #define RECIRC_HIGH_TIME_MS ( 120 * SEC_PER_MIN * MS_PER_SECOND ) ///< Pre-Treatment recirc time before high priority alarm in min. typedef enum PreTxRecirculate_States { PRE_TX_RECIRCULATE_STATE = 0, PRE_TX_RECIRCULATE_STOPPED_STATE, NUM_OF_PRE_TX_RECIRCULATE_STATES } PRE_TX_RECIRCULATE_STATE_T; // ********** private data ********** static PRE_TX_RECIRCULATE_STATE_T currentPreTxRecircState; ///< Current pre-treatment recirculation sub-state. static BOOL recircResumeRequested; ///< Flag indicating resume recirculation was requested. static U32 preTxRecircStartTime; ///< Recirculation start time (ms timer count). static BOOL recircMediumAlarmGiven; ///< Flag indicating medium recirculation alarm has been raised. static BOOL recircHighAlarmGiven; ///< Flag indicating high recirculation alarm has been raised. // ********** private function prototypes ********** static void setupPreTxRecirculate( void ); static void resetPreTxRecircFlags( void ); static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateState( void ); static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateStoppedState( void ); /*********************************************************************//** * @brief * The initPreTxRecirculate function initializes the Pre-Treatment * Recirculate state data. * @details \b Inputs: none. * @details \b Outputs: currentPreTxRecircState, * recircResumeRequested, preTxRecircStartTime, * recircMediumAlarmGiven, recircHighAlarmGiven. * @return none. *************************************************************************/ void initPreTxRecirculate( void ) { currentPreTxRecircState = PRE_TX_RECIRCULATE_STATE; recircResumeRequested = FALSE; preTxRecircStartTime = getMSTimerCount(); recircMediumAlarmGiven = FALSE; recircHighAlarmGiven = FALSE; } /*********************************************************************//** * @brief * The transitionToPreTxRecirculate function transitions the software * into pre-treatment recirculation. * @details \b Inputs: none. * @details \b Outputs: currentPreTxRecircState. * @return none *************************************************************************/ void transitionToPreTxRecirculate( void ) { initPreTxRecirculate(); setupPreTxRecirculate(); setCurrentSubState( (U32)currentPreTxRecircState ); } /*********************************************************************//** * @brief * The execPreTxRecirculate function executes the Pre-Treatment * Recirculate state machine. * @details \b Inputs: currentPreTxRecircState, * preTxRecircStartTime, recircMediumAlarmGiven, * recircHighAlarmGiven, recircResumeRequested. * @details \b Outputs: currentPreTxRecircState, * recircMediumAlarmGiven, recircHighAlarmGiven, * recircResumeRequested. * @return none *************************************************************************/ void execPreTxRecirculate( void ) { PRE_TX_RECIRCULATE_STATE_T priorSubState = currentPreTxRecircState; if ( ( FALSE == recircHighAlarmGiven ) && ( TRUE == didTimeout( preTxRecircStartTime, RECIRC_HIGH_TIME_MS ) ) ) { recircHighAlarmGiven = TRUE; clearAlarm( ALARM_ID_TD_PRIME_COMPLETED_MEDIUM ); activateAlarmNoData( ALARM_ID_TD_PRIME_COMPLETED_HIGH ); } switch ( currentPreTxRecircState ) { case PRE_TX_RECIRCULATE_STATE: currentPreTxRecircState = handlePreTxRecirculateState(); break; case PRE_TX_RECIRCULATE_STOPPED_STATE: currentPreTxRecircState = handlePreTxRecirculateStoppedState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_PRE_TX_RECIRC_INVALID_STATE, currentPreTxRecircState ); break; } if ( priorSubState != currentPreTxRecircState ) { setCurrentSubState( (U32)currentPreTxRecircState ); SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorSubState, currentPreTxRecircState ); } resetPreTxRecircFlags(); } /*********************************************************************//** * @brief * The getPreTxRecirculateState function gets the current pre-treatment * recirculation sub-state. * @details \b Inputs: currentPreTxRecircState. * @details \b Outputs: none. * @return current pre-treatment recirculation sub-state. *************************************************************************/ U32 getPreTxRecirculateState( void ) { return currentPreTxRecircState; } /*********************************************************************//** * @brief * The signalResumePreTxRecirculate function signals a request to resume * pre-treatment recirculation. * @details \b Inputs: none. * @details \b Outputs: recircResumeRequested. * @return none *************************************************************************/ void signalResumePreTxRecirculate( void ) { recircResumeRequested = TRUE; } /*********************************************************************//** * @brief * The resetPreTxRecircFlags function resets recirculation request flags. * @details \b Inputs: none. * @details \b Outputs: recircResumeRequested. * @return none *************************************************************************/ static void resetPreTxRecircFlags( void ) { recircResumeRequested = FALSE; } /*********************************************************************//** * @brief * The handlePreTxRecirculateState function handles the * Recirculate sub-state. * @details \b Inputs: preTxRecircStartTime, * recircMediumAlarmGiven * @details \b Outputs: recircMediumAlarmGiven * @return next Recirculate sub-state *************************************************************************/ static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateState( void ) { PRE_TX_RECIRCULATE_STATE_T state = PRE_TX_RECIRCULATE_STATE; if ( ( FALSE == recircMediumAlarmGiven ) && ( TRUE == didTimeout( preTxRecircStartTime, RECIRC_MEDIUM_TIME_MS ) ) ) { recircMediumAlarmGiven = TRUE; activateAlarmNoData( ALARM_ID_TD_PRIME_COMPLETED_MEDIUM ); } if ( TRUE == doesAlarmStatusIndicateStop() ) { signalBloodPumpHardStop(); state = PRE_TX_RECIRCULATE_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief * The handlePreTxRecirculateStoppedState function handles the * Recirculate Stopped sub-state. * @details \b Inputs: recircResumeRequested * @details \b Outputs: recircResumeRequested * @return next Recirculate sub-state *************************************************************************/ static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateStoppedState( void ) { PRE_TX_RECIRCULATE_STATE_T state = PRE_TX_RECIRCULATE_STOPPED_STATE; if ( TRUE == recircResumeRequested ) { recircResumeRequested = FALSE; setupPreTxRecirculate(); state = PRE_TX_RECIRCULATE_STATE; } return state; } /*********************************************************************//** * @brief * The setupPreTxRecirculate function configures the actuators * required for Pre-Treatment Recirculation. * @details \b Inputs: none * @details \b Outputs: none * @return none *************************************************************************/ static void setupPreTxRecirculate( void ) { doorClosedRequired( TRUE ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); retractEjector(); stopSyringePump(); setBloodPumpTargetFlowRate( PRE_TX_RECIRC_BLOOD_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); // Direct DD to bypass dialyzer and perform no ultrafiltration cmdBypassDialyzer( TRUE ); cmdChangeQd( PRE_TX_RECIRC_DIALYSATE_FLOW_RATE_ML_MIN ); cmdChangeQuf( 0.0F ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /**@}*/