Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -reb877ae36c28eb83553ee11ccccf42e2c4a5b4d2 -r43ab88c9ad8435e0a0a3df0adde1de150c582305 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision eb877ae36c28eb83553ee11ccccf42e2c4a5b4d2) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 43ab88c9ad8435e0a0a3df0adde1de150c582305) @@ -1,73 +1,962 @@ /************************************************************************** - * - * Copyright (c) 2019-2019 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 - * - * @date 19-Sep-2019 - * @author S. Nash - * - * @brief Top-level state machine for the standby mode. - * - **************************************************************************/ +* +* 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 -#include -#include "Common.h" -#include "OperationModes.h" +#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 ********** -/************************************************************************* - * @brief initStandbyMode +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 - * Outputs : Standby Mode module initialized. - * @param none + * @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 transitionToStandbyMode +/*********************************************************************//** + * @brief * The transitionToStandbyMode function prepares for transition to standby mode. - * @details - * Inputs : none - * Outputs : - * @param none - * @return none + * @details Inputs: none + * @details Outputs: Standby Mode module re-initialized, DG interface initialized, + * blood & dialysate pumps shut off. + * @return initial state *************************************************************************/ -void transitionToStandbyMode( void ) +U32 transitionToStandbyMode( void ) { - // temporary test code - alarm lamp OK - requestAlarmLampPattern( LAMP_PATTERN_OK ); + // 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 execStandbyMode +/*********************************************************************//** + * @brief * The execStandbyMode function executes the Standby Mode state machine. - * @details - * Inputs : none - * Outputs : - * @param none - * @return none + * @details Inputs: currentStandbyState + * @details Outputs: currentStandbyState + * @return current state (sub-mode) *************************************************************************/ -void execStandbyMode( void ) +U32 execStandbyMode( void ) { +#ifdef EMC_TEST_BUILD + static U32 toggle = 0; + static BOOL button_state = FALSE; +#endif BOOL stop = isStopButtonPressed(); - if ( TRUE == stop ) +#ifndef RUN_WITHOUT_DG + // State machine to get DG to prep a reservoir so we can start a treatment + switch ( currentStandbyState ) { - requestNewOperationMode( MODE_PRES ); + 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 ( 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; +} + +/**@}*/