/************************************************************************** * * Copyright (c) 2024-2024 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 ModeStandby.c * * @author (last) Sean * @date (last) 30-Jul-2024 * * @author (original) Sean * @date (original) 30-Jul-2024 * ***************************************************************************/ #include "AirTrap.h" #include "Buttons.h" #include "DDInterface.h" #include "Messaging.h" #include "ModeTreatment.h" #include "ModeTxParams.h" #include "ModeStandby.h" #include "OperationModes.h" #include "Switches.h" #include "SystemCommTD.h" /** * @addtogroup TDStandbyMode * @{ */ // ********** private definitions ********** #define USER_COMMAND_CANCEL 0 ///< Cancel treatment workflow command code. #define USER_COMMAND_INITIATE 1 ///< Initiate treatment workflow command code. // ********** private data ********** static TD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. static BOOL treatStartReqReceived; ///< Flag indicates user has requested initiation of a treatment. // ********** private function prototypes ********** static TD_STANDBY_STATE_T handleStandbyModeStartState( void ); static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); /*********************************************************************//** * @brief * The initStandbyMode function initializes the Standby Mode Unit. * @details \b Inputs: none * @details \b Outputs: currentStandbyState, treatStartReqReceived * @return none *************************************************************************/ void initStandbyMode( void ) { currentStandbyState = STANDBY_START_STATE; treatStartReqReceived = FALSE; } /*********************************************************************//** * @brief * The transitionToStandbyMode function prepares for transition to standby mode. * @details \b Inputs: none * @details \b Outputs: Standby Mode unit re-initialized, DD interface initialized, * actuators off. * @return initial state *************************************************************************/ U32 transitionToStandbyMode( void ) { TD_OP_MODE_T previousOpMode = getPreviousOperationMode(); // Re-initialize when transitioning to standby mode initStandbyMode(); resetDDInterface(); setCurrentSubState( NO_SUB_STATE ); // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); // Pumps should be off // signalBloodPumpHardStop(); // stopSyringePump(); // Set valves to default positions // setValveAirTrap( VALVE_3WAY_COMMON_TO_CLOSED_STATE ); // setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); // setValvePosition( H19, VALVE_POSITION_A_INSERT_EJECT ); // doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode // syringeDetectionRequired( FALSE ); // Request DD service record and usage information from DD // sendDGServiceRequestToDG(); // sendDGUsageInfoRequestToDG(); return currentStandbyState; } /*********************************************************************//** * @brief * The execStandbyMode function executes the Standby Mode state machine. * @details \b Inputs: currentStandbyState * @details \b Outputs: currentStandbyState * @return current state (sub-mode) *************************************************************************/ U32 execStandbyMode( void ) { BOOL stop = isStopButtonPressed(); if ( TRUE == stop ) { // Ignore stop button in this mode. } // State machine for standby mode switch ( currentStandbyState ) { case STANDBY_START_STATE: currentStandbyState = handleStandbyModeStartState(); break; case STANDBY_WAIT_FOR_TREATMENT_STATE: currentStandbyState = handleStandbyModeWaitForTreatmentState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); currentStandbyState = STANDBY_START_STATE; break; } return currentStandbyState; } /*********************************************************************//** * @brief * The handleStandbyModeStartState function handles the standby start state. * This state waits for the door to be closed and then initiates homing of * pumps and valves and transitions to the wait for treatment state. * @details \b Inputs: * @details \b Outputs: * @return next state of the standby mode state machine *************************************************************************/ static TD_STANDBY_STATE_T handleStandbyModeStartState( void ) { TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Wait for door to be closed so we can home actuators // if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) // { // // If we haven't already initiated homing of actuators, initiate now // if ( homingInitiated != TRUE ) // { // VALVE_T valve; // // // Home pumps and valves // for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) // { // homeValve( valve, VALVE_NO_FORCE_HOME, VALVE_CARTRIDGE_MAY_BE_PRESENT ); // } // homeBloodPump(); // homeDialInPump(); // homeDialOutPump(); // retractSyringePump(); // // homingInitiated = TRUE; // } // else // { // // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration //#ifndef _RELEASE_ // if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) ) // { // state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check // } // else //#endif // { // if ( ( TRUE == isSyringePumpHome() ) && ( TRUE == isSyringePumpStopped() ) ) // { // syringePumpVerifyForceSensorDACCalibration(); // homingInitiated = FALSE; // reset for next time // doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode // state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check // } // } // } // } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForTreatmentState function handles wait for * treatment state. * @details \b Inputs: treatStartReqReceived * @details \b Outputs: treatStartReqReceived * @return next state of the standby mode state machine *************************************************************************/ static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) { TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; DD_OP_MODE_T ddOperationMode = getDDOpMode(); // switch ( dgOperationMode ) // { // case DG_MODE_GENE: // // If DG is in idle generation state while we are in standby mode, transition DG to standby too // cmdStopDG(); // break; // // // If DG is any of the cleaning modes, set the HD standby to be in the corresponding cleaning mode // case DG_MODE_FLUS: // case DG_MODE_HEAT: // case DG_MODE_CHEM: // case DG_MODE_CHFL: // case DG_MODE_HCOL: // case DG_MODE_ROPS: // setRequestedCleaningMode( dgOperationMode ); // state = STANDBY_WAIT_FOR_DG_CLEANING_MODE_TO_START_STATE; // break; // // default: // // Do nothing. There are other DG modes that HD standby does not need to act upon them. // break; // } // If DD is communicating and we don't yet have DD version info, request it // if ( TRUE == isDDCommunicating() ) // { // DG_VERSIONS_T ddVersion = getDDVersion(); // // if ( 0 == dgVersion.compatibilityRev ) // { // sendFWVersionRequest(); // } // } // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). if ( TRUE == treatStartReqReceived ) { // PRESSURE_LIMIT_CHANGE_RESPONSE_T respRecord = { TRUE, REQUEST_REJECT_REASON_NONE, 0, 0, 0 }; // Initialize treatment modes before starting a new treatment initTreatParamsMode(); // initPreTreatmentMode(); initTreatmentMode(); // initPostTreatmentMode(); resetAirTrap(); // Send UI default pressure settings since user is not asked to set them. // respRecord.artPresLimitWindowmmHg = getTreatmentParameterS32DefaultValue( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ); // respRecord.venPresLimitWindowmmHg = getTreatmentParameterS32DefaultValue( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ); // respRecord.venPresLimitAsymmetricmmHg = getTreatmentParameterS32DefaultValue( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ); // sendPressureLimitsChangeResponse( &respRecord ); // Start treatment workflow with treatment parameters mode requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } return state; } /*********************************************************************//** * @brief * The signalUserInitiateTreatment function handles user initiation of a * treatment. * @details \b Inputs: none * @details \b Outputs: treatStartReqReceived * @param message initiate/reject treatment workflow message from UI which * includes the command code (0=cancel, 1=initiate). * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateTreatment( MESSAGE_T *message ) { BOOL result = FALSE; U32 cmd = 0; TD_OP_MODE_T mode = getCurrentOperationMode(); REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; UI_RESPONSE_PAYLOAD_T response; // Verify message payload length is valid if ( sizeof( U32 ) == message->hdr.payloadLen ) { memcpy( &cmd, message->payload, sizeof( U32 ) ); if ( USER_COMMAND_INITIATE == cmd ) { // Verify TD is in standby mode waiting for treatment start request if ( ( mode != MODE_STAN ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } // Verify DD is communicating with HD else if ( isDDCommunicating() != TRUE ) { rejReason = REQUEST_REJECT_REASON_DD_COMM_LOST; } // Verify DD is not busy else if ( ( DD_MODE_STAN != getDDOpMode() ) || ( DD_STANDBY_MODE_STATE_IDLE != getDDSubMode() ) ) // || ( isDDPOSTPassed() != TRUE ) ) { rejReason = REQUEST_REJECT_REASON_DD_NOT_IN_STANDBY_IDLE_STATE; } else { // If request to start treatment not rejected, set flag to initiate treatment workflow result = TRUE; treatStartReqReceived = TRUE; } } else if ( USER_COMMAND_CANCEL == cmd ) { result = signalUserCancelTreatment(); if ( result != TRUE ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } } else { rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; } } // Respond to request to start treatment response.accepted = result; response.rejectionReason = rejReason; sendMessage( MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( UI_RESPONSE_PAYLOAD_T ) ); return result; } /*********************************************************************//** * @brief * The signalAlarmActionToStandbyMode function executes the given alarm action * as appropriate while in Standby Mode. * @details \b Inputs: none * @details \b Outputs: given alarm action executed * @param action ID of alarm action to execute * @return none *************************************************************************/ void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ) { switch ( action ) { case ALARM_ACTION_STOP: // if ( isAlarmActive( ALARM_ID_HD_VENOUS_BUBBLE_DETECTED ) != TRUE ) // { // // no stop action in standby mode // } // // if Dialin enabled bubble detection, stop on venous bubble detection alarm // else // { // // Pumps should be off // signalBloodPumpHardStop(); // stopSyringePump(); // // // Set valves to safe positions // setValveAirTrap( STATE_CLOSED ); // setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); // setValvePosition( H19, VALVE_POSITION_C_CLOSE ); // } break; default: // do not handle other actions in standby mode break; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /**@}*/