/************************************************************************** * * 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) Quang Nguyen * @date (last) 24-Aug-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "ConcentratePumps.h" #include "CPLD.h" #include "DrainPump.h" #include "Heaters.h" #include "ModeStandby.h" #include "OperationModes.h" #include "Reservoirs.h" #include "ROPump.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup DGStandbyMode * @{ */ // ********** private definitions ********** #define FILTER_FLUSH_TIME_MS ( 120 * MS_PER_SECOND ) ///< Duration of filter flush state (in ms). #define WATER_SAMPLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Duration of water sample state (in ms). #define FLUSH_EXPIRATION_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Duration in which a filter flush is valid (in ms). // ********** private data ********** static DG_STANDBY_MODE_STATE_T standbyState = DG_STANDBY_MODE_STATE_START; ///< Currently active standby state. static BOOL stopSampleWaterRequest = FALSE; ///< Flag indicating HD has requested to stop sample water static BOOL startSampleWaterRequest = FALSE; ///< Flag indicating HD has requested to start sample water static BOOL flushFilterRequest = FALSE; ///< Flag indicating HD has requested to flush filters static BOOL endSampleWaterRequest = FALSE; ///< Flag indicating HD has requested to end sample water static BOOL pendingStartDGRequest = FALSE; ///< Flag indicating HD has requested DG start (go to re-circulate mode). static U32 waterSampleStartTime = 0; ///< Time stamp for start of water sample state. static U32 filterFlushStartTime = 0; ///< Time stamp for start of filter flush state. // ********** private function prototypes ********** static DG_STANDBY_MODE_STATE_T handleStandbyIdleState( void ); static DG_STANDBY_MODE_STATE_T handleStandbyFlushFilterState( void ); static DG_STANDBY_MODE_STATE_T handleStandbyFlushFilterIdleState( void ); static DG_STANDBY_MODE_STATE_T handleStandbySampleWaterState( void ); /*********************************************************************//** * @brief * The initStandbyMode function initializes the standby mode module. * @details Inputs: none * @details Outputs: Standby mode module initialized * @return none *************************************************************************/ void initStandbyMode( void ) { standbyState = DG_STANDBY_MODE_STATE_START; stopSampleWaterRequest = FALSE; startSampleWaterRequest = FALSE; flushFilterRequest = FALSE; endSampleWaterRequest = FALSE; waterSampleStartTime = 0; filterFlushStartTime = 0; pendingStartDGRequest = FALSE; } /*********************************************************************//** * @brief * The transitionToStandbyMode function prepares for transition to standby mode. * @details Inputs: none * @details Outputs: Re-initialized standby mode * @return none *************************************************************************/ void transitionToStandbyMode( void ) { // re-initialize standby mode each time we transition to standby mode initStandbyMode(); // set initial actuator states setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); signalROPumpHardStop(); signalDrainPumpHardStop(); stopPrimaryHeater(); stopTrimmerHeater(); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); // UV off resetReservoirLoadCellsOffset( DG_RESERVOIR_1 ); resetReservoirLoadCellsOffset( DG_RESERVOIR_2 ); } /*********************************************************************//** * @brief * The execStandbyMode function executes the standby mode state machine. * @details Inputs: none * @details Outputs: Standby mode state machine executed * @return current state *************************************************************************/ U32 execStandbyMode( void ) { // execute current Standby state switch ( standbyState ) { case DG_STANDBY_MODE_STATE_START: standbyState = DG_STANDBY_MODE_STATE_IDLE; break; case DG_STANDBY_MODE_STATE_IDLE: standbyState = handleStandbyIdleState(); break; case DG_STANDBY_MODE_STATE_FLUSH_FILTER: standbyState = handleStandbyFlushFilterState(); break; case DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE: standbyState = handleStandbyFlushFilterIdleState(); break; case DG_STANDBY_MODE_STATE_SAMPLE_WATER: standbyState = handleStandbySampleWaterState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, 0, standbyState ) // TODO - add s/w fault enum to 1st data param standbyState = DG_STANDBY_MODE_STATE_START; break; } return standbyState; } /*********************************************************************//** * @brief * The handleStandbyIdleState function executes the idle state of the * standby mode state machine. * @details Inputs: pendingSampleWaterRequest, pendingStartDGRequest * @details Outputs: Idle state of the standby mode executed * @return the next state *************************************************************************/ static DG_STANDBY_MODE_STATE_T handleStandbyIdleState( void ) { DG_STANDBY_MODE_STATE_T state = DG_STANDBY_MODE_STATE_IDLE; // go to standby solo mode if HD is turned off or stops communicating. if ( FALSE == isHDCommunicating() ) { // TODO if HD comm loss, should we wait an hour or so before going to solo standby? requestNewOperationMode( DG_MODE_SOLO ); } // if HD requests water sample, go to water sample state else if ( TRUE == flushFilterRequest ) { flushFilterRequest = FALSE; filterFlushStartTime = getMSTimerCount(); setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_OPEN ); state = DG_STANDBY_MODE_STATE_FLUSH_FILTER; } else if ( TRUE == pendingStartDGRequest ) { pendingStartDGRequest = FALSE; requestNewOperationMode( DG_MODE_CIRC ); } return state; } /*********************************************************************//** * @brief * The handleStandbyFilterFlushState function executes the flush filter state * of the standby mode state machine. * @details Inputs: filterFLushStartTime * @details Outputs: Flushed the filters * @return the next state *************************************************************************/ static DG_STANDBY_MODE_STATE_T handleStandbyFlushFilterState( void ) { DG_STANDBY_MODE_STATE_T state = DG_STANDBY_MODE_STATE_FLUSH_FILTER; if ( TRUE == didTimeout( filterFlushStartTime, FILTER_FLUSH_TIME_MS ) ) { state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; } return state; } /*********************************************************************//** * @brief * The handleStandbyFlushFilterIdleState function executes the flush filter state * of the standby mode state machine. * @details Inputs: filterFLushStartTime * @details Outputs: Flushed the filters * @return the next state *************************************************************************/ static DG_STANDBY_MODE_STATE_T handleStandbyFlushFilterIdleState( void ) { DG_STANDBY_MODE_STATE_T state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; if ( TRUE == startSampleWaterRequest ) { startSampleWaterRequest = FALSE; waterSampleStartTime = getMSTimerCount(); setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VSP, VALVE_STATE_OPEN ); state = DG_STANDBY_MODE_STATE_SAMPLE_WATER; } if ( TRUE == endSampleWaterRequest ) { setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_CLOSED ); state = DG_STANDBY_MODE_STATE_IDLE; } return state; } /*********************************************************************//** * @brief * The handleStandbySampleWaterState function executes the sample water state * of the standby mode state machine. * @details Inputs: stopSampleWaterRequest, waterSampleStartTime * @details Outputs: Finished sample water and closed valve * @return the next state *************************************************************************/ static DG_STANDBY_MODE_STATE_T handleStandbySampleWaterState( void ) { DG_STANDBY_MODE_STATE_T state = DG_STANDBY_MODE_STATE_SAMPLE_WATER; // After HD requests to stop or 10 seconds has elapsed, close and return to idle state if ( ( TRUE == stopSampleWaterRequest ) || ( TRUE == didTimeout( waterSampleStartTime, WATER_SAMPLE_TIME_MS ) ) ) { setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN ); state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; } return state; } /*********************************************************************//** * @brief * The requestWaterSample function handles an HD request to sample water. * @details Inputs: standbyState * @details Outputs: pendingSampleWaterRequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ void waterSampleCommandHandler( SAMPLE_WATER_CMD_T sampleWaterCmd ) { DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_SAMPLE_WATER; cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; switch ( sampleWaterCmd ) { case SAMPLE_WATER_CMD_STOP: if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_SAMPLE_WATER == standbyState ) ) { stopSampleWaterRequest = TRUE; cmdResponse.rejected = FALSE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } break; case SAMPLE_WATER_CMD_START: if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE == standbyState ) ) { startSampleWaterRequest = TRUE; cmdResponse.rejected = FALSE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } break; case SAMPLE_WATER_CMD_FLUSH: if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) ) { flushFilterRequest = TRUE; cmdResponse.rejected = FALSE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } break; case SAMPLE_WATER_CMD_END: if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE == standbyState ) ) { endSampleWaterRequest = TRUE; cmdResponse.rejected = FALSE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } break; default: cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; break; } sendCommandResponseMsg( &cmdResponse ); } /*********************************************************************//** * @brief * The requestDGStart function handles an HD request to start (go to re-circulate mode). * @details Inputs: standbyState * @details Outputs: pendingSampleWaterRequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ BOOL requestDGStart( void ) { BOOL result = FALSE; if ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) { result = TRUE; pendingStartDGRequest = TRUE; } return result; } /*********************************************************************//** * @brief * The getCurrentStandbyState function returns the current state of standby mode. * @details Inputs: standbyState * @details Outputs: none * @return the current state of standby mode. *************************************************************************/ DG_STANDBY_MODE_STATE_T getCurrentStandbyState( void ) { return standbyState; } /**@}*/