/************************************************************************** * * Copyright (c) 2019-2022 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) Dara Navaei * @date (last) 15-Jul-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "AirTrap.h" #include "AlarmLamp.h" #include "Battery.h" #include "BloodFlow.h" #include "Buttons.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" #include "ModePostTreat.h" #include "ModePreTreat.h" #include "ModeStandby.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "Switches.h" #include "SyringePump.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" #ifdef EMC_TEST_BUILD // TODO - test code #include "FPGA.h" #endif /** * @addtogroup HDStandbyMode * @{ */ // ********** private definitions ********** #define DISINFECTS_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Disinfects data publish interval in counts. #define SERVICE_TIME_INTERVAL_MS ( 6 * 30 * SECONDS_IN_A_DAY * MS_PER_SECOND ) ///< HD/DG 6-month service interval in milliseconds. // ********** private data ********** static HD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. static BOOL treatStartReqReceived; ///< Flag indicates user has requested initiation of a treatment. static BOOL flushStartReqReceived; ///< Flag indicates user has requested initiation of flush mode. static BOOL heatDisinfectStartReqReceived; ///< Flag indicates user has requested initiation of heat disinfect mode. static BOOL chemDisinfectStartReqReceived; ///< Flag indicates user has requested initiation of chemical disinfect mode. static DG_DISINFECT_STATE_T dgDisinfectState; ///< DG disinfect state to be boadcast to UI. static U32 dataPublishCounter = 0; ///< Disinfects data publish counter. /// Interval (in task intervals) at which to publish standby mode data to CAN bus. static OVERRIDE_U32_T standbyModePublishInterval = { DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, 0 }; // ********** private function prototypes ********** static HD_STANDBY_STATE_T handleStandbyModeStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGFlushCmdResponseState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGFlushToStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeDGFlushInProgressState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGHeatDisinfectCmdResponseState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGHeatDisinfectStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeDGHeatDisinfectInProgressState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectCmdResponseState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ); static void publishDisinfectData( void ); /*********************************************************************//** * @brief * The initStandbyMode function initializes the Standby Mode module. * @details Inputs: none * @details Outputs: currentStandbyState, treatStartReqReceived, * flushStartReqReceived, dataPublishCounter, heatDisinfectStartReqReceived, * chemDisinfectStartReqReceived, dgDisinfectState * @return none *************************************************************************/ void initStandbyMode( void ) { currentStandbyState = STANDBY_START_STATE; treatStartReqReceived = FALSE; flushStartReqReceived = FALSE; dataPublishCounter = 0; heatDisinfectStartReqReceived = FALSE; chemDisinfectStartReqReceived = FALSE; dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; } /*********************************************************************//** * @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 initial state *************************************************************************/ U32 transitionToStandbyMode( void ) { // Re-initialize when transitioning to standby mode initStandbyMode(); initDGInterface(); resetAirTrap(); doorClosedRequired( FALSE, FALSE ); syringeDetectionRequired( FALSE ); // 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(); signalDialInPumpHardStop(); signalDialOutPumpHardStop(); stopSyringePump(); // Set valves to default positions setValveAirTrap( STATE_CLOSED ); setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); return currentStandbyState; } /*********************************************************************//** * @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(); #ifndef RUN_WITHOUT_DG // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: currentStandbyState = handleStandbyModeStartState();; break; case STANDBY_WAIT_FOR_TREATMENT_STATE: currentStandbyState = handleStandbyModeWaitForTreatmentState(); break; case STANDBY_WAIT_FOR_DISINFECT_STATE: currentStandbyState = handleStandbyModeWaitForDisinfectState(); break; case STANDBY_WAIT_FOR_DG_FLUSH_CMD_RESPONSE_STATE: currentStandbyState = handleStandbyModeWaitForDGFlushCmdResponseState(); break; case STANDBY_WAIT_FOR_DG_FLUSH_TO_START_STATE: currentStandbyState = handleStandbyModeWaitForDGFlushToStartState(); break; case STANDBY_DG_FLUSH_IN_PROGRESS_STATE: currentStandbyState = handleStandbyModeDGFlushInProgressState(); break; case STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_CMD_RESPONSE_STATE: currentStandbyState = handleStandbyModeWaitForDGHeatDisinfectCmdResponseState(); break; case STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_TO_START_STATE: currentStandbyState = handleStandbyModeWaitForDGHeatDisinfectStartState(); break; case STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE: currentStandbyState = handleStandbyModeDGHeatDisinfectInProgressState(); break; case STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_CMD_RESPONSE_STATE: currentStandbyState = handleStandbyModeWaitForDGChemDisinfectCmdResponseState(); break; case STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_TO_START_STATE: currentStandbyState = handleStandbyModeWaitForDGChemDisinfectStartState(); break; case STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE: currentStandbyState = handleStandbyModeDGChemDisininfectInProgressState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); 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 setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); startAirTrapControl(); #endif break; case STANDBY_WAIT_FOR_TREATMENT_STATE: if ( TRUE == treatStartReqReceived ) { requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } // TODO - test code if ( TRUE == stop ) { #ifndef EMC_TEST_BUILD 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 ); #else if ( stop != button_state ) { toggle = INC_WRAP( toggle, 0, 3 ); switch ( toggle ) { case 0: // Pumps and valves off 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; case 1: // Pumps off, valves in pos A setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); break; case 2: // Pumps on, valves in pos A setBloodPumpTargetFlowRate( 500, 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; 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: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); currentStandbyState = STANDBY_START_STATE; break; } #endif return currentStandbyState; } /*********************************************************************//** * @brief * The signalUserInitiateTreatment function handles user initiation of a * treatment. * @details Inputs: none * @details Outputs: treatStartReqReceived * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateTreatment( void ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; if ( ( MODE_STAN != getCurrentOperationMode() ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } if ( TRUE != isDGCommunicating() ) { rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; } if ( ( DG_MODE_STAN != getDGOpMode() ) || ( DG_STANDBY_MODE_STATE_IDLE != getDGSubMode() ) ) { rejReason = REQUEST_REJECT_REASON_DG_NOT_IN_STANDBY_IDLE_STATE; } #ifndef DISABLE_BATT_COMM if ( FALSE == isBatteryCharged() ) { rejReason = REQUEST_REJECT_REASON_BATTERY_IS_NOT_CHARGED; } #endif if ( REQUEST_REJECT_REASON_NONE == rejReason ) { result = TRUE; treatStartReqReceived = TRUE; } sendInitiateTreatmentResponseMsg( result, rejReason ); 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 ) { // Alarm actions not handled in Standby mode } /*********************************************************************//** * @brief * The signalUserInitiateFlushMode function handles user initiation of flush * mode. * @details Inputs: currentStandbyState * @details Outputs: flushStartReqReceived * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateFlushMode( void ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; if ( MODE_STAN == getCurrentOperationMode() ) { if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) { if ( TRUE == isDGCommunicating() ) { flushStartReqReceived = TRUE; result = TRUE; currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; rejReason = REQUEST_REJECT_REASON_NONE; } else { rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; } } } sendDisinfectConfirmResponse( result, rejReason ); return result; } /*********************************************************************//** * @brief * The signalUserInitiateFlushMode function handles user initiation of heat * disinfect mode. * @details Inputs: currentStandbyState * @details Outputs: heatDisinfectStartReqReceived * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateHeatDisinfectMode( void ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; if ( MODE_STAN == getCurrentOperationMode() ) { if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) { if ( TRUE == isDGCommunicating() ) { heatDisinfectStartReqReceived = TRUE; result = TRUE; currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; rejReason = REQUEST_REJECT_REASON_NONE; } else { rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; } } } sendDisinfectConfirmResponse( result, rejReason ); return result; } /*********************************************************************//** * @brief * The signalUserInitiateChemicalDisinfectMode function handles user * initiation of chemical disinfect mode. * @details Inputs: currentStandbyState * @details Outputs: chemDisinfectStartReqReceived * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateChemicalDisinfectMode( void ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; if ( MODE_STAN == getCurrentOperationMode() ) { if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) { if ( TRUE == isDGCommunicating() ) { chemDisinfectStartReqReceived = TRUE; result = TRUE; currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; rejReason = REQUEST_REJECT_REASON_NONE; } else { rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; } } } sendDisinfectConfirmResponse( result, rejReason ); return result; } /*********************************************************************//** * @brief * The signalInitiateStandbyDisinfectSubmode function handles user * initiation of setting the disinfects submode. * @details Inputs: currentStandbyState * @details Outputs: currentStandbyState * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalInitiateStandbyDisinfectSubmode( void ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; if ( ( MODE_STAN == getCurrentOperationMode() ) && ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) { if ( TRUE == isDGCommunicating() ) { currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; result = TRUE; rejReason = REQUEST_REJECT_REASON_NONE; } else { rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; } } sendDisinfectConfirmResponse( result, rejReason ); return result; } // ********** private functions ********** /*********************************************************************//** * @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 Inputs: * @details Outputs: * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeStartState( void ) { static BOOL homingInitiated = FALSE; HD_STANDBY_STATE_T state = STANDBY_START_STATE; // Wait for door to be closed so we can home actuators if ( ( homingInitiated != TRUE ) && ( STATE_CLOSED == getSwitchStatus( FRONT_DOOR ) ) ) { VALVE_T valve; // Home pumps and valves for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) { homeValve( valve ); } homeBloodPump(); homeDialInPump(); homeDialOutPump(); retractSyringePump(); homingInitiated = TRUE; } else { // Trigger door open alarm to prompt user to close the door activateAlarmNoData( ALARM_ID_CARTRIDGE_DOOR_OPENED ); homingInitiated = FALSE; } // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration if ( ( TRUE == homingInitiated ) && ( TRUE == isSyringePumpHome() ) ) { syringePumpVerifyForceSensorDACCalibration(); homingInitiated = FALSE; // reset for next time state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check } return state; } // Verify calibration /*********************************************************************//** * @brief * The handleStandbyModeWaitForTreatmentState function handles wait for * treatment state. * @details Inputs: treatStartReqReceived * @details Outputs: treatStartReqReceived * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) { HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; DG_OP_MODE_T dgOperationMode = getDGOpMode(); // If DG is filling while we are in standby mode, abort the fill if ( DG_MODE_FILL == dgOperationMode ) { cmdStopDGFill(); } // If DG is in idle generation state while we are in standby mode, transition DG to standby too if ( DG_MODE_GENE == dgOperationMode ) { cmdStopDG(); } // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). TODO - check required conditions before allowing treatment start, reject if necessary. if ( TRUE == treatStartReqReceived ) { // Initialize treatment modes before starting a new treatment initTreatParamsMode(); initPreTreatmentMode(); initTreatmentMode(); initPostTreatmentMode(); // Start treatment workflow with treatment parameters mode requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDisinfectState function handles wait for * disinfect state. * @details Inputs: flushStartReqReceived, heatDisinfectStartReqReceived, * chemDisinfectStartReqReceived * @details Outputs: none * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ) { HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DISINFECT_STATE; if ( TRUE == flushStartReqReceived ) { cmdStartDGFlush(); state = STANDBY_WAIT_FOR_DG_FLUSH_CMD_RESPONSE_STATE; } else if ( TRUE == heatDisinfectStartReqReceived ) { cmdStartDGHeatDisinfect(); state = STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_CMD_RESPONSE_STATE; } else if ( TRUE == chemDisinfectStartReqReceived ) { cmdStartDGChemicalDisinfect(); state = STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_CMD_RESPONSE_STATE; } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGFlushCmdResponseState function handles DG flush * command response state. * @details Inputs: none * @details Outputs: flushStartReqReceived, dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGFlushCmdResponseState( void ) { DG_CMD_RESPONSE_T dgCmdResp; HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_FLUSH_CMD_RESPONSE_STATE; BOOL result = FALSE; // Check if DG has responded to the start DG flush command if ( TRUE == getDGCommandResponse( DG_CMD_START_FLUSH, &dgCmdResp ) ) { // Assume the command will be rejected and it goes back to wait for disinfect command state = STANDBY_WAIT_FOR_DISINFECT_STATE; flushStartReqReceived = FALSE; if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) { // If the command has not been rejected, transition to the next state dgDisinfectState = DG_DISINFECT_FLUSH_STATE; state = STANDBY_WAIT_FOR_DG_FLUSH_TO_START_STATE; result = TRUE; } sendDisinfectConfirmResponse( result, dgCmdResp.rejectCode ); } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGFlushToStartState function handles DG flush * wait to start state. * @details Inputs: none * @details Outputs: dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGFlushToStartState( void ) { HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_FLUSH_TO_START_STATE; if ( DG_MODE_FLUS == getDGOpMode() ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_DG_FLUSH_IN_PROGRESS_STATE; } return state; } /*********************************************************************//** * @brief * The handleStandbyModeDGFlushInProgressState function handles DG flush * in progress state. * @details Inputs: none * @details Outputs: dgDisinfectState, currentStandbyState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeDGFlushInProgressState( void ) { HD_STANDBY_STATE_T state = STANDBY_DG_FLUSH_IN_PROGRESS_STATE; if ( getDGOpMode() != DG_MODE_FLUS ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_WAIT_FOR_TREATMENT_STATE; } publishDisinfectData(); return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGHeatDisinfectCmdResponseState function handles * DG heat disinfect command response state. * @details Inputs: none * @details Outputs: heatDisinfectStartReqReceived, dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGHeatDisinfectCmdResponseState( void ) { DG_CMD_RESPONSE_T dgCmdResp; HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_CMD_RESPONSE_STATE; BOOL result = FALSE; if ( TRUE == getDGCommandResponse( DG_CMD_START_HEAT_DISINFECT, &dgCmdResp ) ) { state = STANDBY_WAIT_FOR_DISINFECT_STATE; heatDisinfectStartReqReceived = FALSE; if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) { dgDisinfectState = DG_DISINFECT_HEAT_STATE; state = STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_TO_START_STATE; result = TRUE; } sendDisinfectConfirmResponse( result, dgCmdResp.rejectCode ); } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGHeatDisinfectStartState function handles * DG heat disinfect wait for start state. * @details Inputs: none * @details Outputs: dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGHeatDisinfectStartState( void ) { HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_HEAT_DISINFECT_TO_START_STATE; if ( DG_MODE_HEAT == getDGOpMode() ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE; } return state; } /*********************************************************************//** * @brief * The handleStandbyModeDGHeatDisinfectInProgressState function handles DG * heat disinfect in progress state. * @details Inputs: none * @details Outputs: dgDisinfectState, currentStandbyState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeDGHeatDisinfectInProgressState( void ) { HD_STANDBY_STATE_T state = STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE; if ( getDGOpMode() != DG_MODE_HEAT ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_WAIT_FOR_TREATMENT_STATE; } publishDisinfectData(); return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGChemDisinfectCmdResponseState function handles * DG chemical disinfect wait for command response state. * @details Inputs: none * @details Outputs: chemDisinfectStartReqReceived, dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectCmdResponseState( void ) { DG_CMD_RESPONSE_T dgCmdResp; HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_CMD_RESPONSE_STATE; BOOL result = FALSE; if ( TRUE == getDGCommandResponse( DG_CMD_START_CHEM_DISINFECT, &dgCmdResp ) ) { state = STANDBY_WAIT_FOR_DISINFECT_STATE; chemDisinfectStartReqReceived = FALSE; if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) { dgDisinfectState = DG_DISINFECT_CHEM_STATE; state = STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_TO_START_STATE; result = TRUE; } sendDisinfectConfirmResponse( result, dgCmdResp.rejectCode ); } return state; } /*********************************************************************//** * @brief * The handleStandbyModeWaitForDGChemDisinfectStartState function handles * DG chemical disinfect wait for start state. * @details Inputs: none * @details Outputs: dgDisinfectState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectStartState( void ) { HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DG_CHEM_DISINFECT_TO_START_STATE; if ( DG_MODE_CHEM == getDGOpMode() ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE; } return state; } /*********************************************************************//** * @brief * The handleStandbyModeDGChemDisininfectInProgressState function handles * DG chemical disinfect in progress state. * @details Inputs: none * @details Outputs: dgDisinfectState, currentStandbyState * @return next state of the standby mode state machine *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ) { HD_STANDBY_STATE_T state = STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE; if ( getDGOpMode() != DG_MODE_CHEM ) { dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; state = STANDBY_WAIT_FOR_TREATMENT_STATE; } publishDisinfectData(); return state; } /*********************************************************************//** * @brief * The publishDisinfectData function publishes disinfects data at * the set interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ static void publishDisinfectData( void ) { if ( ++dataPublishCounter > DISINFECTS_DATA_PUB_INTERVAL ) { DG_DISINFECT_UI_STATES_T state = getDGDisinfectsStates(); DISINFECTS_DATA_T data; switch( currentStandbyState ) { case STANDBY_DG_FLUSH_IN_PROGRESS_STATE: data.disinfectDGFlushState = state.flushUIState; break; case STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE: data.disinfectDGHeatState = state.heatDisinfectUIState; break; case STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE: data.disinfectDGChemState = state.chemDisinfectUIState; break; } data.disinfectSubModeHDState = (U32)dgDisinfectState; broadcastData( MSG_ID_HD_DISINFECT_STANDBY_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( DISINFECTS_DATA_T ) ); dataPublishCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetStandbyModePublishIntervalOverride function sets the override of the * standby mode data publication interval. * @details Inputs: none * @details Outputs: standbyModePublishInterval * @param ms milliseconds between standby mode broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetStandbyModePublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; standbyModePublishInterval.ovData = intvl; standbyModePublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetStandbyModePublishIntervalOverride function resets the override of the * standby mode data publication interval. * @details Inputs: none * @details Outputs: standbyModePublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetStandbyModePublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; standbyModePublishInterval.override = OVERRIDE_RESET; standbyModePublishInterval.ovData = standbyModePublishInterval.ovInitData; } return result; } /**@}*/