/************************************************************************** * * Copyright (c) 2019-2020 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 ModePreTreat.c * * @author (last) Sean Nash * @date (last) 06-Oct-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "AlarmMgmt.h" #include "ModePreTreat.h" #include "OperationModes.h" #include "Prime.h" #include "SystemCommMessages.h" /** * @addtogroup HDPreTreatmentMode * @{ */ // ********** private definitions ********** #define BLOOD_PUMP_RECIRC_FLOW_RATE 100 ///< Blood pump flow rate during recirculation in mL/min. #define DIALYSATE_PUMP_RECIRC_FLOW_RATE 100 ///< Dialysate pump flow rate during recirculation in mL/min. // ********** private data ********** static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user requests treatment begin. static BOOL patientConnectionStartReqReceived = FALSE; ///< Flag indicates user requests patient connection. static BOOL alarmActionStopReceived = FALSE; ///< Flag indicates alarm action stop received. static BOOL alarmActionResumeReceived = FALSE; ///< Flag indicates alarm action resume received. static HD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current state of pre-treatment mode state machine. static HD_PRE_TREATMENT_MODE_STATE_T resumePreTreatmentState; ///< Pre-treatment mode state to be resumed when alarm action resume signal receives. // ********** private function prototypes ********** static void handleAlarmActionStop( void ); static void handleAlarmActionResume( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateStartState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePretreatmentPauseState( void ); /*********************************************************************//** * @brief * The initPreTreatmentMode function initializes the Pre-Treatment Mode module. * @details Inputs: none * @details Outputs: Pre-Treatment Mode module initialized. * @return none *************************************************************************/ void initPreTreatmentMode( void ) { treatStartReqReceived = FALSE; patientConnectionStartReqReceived = FALSE; alarmActionStopReceived = FALSE; alarmActionResumeReceived = FALSE; currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; resumePreTreatmentState = HD_PRE_TREATMENT_START_STATE; } /*********************************************************************//** * @brief * The transitionToPreTreatmentMode function prepares for transition to * pre-treatment mode. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ void transitionToPreTreatmentMode( void ) { // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); initPreTreatmentMode(); } /*********************************************************************//** * @brief * The execPreTreatmentMode function executes the Pre-Treatment Mode state machine. * @details Inputs: none * @details Outputs: none * @return current state (sub-mode) *************************************************************************/ U32 execPreTreatmentMode( void ) { // execute mode state machine switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_START_STATE: cmdStartDG(); cmdSetDGDialysateTargetTemps( 39.0, 37.0 ); currentPreTreatmentState = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; break; case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: currentPreTreatmentState = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; break; case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: currentPreTreatmentState = handleSelfTestNoCartState(); break; case HD_PRE_TREATMENT_CART_INSTALL_STATE: currentPreTreatmentState = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; break; case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: currentPreTreatmentState = handleSelfTestDryState(); break; case HD_PRE_TREATMENT_PRIME_STATE: currentPreTreatmentState = handlePrimeState(); break; case HD_PRE_TREATMENT_RECIRCULATE_START_STATE: currentPreTreatmentState = handleRecirculateStartState(); break; case HD_PRE_TREATMENT_RECIRCULATE_STATE: currentPreTreatmentState = handleRecirculateState(); break; case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: currentPreTreatmentState = handlePatientConnectionState(); break; case HD_PRE_TREATMENT_PAUSE_STATE: currentPreTreatmentState = handlePretreatmentPauseState(); break; default: currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); break; } return (U32)currentPreTreatmentState; } /*********************************************************************//** * @brief * The signalUserBeginningTreatment function handles user start of a * treatment. * @details Inputs: none * @details Outputs: treatStartReqReceived, send response to treatment start * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserBeginningTreatment( void ) { BOOL result = FALSE; if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) { treatStartReqReceived = TRUE; result = TRUE; } sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected return result; } /*********************************************************************//** * @brief * The signalAlarmActionToPreTreatmentMode function executes the given alarm action * as appropriate while in PreTreatment Mode. * @details Inputs: none * @details Outputs: given alarm action executed * @param action ID of alarm action to execute * @return none *************************************************************************/ void signalAlarmActionToPreTreatmentMode( ALARM_ACTION_T action ) { switch( action ) { case ALARM_ACTION_STOP: handleAlarmActionStop(); break; case ALARM_ACTION_RESUME: handleAlarmActionResume(); break; case ALARM_ACTION_END_TREATMENT: requestNewOperationMode( MODE_POST ); break; case ALARM_ACTION_ACK: // Nothing to be done here break; default: // Ignore break; } } /*********************************************************************//** * @brief * The handleAlarmActionStop function forwards the alarm action to corresponding * sub-mode and sets appropriate flag to allow corresponding sub-mode handles. * @details Inputs: currentPreTreatmentState * @details Outputs: signals corresponding sub-mode of alarm action * @return none *************************************************************************/ static void handleAlarmActionStop( void ) { switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_PRIME_STATE: signalAlarmActionToPrimeMode( ALARM_ACTION_STOP ); break; case HD_PRE_TREATMENT_RECIRCULATE_STATE: // The corresponding sub-mode will handle the signal alarmActionStopReceived = TRUE; break; case HD_PRE_TREATMENT_START_STATE: case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: case HD_PRE_TREATMENT_CART_INSTALL_STATE: case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: // do nothing break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); break; } } /*********************************************************************//** * @brief * The handleAlarmActionResume function forwards the alarm action to corresponding * sub-mode and sets appropriate flag to allow corresponding sub-mode handles. * @details Inputs: currentPreTreatmentState * @details Outputs: signals corresponding sub-mode of alarm action * @return none *************************************************************************/ static void handleAlarmActionResume( void ) { switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_PRIME_STATE: signalAlarmActionToPrimeMode( ALARM_ACTION_RESUME ); break; case HD_PRE_TREATMENT_RECIRCULATE_STATE: case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: case HD_PRE_TREATMENT_START_STATE: case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: case HD_PRE_TREATMENT_CART_INSTALL_STATE: case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: // do nothing break; case HD_PRE_TREATMENT_PAUSE_STATE: alarmActionResumeReceived = TRUE; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); break; } } /*********************************************************************//** * @brief * The handleSelfTestNoCartState function handles self-test with no cartridge. * @details Inputs: none * @details Outputs: home blood pump and dialysate pumps * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ) { // TODO: Prompt user to close door VALVE_T valve; for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) { homeValve( valve ); } homeBloodPump(); homeDialInPump(); homeDialOutPump(); // TODO: Prompt user to open door return HD_PRE_TREATMENT_CART_INSTALL_STATE; } /*********************************************************************//** * @brief * The handleSelfTestDryState function performs dry self-test. * @details Inputs: none * @details Outputs: transition to prime sub-mode when blood pump finished homing * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ) { HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_CART_INSTALL_STATE; if ( FALSE == isBloodPumpRunning() ) { transitionToPrime(); state = HD_PRE_TREATMENT_PRIME_STATE; } return state; } /*********************************************************************//** * @brief * The handlePrimeState function handles priming the blood and dialysate circuits. * @details Inputs: none * @details Outputs: transition to self test wet state after priming passed * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ) { HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_PRIME_STATE; execPrime(); if ( TRUE == isWetSelfTestsPassed() ) { state = HD_PRE_TREATMENT_RECIRCULATE_START_STATE; activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); } return state; } /*********************************************************************//** * @brief * The handleRecirculateStartState function change valves and heater settings * for recirculation state during pre-treatment mode. * @details Inputs: none * @details Outputs: controlled valves and pumps * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateStartState( void ) { setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); setValveAirTrap( STATE_CLOSED ); cmdSetDGActiveReservoir( DG_RESERVOIR_1 ); cmdStartDGTrimmerHeater(); setBloodPumpTargetFlowRate( BLOOD_PUMP_RECIRC_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( DIALYSATE_PUMP_RECIRC_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); signalDialOutPumpHardStop(); return HD_PRE_TREATMENT_RECIRCULATE_STATE; } /*********************************************************************//** * @brief * The handleRecirculateState function handles blood and dialysate circuits * recirculation state during pre-treatment mode. * @details Inputs: none * @details Outputs: controlled valves and pumps * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ) { HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_RECIRCULATE_STATE; // TODO Add handler to UI interaction patientConnectionStartReqReceived = TRUE; if ( TRUE == patientConnectionStartReqReceived ) { state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; } if ( TRUE == alarmActionStopReceived ) { signalDialOutPumpHardStop(); signalDialInPumpHardStop(); signalBloodPumpHardStop(); cmdStopDGTrimmerHeater(); state = HD_PRE_TREATMENT_PAUSE_STATE; resumePreTreatmentState = HD_PRE_TREATMENT_RECIRCULATE_START_STATE; } return state; } /*********************************************************************//** * @brief * The handlePatientConnectionState function handles patient connection state * during pre-treatment mode. * @details Inputs: none * @details Outputs: requested mode transition to treatment mode * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) { if ( TRUE == treatStartReqReceived ) { requestNewOperationMode( MODE_TREA ); } return HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; } /*********************************************************************//** * @brief * The handlePretreatmentPauseState function handles pre-treatment pause state. * @details Inputs: previousPrimeState * @details Outputs: primeStartTime, primeResumeReqReceived * @return current state *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePretreatmentPauseState( void ) { HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_PAUSE_STATE; if ( TRUE == alarmActionResumeReceived ) { alarmActionResumeReceived = FALSE; state = resumePreTreatmentState; } return state; } /**@}*/