/************************************************************************** * * 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 Rinseback.c * * @author (last) Sean Nash * @date (last) 14-Jan-2021 * * @author (original) Sean * @date (original) 14-Jan-2021 * ***************************************************************************/ #include "AirTrap.h" #include "BloodFlow.h" #include "Buttons.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "Rinseback.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TreatmentStop.h" #include "Valves.h" /** * @addtogroup Rinseback * @{ */ // ********** private definitions ********** #define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). #define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25.0 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. #define MIN_RINSEBACK_FLOW_RATE_ML_MIN 50.0 ///< Minimum rinseback flow rate (in mL/min). #define MAX_RINSEBACK_FLOW_RATE_ML_MIN 150.0 ///< Maximum rinseback flow rate (in mL/min). static const F32 RINSEBACK_FLOW_INTEGRATOR = 1.0 / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); // ********** private data ********** static RINSEBACK_STATE_T rinsebackState; ///< Current state of the rinseback sub-mode. static F32 cumulativeRinsebackVolume_mL; ///< Total cumulative rinseback volume (in mL). static BOOL rinsebackStopRequested; ///< Flag indicates alarm requesting to stop rinseback. static BOOL startRinsebackRequested; ///< Flag indicates user requesting rinseback start (confirming saline bag move to arterial line end). static BOOL incrRinsebackFlowRateRequested; ///< Flag indicates user requesting rinseback flow rate be increased. static BOOL decrRinsebackFlowRateRequested; ///< Flag indicates user requesting rinseback flow rate be decreased. static BOOL pauseRinsebackRequested; ///< Flag indicates user requesting rinseback pause. static BOOL resumeRinsebackRequested; ///< Flag indicates user requesting rinseback resume. static BOOL endRinsebackRequested; ///< Flag indicates user requesting to end rinseback operation. static BOOL additionalRinsebackRequested; ///< Flag indicates user requesting a little more rinseback volume. static BOOL recircRequested; ///< Flag indicates user requesting to begin re-circulation (confirming disconnection and shunt). static BOOL backToTreatmentRequested; ///< Flag indicates user requesting to go back to treatment (confirming still connected). static BOOL endTreatmentRequested; ///< Flag indicates user requesting to end treatment. // ********** private function prototypes ********** static void resetRinsebackFlags( void ); static RINSEBACK_STATE_T handleRinsebackStopInitState( void ); static RINSEBACK_STATE_T handleRinsebackRunState( void ); static RINSEBACK_STATE_T handleRinsebackPausedState( void ); static RINSEBACK_STATE_T handleRinsebackStoppedState( void ); static RINSEBACK_STATE_T handleRinsebackRunAdditionalState( void ); static BOOL handleStartRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleIncrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleDecrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handlePauseRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleResumeRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleEndRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleAdditionalRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleToRecircUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleBackToTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleEndTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); /*********************************************************************//** * @brief * The initRinseback function initializes the Rinseback sub-mode module. * @details Inputs: none * @details Outputs: Rinseback sub-mode module initialized. * @return none *************************************************************************/ void initRinseback( void ) { rinsebackState = RINSEBACK_STOP_INIT_STATE; cumulativeRinsebackVolume_mL = 0.0; resetRinsebackFlags(); } /*********************************************************************//** * @brief * The resetRinsebackFlags function resets the Rinseback request flags. * @details Inputs: none * @details Outputs: Rinseback request flags reset to FALSE. * @return none *************************************************************************/ static void resetRinsebackFlags( void ) { rinsebackStopRequested = FALSE; startRinsebackRequested = FALSE; incrRinsebackFlowRateRequested = FALSE; decrRinsebackFlowRateRequested = FALSE; pauseRinsebackRequested = FALSE; resumeRinsebackRequested = FALSE; endRinsebackRequested = FALSE; additionalRinsebackRequested = FALSE; recircRequested = FALSE; backToTreatmentRequested = FALSE; endTreatmentRequested = FALSE; } /*********************************************************************//** * @brief * The transitionToRinseback function prepares for transition to Rinseback * sub-mode. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ void transitionToRinseback( void ) { initRinseback(); // Set user alarm recovery actions allowed in this sub-mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); // Set valves to safe state setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Ensure all pumps except DPi stopped signalBloodPumpHardStop(); signalDialOutPumpHardStop(); // TODO - stop Heparin pump // Re-circulate dialysate side of dialyzer w/ heating to maintain temperature setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); cmdStartDGTrimmerHeater(); } /*********************************************************************//** * @brief * The execRinseback function executes the Rinseback sub-mode state machine. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ void execRinseback( void ) { switch ( rinsebackState ) { case RINSEBACK_STOP_INIT_STATE: rinsebackState = handleRinsebackStopInitState(); //setBloodIsPrimed( FALSE ); TODO - call in handler when transition to RB run break; case RINSEBACK_RUN_STATE: rinsebackState = handleRinsebackRunState(); //setRinsebackIsCompleted( TRUE ); TODO - call in handler when rinseback is done break; case RINSEBACK_PAUSED_STATE: rinsebackState = handleRinsebackPausedState(); break; case RINSEBACK_STOP_STATE: rinsebackState = handleRinsebackStoppedState(); break; case RINSEBACK_RUN_ADDITIONAL_STATE: rinsebackState = handleRinsebackRunAdditionalState(); break; default: // TODO - s/w fault break; } // Rinseback flags should be handled by now - reset in case not handled by current state resetRinsebackFlags(); } /*********************************************************************//** * @brief * The handleRinsebackStopInitState function handles the stopped initial * rinseback state operations. * @details Inputs: none * @details Outputs: none * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackStopInitState( void ) { RINSEBACK_STATE_T result = RINSEBACK_STOP_INIT_STATE; return result; } /*********************************************************************//** * @brief * The handleRinsebackRunState function handles the rinseback run state * operations. * @details Inputs: none * @details Outputs: none * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackRunState( void ) { RINSEBACK_STATE_T result = RINSEBACK_RUN_STATE; // TODO - update rinseback volume cumulativeRinsebackVolume_mL += ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); // Has rinseback completed? if ( cumulativeRinsebackVolume_mL <= TARGET_RINSEBACK_VOLUME_ML ) { setRinsebackIsCompleted( TRUE ); result = RINSEBACK_STOP_STATE; } // Has user or alarm requested rinseback pause? else if ( ( TRUE == rinsebackStopRequested ) || ( TRUE == isAnyAlarmActive() ) ) { result = RINSEBACK_PAUSED_STATE; } // Otherwise, continue rinseback else { // Has user requested rate change? if ( ( TRUE == incrRinsebackFlowRateRequested ) || ( TRUE == incrRinsebackFlowRateRequested ) ) { // TODO - update rate if within limits } } return result; } /*********************************************************************//** * @brief * The handleRinsebackStopInitState function handles the rinseback paused * state operations. * @details Inputs: none * @details Outputs: none * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackPausedState( void ) { RINSEBACK_STATE_T result = RINSEBACK_PAUSED_STATE; return result; } /*********************************************************************//** * @brief * The handleRinsebackStoppedState function handles the stopped rinseback * state operations. * @details Inputs: none * @details Outputs: none * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackStoppedState( void ) { RINSEBACK_STATE_T result = RINSEBACK_STOP_STATE; return result; } /*********************************************************************//** * @brief * The handleRinsebackRunAdditionalState function handles the rinseback additional * state operations. * @details Inputs: none * @details Outputs: none * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackRunAdditionalState( void ) { RINSEBACK_STATE_T result = RINSEBACK_RUN_ADDITIONAL_STATE; return result; } /*********************************************************************//** * @brief * The signalStopRinseback function signals the rinseback sub-mode * to stop per an active alarm. * @details Inputs: none * @details Outputs: rinsebackStopRequested * @return none *************************************************************************/ void signalStopRinseback( void ) { rinsebackStopRequested = TRUE; } /*********************************************************************//** * @brief * The signalRinsebackUserAction function signals a rinseback user action * has been requested. The request is handled and responded to. * @details Inputs: none * @details Outputs: none * @param action User action requested * @return none *************************************************************************/ void signalRinsebackUserAction( REQUESTED_RINSEBACK_USER_ACTIONS_T action ) { BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; // Reject user action requests if any alarm is currently active. User must clear alarm first. if ( FALSE == isAnyAlarmActive() ) { switch ( action ) { case REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_START: accepted = handleStartRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_INCREASE_RATE: accepted = handleIncrRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_DECREASE_RATE: accepted = handleDecrRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_PAUSE: accepted = handlePauseRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_RESUME: accepted = handleResumeRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_END: accepted = handleEndRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_ADDITIONAL: accepted = handleAdditionalRinsebackUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_DISCONNECT: accepted = handleToRecircUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_END_TREATMENT: accepted = handleBackToTreatmentUserAction( &rejReason ); break; case REQUESTED_USER_ACTION_RINSEBACK_BACK_TO_TREATMENT: accepted = handleEndTreatmentUserAction( &rejReason ); break; default: rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; break; } } else { rejReason = REQUEST_REJECT_REASON_ALARM_IS_ACTIVE; } // Respond to user action request sendRinsebackCmdResponse( accepted, (U32)rejReason ); } /*********************************************************************//** * @brief * The handleStartRinsebackUserAction function handles a start rinseback * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleStartRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( RINSEBACK_STOP_INIT_STATE == rinsebackState ) { result = TRUE; startRinsebackRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleIncrRinsebackUserAction function handles an increase rinseback * flow rate user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleIncrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; F32 rbRate = (F32)getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); if ( ( rbRate + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) <= MAX_RINSEBACK_FLOW_RATE_ML_MIN ) { if ( RINSEBACK_RUN_STATE == rinsebackState ) { result = TRUE; incrRinsebackFlowRateRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } } else { *rejReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; } return result; } /*********************************************************************//** * @brief * The handleDecrRinsebackUserAction function handles a decrease rinseback * flow rte user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleDecrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; F32 rbRate = (F32)getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); if ( ( rbRate + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) >= MIN_RINSEBACK_FLOW_RATE_ML_MIN ) { if ( RINSEBACK_RUN_STATE == rinsebackState ) { result = TRUE; decrRinsebackFlowRateRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } } else { *rejReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; } return result; } /*********************************************************************//** * @brief * The handlePauseRinsebackUserAction function handles a pause rinseback * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handlePauseRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( RINSEBACK_RUN_STATE == rinsebackState ) { result = TRUE; pauseRinsebackRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleResumeRinsebackUserAction function handles a resume rinseback * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleResumeRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( RINSEBACK_PAUSED_STATE == rinsebackState ) { result = TRUE; resumeRinsebackRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleEndRinsebackUserAction function handles an end rinseback * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleEndRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( ( RINSEBACK_RUN_STATE == rinsebackState ) || ( RINSEBACK_PAUSED_STATE == rinsebackState ) ) { result = TRUE; endRinsebackRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleAdditionalRinsebackUserAction function handles an additional rinseback * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleAdditionalRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( RINSEBACK_STOP_STATE == rinsebackState ) { result = TRUE; additionalRinsebackRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleToRecircUserAction function handles a go to re-circulate * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleToRecircUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( RINSEBACK_STOP_STATE == rinsebackState ) { result = TRUE; recircRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleBackToTreatmentUserAction function handles a back to treatment * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleBackToTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( ( RINSEBACK_STOP_INIT_STATE == rinsebackState ) || ( RINSEBACK_STOP_STATE == rinsebackState ) ) { result = TRUE; backToTreatmentRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The handleEndTreatmentUserAction function handles an end treatment * user action request. It is assumed that the calling function will set * the reject reason parameter to None beforehand. * @details Inputs: none * @details Outputs: none * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ static BOOL handleEndTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; if ( ( RINSEBACK_STOP_INIT_STATE == rinsebackState ) || ( RINSEBACK_STOP_STATE == rinsebackState ) ) { result = TRUE; endTreatmentRequested = TRUE; } else { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } return result; } /*********************************************************************//** * @brief * The getCurrentRinsebackState function returns the current state of the * rinseback sub-mode. * @details Inputs: rinsebackState * @details Outputs: none * @return rinsebackState *************************************************************************/ RINSEBACK_STATE_T getCurrentRinsebackState( void ) { return rinsebackState; } /**@}*/