/************************************************************************** * * 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 ModeStandby.c * * @author (last) Sean Nash * @date (last) 08-Oct-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "AirTrap.h" #include "AlarmLamp.h" #include "BloodFlow.h" #include "Buttons.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" #include "OperationModes.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "ModeStandby.h" #ifdef EMC_TEST_BUILD // TODO - test code #include "FPGA.h" #endif /** * @addtogroup HDStandbyMode * @{ */ // ********** private definitions ********** // ********** private data ********** static HD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of a treatment // ********** private function prototypes ********** /*********************************************************************//** * @brief * The initStandbyMode function initializes the Standby Mode module. * @details Inputs: none * @details Outputs: Standby Mode module initialized. * @return none *************************************************************************/ void initStandbyMode( void ) { currentStandbyState = STANDBY_START_STATE; treatStartReqReceived = FALSE; } /*********************************************************************//** * @brief * The transitionToStandbyMode function prepares for transition to standby mode. * @details Inputs: none * @details Outputs: Standby Mode module re-initialized, DG interface initialized, * blood & dialysate pumps shut off. * @return none *************************************************************************/ void transitionToStandbyMode( void ) { // Re-initialize when transitioning to standby mode initStandbyMode(); initDGInterface(); resetAirTrap(); // 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 setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } /*********************************************************************//** * @brief * The execStandbyMode function executes the Standby Mode state machine. * @details Inputs: currentStandbyState * @details Outputs: currentStandbyState * @return current state (sub-mode) *************************************************************************/ U32 execStandbyMode( void ) { #ifdef EMC_TEST_BUILD static U32 toggle = 0; static BOOL button_state = FALSE; #endif BOOL stop = isStopButtonPressed(); DG_OP_MODE_T dgOpMode = getDGOpMode(); // TODO - the DG mode & sub-mode come as a pair at interval - they MUST be kept together. U32 dgSubMode = getDGSubMode(); #ifndef RUN_WITHOUT_DG if ( TRUE == stop ) { activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); } // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: // Temporary test code - TODO - remove later if ( TRUE == isDGCommunicating() ) { homeBloodPump(); homeDialInPump(); homeDialOutPump(); cmdSetDGDialysateTargetTemps( 39.0, 37.0 ); cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); cmdStartDG(); currentStandbyState = STANDBY_FLUSH_DG_LINES_STATE; } break; case STANDBY_FLUSH_DG_LINES_STATE: // Temporary test code - TODO - remove later cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); if ( DG_MODE_CIRC == dgOpMode ) { if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) { cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML ); } } else if ( DG_MODE_DRAI == dgOpMode ) { currentStandbyState = STANDBY_DRAIN_RESERVOIR_STATE; } else { cmdStartDG(); } break; case STANDBY_DRAIN_RESERVOIR_STATE: // Temporary test code - TODO - remove later if ( DG_MODE_CIRC == dgOpMode ) { currentStandbyState = STANDBY_WAIT_FOR_PRIME_STATE; } break; case STANDBY_WAIT_FOR_PRIME_STATE: // Temporary test code - TODO - remove later if ( DG_MODE_CIRC == dgOpMode ) { if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) { cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML ); } } else if ( DG_MODE_FILL == dgOpMode ) { currentStandbyState = STANDBY_FILL_RESERVOIR_STATE; } break; case STANDBY_FILL_RESERVOIR_STATE: // Temporary test code - TODO - remove later if ( DG_MODE_CIRC == dgOpMode ) { currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; } break; case STANDBY_WAIT_FOR_TREATMENT_STATE: // TODO - test code { if ( DG_MODE_CIRC == dgOpMode ) { if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) { if ( TRUE == treatStartReqReceived ) { setStartReservoirVolume(); cmdSetDGActiveReservoir( DG_RESERVOIR_1 ); requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } } } } break; default: // TODO - s/w fault currentStandbyState = STANDBY_START_STATE; break; } #else // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; // Temporary test code - TODO - remove later homeBloodPump(); homeDialInPump(); homeDialOutPump(); #ifdef EMC_TEST_BUILD startAirTrapControl(); #endif break; case STANDBY_WAIT_FOR_TREATMENT_STATE: if ( TRUE == treatStartReqReceived ) { requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } // TODO - test code if ( TRUE == stop ) { treatStartReqReceived = FALSE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); requestNewOperationMode( MODE_TPAR ); #ifdef EMC_TEST_BUILD if ( stop != button_state ) { toggle = INC_WRAP( toggle, 0, 3 ); switch ( toggle ) { case 0: // Pumps and valves off setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); break; case 1: // Pumps on, valves off setBloodPumpTargetFlowRate( 200, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); break; case 2: // Pumps on, valves on setValvePosition( VDI, VALVE_POSITION_B_OPEN ); setValvePosition( VDO, VALVE_POSITION_B_OPEN ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); break; case 3: // Pumps off, valves on setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); break; default: // Should not get here, reset if we do toggle = 0; setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); break; } } #endif } #ifdef EMC_TEST_BUILD button_state = stop; #endif break; default: // TODO - s/w fault currentStandbyState = STANDBY_START_STATE; break; } #endif return currentStandbyState; } /*********************************************************************//** * @brief * The signalUserStartingTreatment function handles user initiation of a * treatment. * @details Inputs: none * @details Outputs: requested mode transition to treatment parameters mode * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserStartingTreatment( void ) { BOOL result = FALSE; if ( ( MODE_STAN == getCurrentOperationMode() ) && ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) { treatStartReqReceived = TRUE; result = TRUE; } sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected return result; } /*********************************************************************//** * @brief * The signalAlarmActionToStandbyMode function executes the given alarm action * as appropriate while in Standby Mode. * @details Inputs: none * @details Outputs: given alarm action executed * @param action ID of alarm action to execute * @return none *************************************************************************/ void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ) { // TODO - implement } /**@}*/