#include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "CPLD.h" #include "DrainPump.h" #include "FlowSensors.h" #include "Heaters.h" #include "LoadCell.h" #include "MessageSupport.h" #include "ModeFault.h" #include "ModeHeatDisinfectActiveCool.h" #include "ModeROPermeateSample.h" #include "OperationModes.h" #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" #include "SystemCommMessages.h" #include "RTC.h" #include "Switches.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" #include "UVReactors.h" #include "Valves.h" /** * @addtogroup DGROPermeateSampleMode * @{ */ // ********** private data ********** #define RO_PERMEATE_SAMPLE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode RO permeate sample data publish interval in counts. #define ACID_PUMP_SPEED_ML_PER_MIN 30.6F ///< Acid concentrate pump speed in mL/min. // The acid pump is 2% faster than the acid pump to create a flow from acid to bicarb line during sampling #define BICARB_PUMP_SPEED_ML_PER_MIN -30.0F ///< Bicarb concentrate pump speed in mL/min. #define RO_PUMP_TARGET_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. #define RO_PUMP_MAX_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. #define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. #define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. #define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. #define RSRVR_FILL_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoir fill timeout in milliseconds. #define RSRVR_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoir drain timeout in milliseconds. #define RSRVR_DRAIN_STEADY_TIMEOUT_MS ( 6 * MS_PER_SECOND ) ///< Reservoir drain steady timeout in milliseconds. #define RSRVR_DRAIN_TARGET_RPM 2400 ///< Reservoir drain target RPM. #define RSRVR_MIX_DRAIN_TIMEOUT_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. #define RSRVR_FILL_TARGET_FILL_ML 1850.0F ///< Reservoir fill target in mL. #define RSRVR_DRAIN_BEFORE_SAMPLE_COLLECTION_MS ( 4.25F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoir drain before collection samples in milliseconds. #define RO_PUMP_TARGET_DISPENSE_FLOW_RATE_LPM 0.4F ///< RO pump target flow rate during dispensing in L/min. #define TARGET_DISPENSE_VOLUME_ML 70.0F ///< Target dispense volume in milliliters. /// Dispense message status enum typedef enum Dispense_Message_Status { DISPENSE_MSG_READY = 0, ///< Dispense message ready to receive message. DISPENSE_MSG_DISPENSING, ///< Dispense message dispensing. DISPENSE_MSG_CANCEL, ///< Dispense message cancel. DISPENSE_MSG_DISPENSE, ///< Dispense message dispense. NUM_OF_DISPENSE_MSG ///< Number of dispense messages. } DISPENSE_MSG_STATUS_T; static DG_RO_PERM_STATE_T roPermeateSampleState; ///< Mode RO permeate sample state. static DG_RO_PERM_STATE_T roPermeateSamplePrevState; ///< Mode RO permeate sample previous state. static U32 stateStartTimeMS; ///< Mode RO permeate sample state timer in milliseconds. static U32 dataPublishCounter; ///< Mode RO permeate sample data publish counter. static U32 overallROPermeateSampleTimer; ///< Mode RO permeate sample over mode timer. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Mode RO permeate sample pending alarm trigger. static DIS_RSRVR_STATUS_T rsrvrsStatus; ///< Mode RO permeate sample reservoirs status. static F32 roPermeateSampledispensedVolumeML; ///< Mode RO permeate sample dispensed volume in milliliters. static BOOL isReservoirFull; ///< Mode RO permeate sample flag to indicate reservoir 2 is filled. static DISPENSE_MSG_STATUS_T dispenseMessageStatus; ///< Mode RO permeate sample dispense message status. /// Conversion coefficient from flow in L/min to volume in milliliters. static const F32 FLOW_LPM_TO_VOL_ML_CONVERSION = (F32)( ML_PER_LITER * TASK_GENERAL_INTERVAL ) / (F32)( SEC_PER_MIN * MS_PER_SECOND ); // ********** private function prototypes ********** static DG_RO_PERM_STATE_T handleROPermeateSampleStartState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleDrainR1State( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleDrainR2State( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleFlushDrainState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleFlushDialysateState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleFlushConcenrateStrawsState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleFlushR2ToR1AndDrainR1State( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleCollectSampleState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleCancelBasicPathState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleCancelWaterPathState( void ); static DG_RO_PERM_STATE_T handleROPermeateSampleCompleteState( void ); static void failROPermeateSample( void ); static void publishROPermeateSampleData( void ); static void monitorROPermeateSample( void ); static void setROPermeateSampleStateTransition( DG_RO_PERM_STATE_T state ); static DG_RO_PERM_STATE_T checkRsrvrMgmtTimeoutStatus( DG_RESERVOIR_ID_T rsrvrID, DG_RO_PERM_STATE_T state ); static DG_RO_PERM_STATE_T checkRsrvrDrainStatus( DG_RESERVOIR_ID_T rsrvrID, DG_RO_PERM_STATE_T state ); /*********************************************************************//** * @brief * The initROPermeateSampleMode function initializes the RO permeate sample * mode module. * @details Inputs: none * @details Outputs: roPermeateSampleState, roPermeateSamplePrevState, * stateStartTimeMS, dataPublishCounter, overallROPermeateSampleTimer, * alarmDetectedPendingTrigger, rsrvrsStatus, roPermeateSampledispensedVolumeML, * isReservoirFull, dispenseMessageStatus * @return none *************************************************************************/ void initROPermeateSampleMode( void ) { roPermeateSampleState = DG_RO_PERM_SAMPLE_STATE_START; roPermeateSamplePrevState = DG_RO_PERM_SAMPLE_STATE_START; stateStartTimeMS = getMSTimerCount(); dataPublishCounter = 0; overallROPermeateSampleTimer = getMSTimerCount(); alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; roPermeateSampledispensedVolumeML = 0.0F; isReservoirFull = FALSE; dispenseMessageStatus = DISPENSE_MSG_READY; // Initialize the reservoirs rsrvrsStatus.rsrvrFillStableTime = 0; rsrvrsStatus.rsrvrFillStableTimeoutMS = RSRVRS_FULL_STABLE_TIME_COUNT; rsrvrsStatus.isThisInitialDrain = TRUE; rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].drainInit = FALSE; rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].loadCell = LOAD_CELL_RESERVOIR_1_PRIMARY; rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = DG_RESERVOIR_ABOVE_TARGET; rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].drainInit = FALSE; rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].loadCell = LOAD_CELL_RESERVOIR_2_PRIMARY; rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = DG_RESERVOIR_ABOVE_TARGET; } /*********************************************************************//** * @brief * The transitionToROPermeateSampleMode function prepares for transition to * RO permeate sample mode * @details Inputs: none * @details Outputs: none * @return initial state *************************************************************************/ U32 transitionToROPermeateSampleMode( void ) { deenergizeActuators( NO_PARK_CONC_PUMPS ); initROPermeateSampleMode(); setCurrentSubState( NO_SUB_STATE ); setCPLDCleanLEDColor( CPLD_CLEAN_LED_OFF ); return roPermeateSampleState; } /*********************************************************************//** * @brief * The execROPermeateSampleMode function executes the RO permeate sample mode * @details Inputs: roPermeateSampleState * @details Outputs: roPermeateSampleState * @return current state *************************************************************************/ U32 execROPermeateSampleMode( void ) { // The inlet pressure shall be checked all the time as long as VPi is open checkInletWaterPressure(); if ( roPermeateSampleState != DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN ) { // Do not check on the inlet water temperature and conductivity until the inlet filters have been flushed // The initial states are drain reservoirs but in those states VPi is closed so these alarms are not checked checkInletWaterTemperature(); checkInletWaterConductivity(); } monitorROPermeateSample(); switch ( roPermeateSampleState ) { case DG_RO_PERM_SAMPLE_STATE_START: roPermeateSampleState = handleROPermeateSampleStartState(); break; case DG_RO_PERM_SAMPLE_STATE_DRAIN_R1: roPermeateSampleState = handleROPermeateSampleDrainR1State(); break; case DG_RO_PERM_SAMPLE_STATE_DRAIN_R2: roPermeateSampleState = handleROPermeateSampleDrainR2State(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN: roPermeateSampleState = handleROPermeateSampleFlushDrainState(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_DIALYSATE: roPermeateSampleState = handleROPermeateSampleFlushDialysateState(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_CONCENTRATE_STRAWS: roPermeateSampleState = handleROPermeateSampleFlushConcenrateStrawsState(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1: roPermeateSampleState = handleROPermeateSampleFlushR2ToR1AndDrainR1State(); break; case DG_RO_PERM_SAMPLE_STATE_COLLECT_SAMPLE: roPermeateSampleState = handleROPermeateSampleCollectSampleState(); break; case DG_RO_PERM_SAMPLE_STATE_CANCEL_BASIC_PATH: roPermeateSampleState = handleROPermeateSampleCancelBasicPathState(); break; case DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH: roPermeateSampleState = handleROPermeateSampleCancelWaterPathState(); break; case DG_RO_PERM_SAMPLE_STATE_COMPLETE: roPermeateSampleState = handleROPermeateSampleCompleteState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_RO_PERMEATE_SAMPLE_INVALID_EXEC_STATE, roPermeateSampleState ) roPermeateSampleState = DG_RO_PERM_SAMPLE_STATE_START; break; } publishROPermeateSampleData(); return roPermeateSampleState; } /*********************************************************************//** * @brief * The getCurrentROPermeateSampleState function returns the current * state of the RO permeate sample mode. * @details Inputs: roPermeateSampleState * @details Outputs: none * @return the current state of RO permeate sample mode. *************************************************************************/ DG_RO_PERM_STATE_T getCurrentROPermeateSampleState( void ) { return roPermeateSampleState; } /*********************************************************************//** * @brief * The stopDGROPermeateSample function stops RO permeate sample mode * @details Inputs: none * @details Outputs: none * @return TRUE if the mode was stopped successfully otherwise, FALSE *************************************************************************/ BOOL stopDGROPermeateSample( void ) { BOOL status = FALSE; // Check if the current operation mode is RO permeate sample mode if ( DG_MODE_ROPS == getCurrentOperationMode() ) { // Reset all the actuators deenergizeActuators( PARK_CONC_PUMPS ); // Transition to mode standby requestNewOperationMode( DG_MODE_STAN ); status = TRUE; } return status; } /*********************************************************************//** * @brief * The setROPermeateSampleDispenseRequest function sets the RO permeate * sample dispense request. * @details Inputs: none * @details Outputs: dispenseMessageStatus * @param request the status of the request (1: dispense, 0: stop) * @return none *************************************************************************/ void setROPermeateSampleDispenseRequest( U32 request ) { dispenseMessageStatus = ( request == 1 ? DISPENSE_MSG_DISPENSE : DISPENSE_MSG_CANCEL ); } // ********** private functions ********** /*********************************************************************//** * @brief * The handleROPermeateSampleStartState function handles the RO permeate * sample start state. * @details Inputs: none * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleStartState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_DRAIN_R1; setROPermeateSampleStateTransition( state ); return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleDrainR1State function handles the RO permeate * sample drain R1 state. * @details Inputs: none * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleDrainR1State( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_DRAIN_R1; state = checkRsrvrDrainStatus( DG_RESERVOIR_1, state ); return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleDrainR2State function handles the RO permeate * sample drain R2 state. * @details Inputs: none * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleDrainR2State( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_DRAIN_R2; state = checkRsrvrDrainStatus( DG_RESERVOIR_2, state ); return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleFlushDrainState function handles the RO permeate * sample flush drain state. * @details Inputs: stateStartTimeMS * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleFlushDrainState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN; if ( TRUE == didTimeout( stateStartTimeMS, FLUSH_DRAIN_WAIT_TIME_MS ) ) { state = DG_RO_PERM_SAMPLE_STATE_FLUSH_DIALYSATE; setROPermeateSampleStateTransition( state ); } return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleFlushDialysateState function handles the RO permeate * sample flush dialysate state. * @details Inputs: stateStartTimeMS * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleFlushDialysateState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_FLUSH_DIALYSATE; if ( TRUE == didTimeout( stateStartTimeMS, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) { state = DG_RO_PERM_SAMPLE_STATE_FLUSH_CONCENTRATE_STRAWS; setROPermeateSampleStateTransition( state ); } return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleFlushConcenrateStrawsState function handles * the RO permeate sample flush concentrate straws state. * @details Inputs: stateStartTimeMS * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleFlushConcenrateStrawsState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_FLUSH_CONCENTRATE_STRAWS; if ( TRUE == didTimeout( stateStartTimeMS, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) { state = DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1; setROPermeateSampleStateTransition( state ); } return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleFlushR2ToR1AndDrainR1State function handles * the RO permeate sample flush R2 to R1 and drain R1 state. * @details Inputs: stateStartTimeMS, rsrvrsStatus, isReservoirFull * @details Outputs: stateStartTimeMS, rsrvrsStatus, isReservoirFull * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleFlushR2ToR1AndDrainR1State( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1; if ( DG_RESERVOIR_BELOW_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) { rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = getDisinfectRsrvrFillStatus( DG_RESERVOIR_2, &rsrvrsStatus, RSRVR_FILL_TARGET_FILL_ML, RSRVR_FILL_TIMEOUT_MS, stateStartTimeMS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) { if ( FALSE == isReservoirFull ) { isReservoirFull = TRUE; stateStartTimeMS = getMSTimerCount(); } if ( TRUE == didTimeout( stateStartTimeMS, RSRVR_DRAIN_BEFORE_SAMPLE_COLLECTION_MS ) ) { stateStartTimeMS = getMSTimerCount(); state = DG_RO_PERM_SAMPLE_STATE_COLLECT_SAMPLE; setROPermeateSampleStateTransition( state ); } } state = checkRsrvrMgmtTimeoutStatus( DG_RESERVOIR_2, state ); return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleCollectSampleState function handles * the RO permeate sample collect sample state. * @details Inputs: dispenseMessageStatus, roPermeateSampledispensedVolumeML * @details Outputs: dispenseMessageStatus, roPermeateSampledispensedVolumeML * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleCollectSampleState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_COLLECT_SAMPLE; if ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) { clearAlarm( ALARM_ID_DG_RO_PERMEATE_SAMPLE_REMOVE_DIA_CAP ); switch ( dispenseMessageStatus ) { case DISPENSE_MSG_READY: setROPermeateSampleStateTransition( state ); break; case DISPENSE_MSG_DISPENSING: // It is dispensing so do nothing break; case DISPENSE_MSG_CANCEL: state = DG_RO_PERM_SAMPLE_STATE_DRAIN_R1; setROPermeateSampleStateTransition( state ); break; case DISPENSE_MSG_DISPENSE: dispenseMessageStatus = DISPENSE_MSG_DISPENSE; if ( FALSE == isROPumpRunning() ) { setROPermeateSampleStateTransition( state ); dispenseMessageStatus = DISPENSE_MSG_DISPENSING; } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_RO_PERMEATE_SAMPLE_INVALID_MESSAGE, dispenseMessageStatus ) dispenseMessageStatus = DISPENSE_MSG_READY; break; } if ( TRUE == isROPumpRunning() ) { if ( roPermeateSampledispensedVolumeML < TARGET_DISPENSE_VOLUME_ML ) { roPermeateSampledispensedVolumeML += getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * FLOW_LPM_TO_VOL_ML_CONVERSION; } else { // Done with dispensing fluid // Message HD that DG is ready for the next command (either dispense more or cancel the run) dispenseMessageStatus = DISPENSE_MSG_READY; roPermeateSampledispensedVolumeML = 0.0F; setROPermeateSampleStateTransition( state ); handleSendROPermeateSampleDispenseReadyToHD(); // TODO should we send this multiple times until confirmation? } } } else { deenergizeActuators( NO_PARK_CONC_PUMPS ); activateAlarmNoData( ALARM_ID_DG_RO_PERMEATE_SAMPLE_REMOVE_DIA_CAP ); roPermeateSampledispensedVolumeML = 0.0F; dispenseMessageStatus = DISPENSE_MSG_READY; } return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleCancelBasicPathState function handles * the RO permeate sample cancel basic path state. * @details Inputs: none * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleCancelBasicPathState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_CANCEL_BASIC_PATH; failROPermeateSample(); return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleCancelWaterPathState function handles * the RO permeate sample cancel water path state. * @details Inputs: stateStartTimeMS, rsrvrsStatus * @details Outputs: stateStartTimeMS, rsrvrsStatus, alarmDetectedPendingTrigger * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleCancelWaterPathState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH; if ( DG_RESERVOIR_ABOVE_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) { // If the cancellation water path cannot be done, go to basic cancellation path rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = getDisinfectRsrvrDrainStatus( DG_RESERVOIR_2, &rsrvrsStatus, RSRVR_DRAIN_STEADY_TIMEOUT_MS, RSRVR_DRAIN_TIMEOUT_MS, stateStartTimeMS ); } else if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) && ( DG_RESERVOIR_BELOW_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) ) { // Reset the state timer for the next reservoir to drain stateStartTimeMS = getMSTimerCount(); rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = DG_RESERVOIR_ABOVE_TARGET; // Set the drain valve to reservoir 1 and close reservoir 2 setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); } else if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) && ( DG_RESERVOIR_ABOVE_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) ) { rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = getDisinfectRsrvrDrainStatus( DG_RESERVOIR_1, &rsrvrsStatus, RSRVR_DRAIN_STEADY_TIMEOUT_MS, RSRVR_DRAIN_TIMEOUT_MS, stateStartTimeMS ); } else if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) && ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) ) { failROPermeateSample(); } else if ( ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus ) || ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) ) { alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; state = DG_RO_PERM_SAMPLE_STATE_CANCEL_BASIC_PATH; } return state; } /*********************************************************************//** * @brief * The handleROPermeateSampleCompleteState function handles * the RO permeate sample complete state. * @details Inputs: none * @details Outputs: none * @return next state of the RO permeate sample state machine *************************************************************************/ static DG_RO_PERM_STATE_T handleROPermeateSampleCompleteState( void ) { DG_RO_PERM_STATE_T state = DG_RO_PERM_SAMPLE_STATE_COMPLETE; stopDGROPermeateSample(); return state; } /*********************************************************************//** * @brief * The failROPermeateSample function sets the alarm that failed the RO * permeate sample mode. * @details Inputs: alarmDetectedPendingTrigger, prevHeatDisinfectState * @details Outputs: none * @return none *************************************************************************/ static void failROPermeateSample( void ) { // In the cleaning modes the alarms are triggered but the mode is not transitioned to fault automatically // so transition to fault mode is done here if ( alarmDetectedPendingTrigger != ALARM_ID_NO_ALARM ) { SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, roPermeateSamplePrevState ) } requestNewOperationMode( DG_MODE_STAN ); } /*********************************************************************//** * @brief * The publishROPermeateSampleData function broadcasts RO permeate sample * data at the set interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ static void publishROPermeateSampleData( void ) { if ( ++dataPublishCounter >= RO_PERMEATE_SAMPLE_DATA_PUB_INTERVAL ) { MODE_RO_PERMEATE_SAMPLE_DATA_T data; data.roPermeateSampleState = (U32)roPermeateSampleState; data.overallElapsedTimeMS = calcTimeSince( overallROPermeateSampleTimer ); data.stateElapsedTimeMS = calcTimeSince( stateStartTimeMS ); data.roPermeateSampleDispensedVolML = roPermeateSampledispensedVolumeML; data.dispenseMessageStatus = (U32)dispenseMessageStatus; broadcastData( MSG_ID_DG_RO_PERMEATE_SAMPLE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_RO_PERMEATE_SAMPLE_DATA_T ) ); dataPublishCounter = 0; } } /*********************************************************************//** * @brief * The monitorROPermeateSample function monitors the status of the caps and * sets the state of the state machine to water cancellation path if the caps * are not closed during the run. * @details Inputs: none * @details Outputs: roPermeateSamplePrevState, roPermeateSampleState, * alarmDetectedPendingTrigger * @return: none *************************************************************************/ static void monitorROPermeateSample( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif { BOOL isDialysateCapOpen = ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ? TRUE : FALSE ); BOOL isConcentrateCapOpen = ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? TRUE : FALSE ); switch ( roPermeateSampleState ) { case DG_RO_PERM_SAMPLE_STATE_START: case DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN: case DG_RO_PERM_SAMPLE_STATE_FLUSH_DIALYSATE: case DG_RO_PERM_SAMPLE_STATE_FLUSH_CONCENTRATE_STRAWS: case DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1: if ( ( TRUE == isDialysateCapOpen ) || ( TRUE == isConcentrateCapOpen ) ) { roPermeateSamplePrevState = roPermeateSampleState; roPermeateSampleState = DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ( TRUE == isDialysateCapOpen ? ALARM_ID_DG_DIALYSATE_CAP_NOT_IN_PROPER_POSITION : ALARM_ID_DG_CONCENTRATE_CAP_NOT_IN_PROPER_POSITION ); setROPermeateSampleStateTransition( roPermeateSampleState ); } break; } } if ( ( TRUE == isDGFaultAlarmActive() ) || ( TRUE == isAnyCleaningModeInletWaterConditionActive() ) ) { if ( roPermeateSampleState != DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH ) { // If there is any fault alarm and we are not already in the cancel water path state, set it to cancel water path state roPermeateSamplePrevState = roPermeateSampleState; roPermeateSampleState = DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH; setROPermeateSampleStateTransition( roPermeateSampleState ); } } } /*********************************************************************//** * @brief * The setROPermeateSampleStateTransition function handles setting the * actuators and variables prior to transitioning to an RO permeate sample state. * @details Inputs: collectSampleSubState * @details Outputs: stateStartTimeMS, rsrvrsStatus, isReservoirFull, * collectSampleSubState, roPermeateSampledispensedVolumeML, dispenseMessageStatus * @param state which is the state to prepare the actuators and variables * @return none *************************************************************************/ static void setROPermeateSampleStateTransition( DG_RO_PERM_STATE_T state ) { switch( state ) { case DG_RO_PERM_SAMPLE_STATE_DRAIN_R1: // Valves setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOffUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump signalROPumpHardStop(); // Drain pump setDrainPumpTargetRPM( RSRVR_DRAIN_TARGET_RPM ); // Variables stateStartTimeMS = getMSTimerCount(); break; case DG_RO_PERM_SAMPLE_STATE_DRAIN_R2: // Valves setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOffUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump signalROPumpHardStop(); // Drain pump setDrainPumpTargetRPM( RSRVR_DRAIN_TARGET_RPM ); // Variables stateStartTimeMS = getMSTimerCount(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN: // Valves setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOnUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump signalROPumpHardStop(); // Drain pump signalDrainPumpHardStop(); // Variables stateStartTimeMS = getMSTimerCount(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_DIALYSATE: // Valves setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Drain pump signalDrainPumpHardStop(); // Variables stateStartTimeMS = getMSTimerCount(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_CONCENTRATE_STRAWS: // Valves setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // Set the concentrate pumps speed setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); // Turn on the concentrate pumps requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); // RO pump setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Drain pump signalDrainPumpHardStop(); // Variables stateStartTimeMS = getMSTimerCount(); break; case DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1: // Valves setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Drain pump setDrainPumpTargetRPM( RSRVR_DRAIN_TARGET_RPM ); // Setup the variables for the next state rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = DG_RESERVOIR_BELOW_TARGET; stateStartTimeMS = getMSTimerCount(); isReservoirFull = FALSE; break; case DG_RO_PERM_SAMPLE_STATE_COLLECT_SAMPLE: switch( dispenseMessageStatus ) { case DISPENSE_MSG_CANCEL: case DISPENSE_MSG_READY: deenergizeActuators( NO_PARK_CONC_PUMPS ); break; case DISPENSE_MSG_DISPENSE: // Valves setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_DISPENSE_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Drain pump setDrainPumpTargetRPM( RSRVR_DRAIN_TARGET_RPM ); roPermeateSampledispensedVolumeML = 0.0F; break; case DISPENSE_MSG_DISPENSING: default: // Do nothing. In these states, we do not need to do anything with actuators break; } break; case DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH: // Prepare to start draining reservoir 2 first // Valves setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // UV reactors turnOffUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); // Concentrate pumps requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // RO pump signalROPumpHardStop(); // Drain pump setDrainPumpTargetRPM( RSRVR_DRAIN_TARGET_RPM ); // Variables stateStartTimeMS = getMSTimerCount(); rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = DG_RESERVOIR_BELOW_TARGET; rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = DG_RESERVOIR_ABOVE_TARGET; break; case DG_RO_PERM_SAMPLE_STATE_COMPLETE: deenergizeActuators( NO_PARK_CONC_PUMPS ); break; default: // Do nothing break; } } /*********************************************************************//** * @brief * The checkRsrvrMgmtTimeoutStatus function checks and manages the status * of reservoir management timeout status * @details Inputs: rsrvrsStatus * @details Outputs: alarmDetectedPendingTrigger, roPermeateSamplePrevState * @param rsrvrID the reservoir ID to check the status of the timeout * @param state the state of the RO permeate sample mode * @return: state of the RO permeate sample mode *************************************************************************/ static DG_RO_PERM_STATE_T checkRsrvrMgmtTimeoutStatus( DG_RESERVOIR_ID_T rsrvrID, DG_RO_PERM_STATE_T state ) { if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) { switch ( state ) { case DG_RO_PERM_SAMPLE_STATE_FLUSH_R2_TO_R1_AND_DRAIN_R1: alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; break; case DG_RO_PERM_SAMPLE_STATE_DRAIN_R1: case DG_RO_PERM_SAMPLE_STATE_DRAIN_R2: alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; break; default: // Do nothing break; } roPermeateSamplePrevState = state; state = DG_RO_PERM_SAMPLE_STATE_CANCEL_WATER_PATH; setROPermeateSampleStateTransition( state ); } return state; } /*********************************************************************//** * @brief * The checkRsrvrDrainStatus function checks and manages the status * of reservoir drain status * @details Inputs: rsrvrsStatus, stateStartTimeMS * @details Outputs: rsrvrsStatus, stateStartTimeMS * @param rsrvrID the reservoir ID to check the status of the timeout * @param state the state of the RO permeate sample mode * @return: state of the RO permeate sample mode *************************************************************************/ static DG_RO_PERM_STATE_T checkRsrvrDrainStatus( DG_RESERVOIR_ID_T rsrvrID, DG_RO_PERM_STATE_T state ) { if ( DG_RESERVOIR_ABOVE_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) { rsrvrsStatus.rsrvr[ rsrvrID ].rStatus = getDisinfectRsrvrDrainStatus( rsrvrID, &rsrvrsStatus, RSRVR_DRAIN_STEADY_TIMEOUT_MS, RSRVR_DRAIN_TIMEOUT_MS, stateStartTimeMS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) { if ( TRUE == rsrvrsStatus.isThisInitialDrain ) { LOAD_CELL_ID_T backUp = ( LOAD_CELL_RESERVOIR_1_PRIMARY == rsrvrsStatus.rsrvr[ rsrvrID ].loadCell ? LOAD_CELL_RESERVOIR_1_BACKUP : LOAD_CELL_RESERVOIR_2_BACKUP ); tareLoadCell( rsrvrsStatus.rsrvr[ rsrvrID ].loadCell ); tareLoadCell( backUp ); } if ( DG_RO_PERM_SAMPLE_STATE_DRAIN_R1 == state ) { DG_RESERVOIR_ID_T switchRsrvrID = ( DG_RESERVOIR_1 == rsrvrID ? DG_RESERVOIR_2 : DG_RESERVOIR_1 ); rsrvrsStatus.rsrvr[ switchRsrvrID ].rStatus = DG_RESERVOIR_ABOVE_TARGET; state = DG_RO_PERM_SAMPLE_STATE_DRAIN_R2; } else if ( DG_RO_PERM_SAMPLE_STATE_DRAIN_R2 == state ) { state = ( TRUE == rsrvrsStatus.isThisInitialDrain ? DG_RO_PERM_SAMPLE_STATE_FLUSH_DRAIN : DG_RO_PERM_SAMPLE_STATE_COMPLETE ); rsrvrsStatus.isThisInitialDrain = FALSE; } stateStartTimeMS = getMSTimerCount(); setROPermeateSampleStateTransition( state ); } state = checkRsrvrMgmtTimeoutStatus( rsrvrID, state ); return state; } /**@}*/