Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r370877da1639ae01135cf4c5f1e009e1517bbf03 -r3eb7c2e62c727be195cd937d49957db9d4ba83b4 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 370877da1639ae01135cf4c5f1e009e1517bbf03) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 3eb7c2e62c727be195cd937d49957db9d4ba83b4) @@ -19,13 +19,15 @@ #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 "TaskGeneral.h" #include "Timers.h" #include "Valves.h" -#include "ModeStandby.h" /** * @addtogroup DGStandbyMode @@ -34,18 +36,29 @@ // ********** private definitions ********** -#define WATER_SAMPLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Duration of water sample state (in ms). +#define FILTER_FLUSH_TIME_MS ( 120 * MS_PER_SECOND ) ///< Duration of filter flush state (in ms). +#define MAX_WATER_SAMPLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Maximum 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). +#define FILTER_FLUSH_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Filter flush data broadcast interval. // ********** private data ********** static DG_STANDBY_MODE_STATE_T standbyState = DG_STANDBY_MODE_STATE_START; ///< Currently active standby state. -static BOOL pendingSampleWaterRequest = FALSE; ///< Flag indicating HD has requested a water sample. +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. +static U32 filterFlushPublishTimerCounter = 0; ///< Filter flush data publish timer counter. // ********** 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 ); /*********************************************************************//** @@ -58,9 +71,15 @@ void initStandbyMode( void ) { standbyState = DG_STANDBY_MODE_STATE_START; - pendingSampleWaterRequest = FALSE; - pendingStartDGRequest = FALSE; + stopSampleWaterRequest = FALSE; + startSampleWaterRequest = FALSE; + flushFilterRequest = FALSE; + endSampleWaterRequest = FALSE; + waterSampleStartTime = 0; + filterFlushStartTime = 0; + filterFlushPublishTimerCounter = 0; + pendingStartDGRequest = FALSE; } /*********************************************************************//** @@ -76,21 +95,26 @@ initStandbyMode(); // set initial actuator states - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + signalROPumpHardStop(); signalDrainPumpHardStop(); stopPrimaryHeater(); stopTrimmerHeater(); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); - // UV off + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); - resetReservoirLoadCellsOffset( DG_RESERVOIR_1 ); - resetReservoirLoadCellsOffset( DG_RESERVOIR_2 ); + // UV off + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); } /*********************************************************************//** @@ -113,12 +137,20 @@ 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 + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_STANDBY_MODE_INVALID_EXEC_STATE, standbyState ) standbyState = DG_STANDBY_MODE_STATE_START; break; } @@ -136,52 +168,112 @@ *************************************************************************/ static DG_STANDBY_MODE_STATE_T handleStandbyIdleState( void ) { - DG_STANDBY_MODE_STATE_T result = DG_STANDBY_MODE_STATE_IDLE; + 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 == pendingSampleWaterRequest ) + else if ( TRUE == flushFilterRequest ) { - pendingSampleWaterRequest = FALSE; - waterSampleStartTime = getMSTimerCount(); + flushFilterRequest = FALSE; + filterFlushStartTime = getMSTimerCount(); setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VSP, VALVE_STATE_OPEN ); - result = DG_STANDBY_MODE_STATE_SAMPLE_WATER; + setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 + state = DG_STANDBY_MODE_STATE_FLUSH_FILTER; } else if ( TRUE == pendingStartDGRequest ) { pendingStartDGRequest = FALSE; requestNewOperationMode( DG_MODE_CIRC ); } - return result; + 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; + } + + if ( FILTER_FLUSH_DATA_PUBLISH_INTERVAL <= filterFlushPublishTimerCounter++ ) + { + U32 const timeout = FILTER_FLUSH_TIME_MS / MS_PER_SECOND; + U32 const countdown = timeout - ( calcTimeSince( filterFlushStartTime ) / MS_PER_SECOND ); + filterFlushPublishTimerCounter = 0; + + broadcastFilterFlushData( timeout, countdown ); + } + + 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: none - * @details Outputs: Sample water state of the standby mode executed + * @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 result = DG_STANDBY_MODE_STATE_SAMPLE_WATER; + DG_STANDBY_MODE_STATE_T state = DG_STANDBY_MODE_STATE_SAMPLE_WATER; - // VPi and VSP valves open for 10 seconds, then close and return to idle state - if ( TRUE == didTimeout( waterSampleStartTime, WATER_SAMPLE_TIME_MS ) ) + // After HD requests to stop or 10 seconds has elapsed, close and return to idle state + if ( ( TRUE == stopSampleWaterRequest ) || ( TRUE == didTimeout( waterSampleStartTime, MAX_WATER_SAMPLE_TIME_MS ) ) ) { - setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); - result = DG_STANDBY_MODE_STATE_IDLE; + setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 + state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; } - return result; + return state; } /*********************************************************************//** @@ -191,17 +283,58 @@ * @details Outputs: pendingSampleWaterRequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ -BOOL requestWaterSample( void ) +void waterSampleCommandHandler( SAMPLE_WATER_CMD_T sampleWaterCmd ) { - BOOL result = FALSE; + DG_CMD_RESPONSE_T cmdResponse; - if ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) + cmdResponse.commandID = DG_CMD_SAMPLE_WATER; + cmdResponse.rejected = TRUE; + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; + + switch ( sampleWaterCmd ) { - result = TRUE; - pendingSampleWaterRequest = TRUE; + 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; } - return result; + sendCommandResponseMsg( &cmdResponse ); } /*********************************************************************//** @@ -249,6 +382,29 @@ /*********************************************************************//** * @brief + * The startDGHeatDisinfect function starts heat disinfect mode. + * @details Inputs: standbyState + * @details Outputs: none + * @return: TRUE if the switch was successful + *************************************************************************/ +BOOL startDGHeatDisinfect( void ) +{ + BOOL status = FALSE; + + // If DG is in standby mode and the standby mode is in Idle state or if DG is in solo mode, request DG heat disinfect + if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) || + ( DG_MODE_SOLO == getCurrentOperationMode() ) ) + { + requestNewOperationMode( DG_MODE_HEAT ); + + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief * The getCurrentStandbyState function returns the current state of standby mode. * @details Inputs: standbyState * @details Outputs: none