Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r19934ca6e36e2dcabd6a6083a9a1f15b1ed32189 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 19934ca6e36e2dcabd6a6083a9a1f15b1ed32189) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -16,6 +16,7 @@ ***************************************************************************/ #include "ConcentratePumps.h" +#include "ConductivitySensors.h" #include "CPLD.h" #include "DrainPump.h" #include "FlowSensors.h" @@ -39,118 +40,161 @@ * @{ */ + // ********** private definitions ********** // General defines -#define FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode flush data publish interval in counts. -#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 DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. +#define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. +#define CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. +// Start state defines +#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. + // Drain R1 & R2 states defines -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. +#define RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. +#define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. +#define FLUSH_DRAIN_WAIT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. +#define MAX_ALLOWED_FLUSH_DRAIN_PERIODS 2 ///< Number of flush drain periods to wait for inlet water to come in range +#define MIN_INLET_TEMPERATURE_C 20.0F ///< Minimum water inlet temperature in C. TODO original temperature was 25 C +#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm +#define MIN_INLET_CONDUCTIVITY_US_PER_CM 100.0F ///< Minimum water inlet conductivity in us/cm -// Flush dialysate state defines -#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. +// Flush circulation path state defines +#define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. +#define MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. +#define FLUSH_CICRCULATION_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush/rinse circulation path wait time in milliseconds. -// Flush concentrate straws state defines -#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. -#define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid pump speed in mL/min. +// Flush and drain R1 and R2 +#define RSRVRS_FULL_VOL_ML 1000.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. +#define RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. +#define FLUSH_ADDITIONAL_TIME_MS ( 38 * MS_PER_SECOND ) ///< Additional time to flush after reservoir full +#define NUM_OF_RINSE_CYCLES 2 ///< Number of rinse cycles -// The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during flush -#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb pump speed in mL/min. +#define CONC_PUMP_FLUSH_SPEED_ML_PER_MIN 40.0 ///< Concentrate pump speed for flush +#define FLUSH_DISINFECTANT_LINE_WAIT_TIME_MS ( 2.5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush disinfectant line in milliseconds. +#define FLUSH_UF_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush UF in milliseconds. -// Flush and drain R1 and R2 state defines -#define RSRVRS_FULL_VOL_ML 1800.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 -#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0F ///< Reservoirs 1 & 2 partial volume in mL. -#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. -#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. -#define RSRVRS_PARTIAL_FILL_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. -#define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. -#define FINAL_DRAIN_RO_PUMP_FLOW_LPM 0.6F ///< Final drain RO pump flow rate in L/min. This is used to flush the drain line during drain. +/// Cancellation paths +typedef enum Cancellation_modes +{ + CANCELLATION_MODE_NONE = 0, ///< Cancellation mode none. + CANCELLATION_MODE_BASIC, ///< Cancellation mode basic. + CANCELLATION_MODE_WATER, ///< Cancellation mode water. + NUM_OF_CANCELLATION_MODES ///< Number of cancellation modes. +} CANCELLATION_MODE_T; -// Flush drain line state defines -#define FLUSH_DRAIN_LINE_VOLUME_L 0.1F ///< Water volume to flush in liters. -#define FLUSH_DRAIN_LINE_TIMEOUT_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush drain lines timeout in milliseconds. +/// Non-volatile write structure +typedef struct +{ + BOOL hasDisFlushStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush status been written to NV or not. + BOOL hasDisFlushCompleteDateBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush complete date been written to NV or not. +} DISINFECT_FLUSH_NV_OPS_T; -// Flush circulation state defines -#define FLUSH_CIRCULATION_WAIT_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush circulation wait time in milliseconds. - -// Flush with fresh water state defines -#define FLUSH_WITH_FRESH_WATER_WAIT_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush with fresh water wait time in milliseconds. - // ********** private data ********** -static DG_FLUSH_STATE_T flushState; ///< Current active flush state. -static DG_FLUSH_STATE_T prevFlushState; ///< Previous flush state. -static DG_FLUSH_UI_STATE_T flushUIState; ///< Current UI flush state. -static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. -static U32 overallFlushElapsedTimeStart; ///< Overall flush mode elapsed time start. -static U32 stateTimerStart; ///< State timer start. -static ALARM_ID_T alarmDetectedPendingTrigger; ///< Alarm ID that is detected and is pending to be triggered. -static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. -static BOOL isThisInitialDrain; ///< Initial drain boolean flag. -static U32 dataPublishCounter; ///< Flush data publish counter. -static BOOL hasWaterCancellationBeenSet; ///< Water cancellation set/not set boolean flag. -static F32 flushLinesVolumeL; ///< Volume of water pumped by RO pump during flush lines state. -static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +static DG_CHEM_DISINFECT_FLUSH_STATE_T chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Currently active chemical disinfect state. +static DG_CHEM_DISINFECT_FLUSH_STATE_T prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Previous active chemical disinfect flush state before alarm. +static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect UI state. +static U32 overallChemDisinfectFlushTimerStart = 0; +static U32 stateTimer = 0; ///< Chemical disinfect state timer to be used in different states. +static U32 stateTrialCounter = 0; ///< Chemical disinfect state trial counter to be used for retries in different states. +static BOOL areTempSensorsInRange = FALSE; ///< Chemical disinfect temperature sensors in/out range flag. +static BOOL haveInletWaterChecksPassed = TRUE; ///< Inlet water pressure, temperature, and pressure in range flag +/// Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect flush cycle or in the beginning. So the drain states can be reused. +static BOOL isThisLastDrain = FALSE; +static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. +static F32 R1ChemDisinfectFlushVol = 0.0; ///< Reservoir 1 full volume during chemical disinfect. +static F32 R2ChemDisinfectFlushVol = 0.0; ///< Reservoir 2 full volume during chemical disinfect. +static U32 chemDisinfectFlushTimer = 0; ///< Chemical disinfect timer. +static U32 rinseCycleCounter = 0; ///< Counter for rinse fill and drain cycles +static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during chemical disinfect. +static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during chemical disinfect. +static U32 dataPublishCounter = 0; ///< Chemical Disinfect data publish counter. +static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. +static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. +static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +static DISINFECT_FLUSH_NV_OPS_T disinfectFlushNVOps; ///< Disinfect flush non-volatile memory operations. // ********** private function prototypes ********** -static DG_FLUSH_STATE_T handleFlushModeStartState( void ); -static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ); -static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushWithFreshWaterState( void ); -static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ); -static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ); -static DG_FLUSH_STATE_T handleFlushModeComplete( void ); +//static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushRemoveAcidBottleFromUIState( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDrainState( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDisinfectantLineState( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState(void); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState(void); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ); -static void failFlushMode( void ); +static void failChemicalDisinfectFlush( void ); static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ); static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); -static void publishFlushData( void ); -static void monitorModeFlush( void ); +static void publishChemicalDisinfectFlushData( void ); +static void monitorModeChemicalDisinfectFlush( void ); +static void writeDisinfectDataToNV( void ); /*********************************************************************//** * @brief - * The initFlushMode function initializes flush mode module. + * The initChemicalDisinfectFlushMode function initializes the chemical + * disinfect flush mode module. * @details Inputs: none - * @details Outputs: flushState, prevFlushState, rsrvrFillStableTimeCounter, - * overallFlushElapsedTime, isThisInitialDrain, dataPublishCounter, - * rsrvr1Status, rsrvr2Status, hasWaterCancellationBeenSet, - * flushLinesVolumeL, haveDrainParamsBeenInit, stateTimerStart + * @details Outputs: chemDisinfectFlushState, stateTimer, isThisLastDrain, + * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, + * overallChemDisinfectFlushTimer, + * cancellationMode, rsrvrFillStableTimeCounter, prevChemDisinfectFlushState + * numberOfPostDisinfectRinses, + * chemDisinfectFlushUIState, haveDrainParamsBeenInit, + * disinfectFlushNVOps * @return none -*************************************************************************/ -void initFlushMode( void ) + *************************************************************************/ +//void initChemicalDisinfectFlushMode( void ) +void initFlushMode(void) { - // Initialize the variables - flushState = DG_FLUSH_STATE_START; - prevFlushState = DG_FLUSH_STATE_START; - flushUIState = FLUSH_UI_STATE_NOT_RUNNING; - rsrvrFillStableTimeCounter = 0; - overallFlushElapsedTimeStart = 0; - isThisInitialDrain = TRUE; - dataPublishCounter = 0; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - hasWaterCancellationBeenSet = FALSE; - flushLinesVolumeL = 0.0; - haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; - haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; - stateTimerStart = 0; + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + overallChemDisinfectFlushTimerStart = 0; + stateTimer = 0; + isThisLastDrain = FALSE; + stateTrialCounter = 0; + areTempSensorsInRange = FALSE; + haveInletWaterChecksPassed = TRUE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillStableTimeCounter = 0; + numberOfPostDisinfectRinses = 0; + R1ChemDisinfectFlushVol = 0.0; + R2ChemDisinfectFlushVol = 0.0; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + //disinfectFlushNVOps.hasFlushCompleteDateBeenWrittenToNV = FALSE; + //disinfectFlushNVOps.hasFlushStatusBeenWrittenToNV = FALSE; } +/******** +void initFlushMode( void ); // initialize this module +U32 transitionToFlushMode( void ); // prepares for transition to pre-treatment mode +U32 execFlushMode( void ); // execute the pre-treatment mode state machine (call from OperationModes) + +DG_FLUSH_STATE_T getCurrentFlushState( void ); // get the current state of the flush mode. + +BOOL stopDGFlush( void ); +*/ + /*********************************************************************//** * @brief * The transitionToFlushMode function prepares for transition to flush mode. @@ -167,91 +211,10 @@ setCPLDCleanLEDColor( CPLD_CLEAN_LED_BLUE ); - return flushState; + return chemDisinfectFlushState; } -/*********************************************************************//** - * @brief - * The execFlushMode function executes the flush mode state machine. - * @details Inputs: flushState - * @details Outputs: flushState - * @return current state -*************************************************************************/ -U32 execFlushMode( void ) -{ - monitorModeFlush(); - // Execute current flush state - switch ( flushState ) - { - case DG_FLUSH_STATE_START: - flushState = handleFlushModeStartState(); - break; - - case DG_FLUSH_STATE_DRAIN_R1: - flushState = handleFlushModeDrainR1State(); - break; - - case DG_FLUSH_STATE_DRAIN_R2: - flushState = handleFlushModeDrainR2State(); - break; - - case DG_FLUSH_STATE_FLUSH_DRAIN: - flushState = handleFlushModeFlushDrainState(); - break; - - case DG_FLUSH_STATE_FLUSH_DIALYSATE: - flushState = handleFlushModeFlushDialysateState(); - break; - - case DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS: - flushState = handleFlushModeFlushConcentrateStrawsState(); - break; - - case DG_FLUSH_STATE_FLUSH_R1_TO_R2: - flushState = handleFlushModeFlushR1ToR2State(); - break; - - case DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1: - flushState = handleFlushModeFlushR2AndDrainR1State(); - break; - - case DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE: - flushState = handleFlushModeFlushCirculationDrainLineState(); - break; - - case DG_FLUSH_STATE_FLUSH_CIRCULATION: - flushState = handleFlushModeFlushCirculationState(); - break; - - case DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER: - flushState = handleFlushModeFlushWithFreshWaterState(); - break; - - case DG_FLUSH_STATE_CANCEL_BASIC_PATH: - flushState = handleFlushModeCancelBasicPathState(); - break; - - case DG_FLUSH_STATE_CANCEL_WATER_PATH: - flushState = handleFlushModeCancelWaterPathState(); - break; - - case DG_FLUSH_STATE_COMPLETE: - flushState = handleFlushModeComplete(); - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_FLUSH_INVALID_EXEC_STATE, flushState ) - flushState = DG_FLUSH_STATE_START; - break; - } - - // Publish the data - publishFlushData(); - - return (U32)flushState; -} - /*********************************************************************//** * @brief * The getCurrentFlushState function returns the current state of the flush @@ -262,7 +225,7 @@ *************************************************************************/ DG_FLUSH_STATE_T getCurrentFlushState( void ) { - return flushState; + return chemDisinfectFlushState; } /*********************************************************************//** @@ -292,654 +255,684 @@ return status; } -// ********** private functions ********** +/*********************************************************************//** + * @brief + * The execChemicalDisinfectFlushMode function executes the chemical disinfect + * flush mode state machine. + * @details Inputs: none + * @details Outputs: Chemical disinfect flush mode state machine executed + * @return current state of chemical disinfect flush mode + *************************************************************************/ +//U32 execChemicalDisinfectFlushMode( void ) +U32 execFlushMode( void ) +{ + monitorModeChemicalDisinfectFlush(); + switch ( chemDisinfectFlushState ) + { + case DG_CHEM_DISINFECT_FLUSH_STATE_START: + chemDisinfectFlushState = handleChemicalDisinfectFlushStartState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1: + chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR1State(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2: + chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR2State(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN: + chemDisinfectFlushState = handleChemicalDisinfectFlushFlushDrainState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE: + chemDisinfectFlushState = handleChemicalDisinfectFlushFlushDisinfectantLineState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF: + chemDisinfectFlushState = handleChemicalDisinfectFlushFlushUFState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1: + chemDisinfectFlushState = handleChemicalDisinfectFlushFlushR2ToR1DrainR1State(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2: + chemDisinfectFlushState = handleChemicalDisinfectFlushFlushR1ToR2DrainR2State(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH: + chemDisinfectFlushState = handleChemicalDisinfectFlushCancelModeBasicPathState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH: + chemDisinfectFlushState = handleChemicalDisinfectFlushCancelModeWaterPathState(); + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE: + chemDisinfectFlushState = handleChemicalDisinfectFlushCompleteState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_CHEM_DISINFECT_INVALID_EXEC_STATE, chemDisinfectFlushState ) + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + break; + } + + //publishChemicalDisinfectFlushData(); + + return chemDisinfectFlushState; +} + /*********************************************************************//** * @brief - * The handleFlushModeStartState function handles the flush start state. - * If the sensors are in range, it transitions to the next state otherwise, - * it transitions to basic cancellation state. - * @details Inputs: stateTimerStart, rsrvr1Status - * @details Outputs: stateTimerStart, rsrvr1Status - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushStartState function handles the chemical + * disinfect flush start state. The state checks the inlet pressure and the + * difference in between TDi and TRo sensors and if they are not in + * range, it transitions to basic cancellation path. Otherwise, it + * transitions to the next state. + * @details Inputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, + * stateTimer + * @details Outputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, + * stateTimer, chemDisinfectFlushUIState + * @return next state of the chemical disinfect flush state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeStartState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_START; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; - // Start overall flush timer - overallFlushElapsedTimeStart = getMSTimerCount(); + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; + // Start overall chemical disinfect timer + overallChemDisinfectFlushTimerStart = getMSTimerCount(); + + // Set all the actuators to reset and de-energized state + deenergizeActuators(); + // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); // Set the actuators to drain R1 + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); - - // Set VPO - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; - stateTimerStart = getMSTimerCount(); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R1; + rsrvrFillStableTimeCounter = 0; + // Assume reservoir 1 is full and drain it + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); return state; } /*********************************************************************//** * @brief - * The handleFlushModeDrainR1State function handles the drain reservoir 1. - * If the drain is completed within the defined time, it transitions to the - * next state, otherwise, it transitions to basic cancellation state. - * @details Inputs: stateTimerStart, rsrvr1Status,rsrvr2Status, isThisInitialDrain - * @details Outputs: stateTimerStart, rsrvr1Status, rsrvr2Status - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushDrainR1State function handles the chemical + * disinfect flush drain R1 state. The state drains reservoir 1. If the + * transition is finished within the time, it transitions to the next state, + * otherwise, it transitions to basic cancellation path. + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, + * ChemDisinfectFlushUIState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R1; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - if ( TRUE == isThisInitialDrain ) - { - // Request a tare for reservoir 1 - tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - } + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Close reservoir 1 drain + tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); + + // Done with draining R1 setValveState( VRD1, VALVE_STATE_CLOSED ); - // Set the actuators to drain R2 - // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); - // Set VPO - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; - stateTimerStart = getMSTimerCount(); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R2; + // Start the timer + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; } return state; } /*********************************************************************//** * @brief - * The handleFlushModeDrainR2State function handles the drain reservoir 2. - * If the drain is completed within the defined time, it transitions to the - * next state, otherwise, it transitions to basic cancellation state. - * @details Inputs: stateTimerStart, rsrvr1Status, rsrvr2Status, isThisInitialDrain - * @details Outputs: stateTimerStart, rsrvr1Status, rsrvr2Status - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushDrainR2State function handles the chemical + * disinfect flush drain R2 state. The state drains reservoir 2. If the + * transition is finished within the time, it transitions to the next + * state, otherwise, it transitions to basic cancellation path. + * @details Inputs: stateTimer, rsrvr2Status, isThisLastDrain, + * stateTrialCounter + * @details Outputs: stateTimer, rsrvr2Status, stateTrialCounter, + * chemDisinfectFlushUIState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R2; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - // Done with draining - signalDrainPumpHardStop(); + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) + { + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + signalDrainPumpHardStop(); // Done with draining + if ( TRUE == isThisLastDrain ) + { + state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; + } + else + { + tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + // ??? make sure load cell check is done in tareLoadCell or add that here? + + // Set valves for next state, flush drain + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPI, VALVE_STATE_OPEN ); - if ( TRUE == isThisInitialDrain ) - { - tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + stateTrialCounter = 0; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; + } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + } - // Set the actuators to flush drain - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - - state = DG_FLUSH_STATE_FLUSH_DRAIN; - } - else - { - // Set the actuators to pull fresh water in to drain the circulation line - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setROPumpTargetFlowRateLPM( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); - - // Turn on the UV reactors - turnOnUVReactor( INLET_UV_REACTOR ); - turnOnUVReactor( OUTLET_UV_REACTOR ); - - flushUIState = FLUSH_UI_STATE_FLUSH_RECIRCULATION_PATH; - state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; - } - - stateTimerStart = getMSTimerCount(); - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - } - return state; } /*********************************************************************//** * @brief - * The handleFlushModeFlushDrainState function handles the flush drain state. - * Once the flush drain time has elapsed, it transitions to the next state. - * @details Inputs: stateTimerStart - * @details Outputs: stateTimerStart - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushFlushDrainState function handles the chemical + * disinfect flush drain state. The state flushes the drain line for a + * period of time and then measures the temperature and conductivity of + * water. If they are not within the range after the specified number of tries, + * it transitions to basic cancellation path, otherwise it transitions to the next state. + * @details Inputs: stateTimer, stateTrialCounter, alarm, + * prevChemDisinfectFlushState + * @details Outputs: stateTimer, stateTrialCounter, alarm, + * prevChemDisinfectFlushState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDrainState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; - if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) + // TODO: check whether flush has already been completed within some time period, skip this state if it has + + // Check if flush time has elapsed + if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + if (haveInletWaterChecksPassed) + { + // set pumps and valves for next state, flush disinfectant line + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + // Set the concentrate pump to run at a constant speed during priming in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, -1.0 * CONC_PUMP_FLUSH_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + // Turn on the bicarb line with forward direction, to dispense the chemical and mix + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_FLUSH_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; + } + else + { + // If the number of failures have not exceeded the limit, try again. + stateTrialCounter++; + if ( stateTrialCounter < MAX_ALLOWED_FLUSH_DRAIN_PERIODS ) + { + stateTimer = getMSTimerCount(); + } + // Couldn't get a good water sample after a couple of trials and the disinfect flush cycle failed + else + { + alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_DG_NEW_WAT; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + } + } - // Turn on the UV reactors - turnOnUVReactor( INLET_UV_REACTOR ); - turnOnUVReactor( OUTLET_UV_REACTOR ); - - stateTimerStart = getMSTimerCount(); - - state = DG_FLUSH_STATE_FLUSH_DIALYSATE; } return state; } /*********************************************************************//** * @brief - * The handleFlushModeFlushDialysateState function handles the flush - * dialysate state. Once the flush dialysate time has elapsed, it - * transitions to the next state. - * @details Inputs: stateTimerStart - * @details Outputs: stateTimerStart - * @return next state of the flush state machine - *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ) + * The handleChemicalDisinfectFlushFlushDisinfectantLineState function handles the + * chemical disinfect flush flush disinfectant line state. The state flushes the + * disinfectant line for a period of time. After the flush if the temperature + * sensors are not within a certain degrees from each other, the state + * transitions to basic cancellation path, otherwise, it transitions to the + * next state. + * @details Inputs: stateTimer, stateTrialCounter, prevChemDisinfectFlushState + * alarm, areTempSensorsInRange, rsrvr1Status, rsrvr2Status + * @details Outputs: stateTimer, stateTrialCounter, prevChemDisinfectFlushState, + * alarm, areTempSensorsInRange, rsrvr1Status, rsrvr2Status + * @return next state of the chemical disinfect state machine + ************************************************************************/ +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDisinfectantLineState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DIALYSATE; - - if ( TRUE == didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; + + // Check if the flush disinfectant line time has elapsed + if ( TRUE == didTimeout( stateTimer, FLUSH_DISINFECTANT_LINE_WAIT_TIME_MS ) ) { - // Turn the pumps on in reverse - 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 ); - - stateTimerStart = getMSTimerCount(); - - state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + // set the pumps and valves for the next state, flush UF + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRD2, VALVE_STATE_OPEN ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF; } return state; } /*********************************************************************//** * @brief - * The handleFlushModeFlushDialysateState function handles the flush - * dialysate state. Once the flush dialysate time has elapsed, it - * transitions to the next state. - * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushFlushUFState function handles the + * chemical disinfect flush flush UF state. + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, + * prevChemDisinfectFlushState + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, + * prevChemDisinfectFlushState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF; - if ( TRUE == didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) + // Check if the flush UFtime has elapsed + if ( TRUE == didTimeout( stateTimer, FLUSH_UF_WAIT_TIME_MS ) ) { - // Done with flushing the concentrate pumps line - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + // set the pumps and valves for the next state, flush R2 to R1 and drain R1 + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - stateTimerStart = getMSTimerCount(); - - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - flushUIState = FLUSH_UI_STATE_FLUSH_RESERVOIRS; - state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rinseCycleCounter = 0; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; } - + return state; } + /*********************************************************************//** * @brief - * The handleFlushModeFlushR1ToR2State function handles the flush - * reservoir 1 to reservoir 2 state. If any of the reservoirs flush within - * the defined period of time, it transitions to the next state, otherwise, - * it transitions to water cancellation state. If reservoir 2 is filled to - * 500 mL before reservoir 1 is filled, it transitions to water cancellation - * state. - * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart, - * prevFlushState, alarmDetectedPendingTrigger - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushRinseR2ToR1AndDrainR1State function handles + * the chemical disinfect rinse R2 to R1 and drain R1 state. The state + * rinses reservoir 2 and drains reservoir 1 at the same time. If the drain + * process times out, it transitions to basic cancellation state, and + * if the rinse times out, it transitions to water cancellation state. + * If the drain and rinse are completed within the define time, it + * transitions to the next state. + * @details Inputs: rsrvr1Status, rsrvr2Status + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, + * prevChemDisinfectFlushState, alarmDetectedPendingTrigger + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; + static BOOL rsrvr1Empty = FALSE; + static BOOL rsrvr2Full = FALSE; - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + if ( FALSE == rsrvr1Empty ) { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - - // Keep monitoring the status of reservoir 2 as the same time - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); - // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already - // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue - // until reservoir 2 is filled up and the tubing might expand or leak. - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - prevFlushState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ); } + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { + // Done with draining R1 + signalDrainPumpHardStop(); + setValveState( VRD1, VALVE_STATE_CLOSED ); + rsrvr1Empty = TRUE; + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + // reservoir 1 drain timeout + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + } } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + + if ( FALSE == rsrvr2Full ) { + // Reservoir 2 must be completely full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Set the actuators to flush R2 and drain R1 state - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_OPEN ); - - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - stateTimerStart = getMSTimerCount(); - - // Set both reservoirs' status - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + rsrvr2Full = TRUE; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + + if ( ( TRUE == rsrvr2Full ) && ( TRUE == rsrvr1Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } + // Set the valves to flush R1 to R2 and drain R2 + setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + + // Set the reservoir status + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; + + } return state; } /*********************************************************************//** * @brief - * The handleFlushModeFlushR2AndDrainR1State function handles the flush - * reservoir 2 and drain reservoir 1 state. If reservoir 2 flushes within - * the defined period of time and reservoir 1 drains within the defined - * period of time, it transitions to the next state. If the flush times out, - * the function transitions to water cancellation state. If the drain times - * out the function transitions to basic cancellation state. If reservoir 1 - * is filled to 500 mL before reservoir 2 is filled, it transitions to - * water cancellation state. - * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart, - * prevFlushState, alarmDetectedPendingTrigger, isThisInitialDrain - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushRinseR1ToR2AndDrainR2State function handles + * the chemical disinfect flush rinse R1 to R2 and drain R2 state. The state + * rinses reservoir 1 and drains reservoir 2 at the same time. If the drain + * process times out, it transitions to basic cancellation state, and + * if the rinse times out, it transitions to water cancellation state. + * If the drain and rinse are completed within the define time, it + * transitions to the next state. + * @details Inputs: rsrvr1Status, rsrvr2Status, rinseCycleCounter + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, + * prevChemDisinfectFlushState, alarmDetectedPendingTrigger, isThisLastDrain + * numberOfPostDisinfectRinses + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; - // If reservoir 1 is empty, turn off the drain pump - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) - { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - // Done with draining R1 - signalDrainPumpHardStop(); - setValveState( VRD1, VALVE_STATE_CLOSED ); - } - // Reservoir 1 drain time out - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - } + static BOOL rsrvr2Empty = FALSE; + static BOOL rsrvr1Full = FALSE; - // First reservoir 2 must be completely full but if reservoir 1 is filled before reservoir 2 is full, alarm - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) + if ( FALSE == rsrvr2Empty ) { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - - U32 drainPumpRPM = getDrainPumpTargetRPM(); - // Keep monitoring the status of reservoir 1 as the same time - F32 volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - // Reservoir 1 cannot be filled before reservoir 2 is filled and is overflowing to reservoir 1. If reservoir 1 has already - // reached to target volume, it means reservoir 2's load cell might be reading incorrect values. This situation might continue - // until reservoir 1 is filled up and the tubing might expand or leak. - // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make - // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { - prevFlushState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ); } + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + // Done with draining R2 + signalDrainPumpHardStop(); + setValveState( VRD2, VALVE_STATE_CLOSED ); + rsrvr2Empty = TRUE; + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + // reservoir 2 drain timeout + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + } } - // Once reservoir 2 is full, reservoir 1 must be partially full - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); - // Once R1 is partially full, transition to the next state + if ( FALSE == rsrvr1Full ) + { + // Reservoir 1 must be completely full + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + } if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - signalROPumpHardStop(); - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - // Turn off the UV reactors prior to transitioning to drain states. - // In the drain states, there is not fluid flowing in the RO section so the reactors are turned off - turnOffUVReactor( INLET_UV_REACTOR ); - turnOffUVReactor( OUTLET_UV_REACTOR ); - - // Close VPi and VPd to drain - setValveState(VPI, VALVE_STATE_CLOSED); - setValveState(VPD, VALVE_STATE_DRAIN_C_TO_NO); - // Set VPO - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - - stateTimerStart = getMSTimerCount(); - isThisInitialDrain = FALSE; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - flushUIState = FLUSH_UI_STATE_DRAIN_RESERVOIRS; - state = DG_FLUSH_STATE_DRAIN_R1; + rsrvr1Full = TRUE; + stateTimer = getMSTimerCount(); } - // Check if reservoir 1 fill timed out - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } } - // Check if reservoir 2 fill time out - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } - return state; -} - -/*********************************************************************//** - * @brief - * The handleFlushModeFlushCirculationDrainLineState function handles the - * flush drain line state. Once the drain line was flushed with sufficient - * water, it transitions to the next state. If the line is not drained - * within the defined time, it transitions to water cancellation state. - * @details Inputs: stateTimerStart, flushLinesVolumeL - * @details Outputs: stateTimerStart, flushLinesVolumeL, - * alarmDetectedPendingTrigger - * @return next state of the flush state machine - *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ) -{ - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; - - F32 waterFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); - F32 waterVolume = ( ( waterFlowRate / SEC_PER_MIN ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - - // Integrate volume of water moved through line - flushLinesVolumeL += waterVolume; - - // When enough water volume has flowed to flush the lines, transition to flush circulation state - if ( flushLinesVolumeL >= FLUSH_DRAIN_LINE_VOLUME_L ) + if ( ( TRUE == rsrvr1Full ) && ( TRUE == rsrvr2Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { - // Set the actuators to transition to flush circulation - // The valves are set to do flush drain and flush circulation - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + ++rinseCycleCounter; + if ( rinseCycleCounter < NUM_OF_RINSE_CYCLES ) + { + // Set the valves to flush R2 to R1 and drain R1 + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - stateTimerStart = getMSTimerCount(); + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - state = DG_FLUSH_STATE_FLUSH_CIRCULATION; - } - else if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_LINE_TIMEOUT_MS ) ) - { - alarmDetectedPendingTrigger = ALARM_ID_DG_DRAIN_CIRCULATION_LINE_TIMEOUT; - // Could not reach to the defined drain line on time - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - } + // Set the reservoir status + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; + } + else + { + // Set the valves to drain R1 + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_OPEN ); - return state; -} + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); -/*********************************************************************//** - * @brief - * The handleFlushModeFlushCirculationState function handles the flush - * circulation state. Once the flush circulation time has elapsed, it - * transitions to the next state. - * @details Inputs: stateTimerStart - * @details Outputs: stateTimerStart - * @return next state of the flush state machine - *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ) -{ - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION; + // Turn off CP1 and CP2 + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - if ( TRUE == didTimeout( stateTimerStart, FLUSH_CIRCULATION_WAIT_TIME_MS ) ) - { - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + //Turn off UV reactors + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); - stateTimerStart = getMSTimerCount(); + // Set the reservoir status + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER; + isThisLastDrain = TRUE; + state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; + } } return state; -} -/*********************************************************************//** - * @brief - * The handleFlushModeFlushWithFreshWaterState function handles the - * flush with fresh water state. It runs the circulation state with fresh - * water for the defined period of time. - * @details Inputs: stateTimerStart - * @details Outputs: none - * @return next state of the flush state machine - *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushWithFreshWaterState( void ) -{ - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER; - - if ( TRUE == didTimeout( stateTimerStart, FLUSH_WITH_FRESH_WATER_WAIT_TIME_MS ) ) - { - deenergizeActuators(); - flushUIState = FLUSH_UI_STATE_COMPLETE; - state = DG_FLUSH_STATE_COMPLETE; - } - - return state; } /*********************************************************************//** * @brief - * The handleFlushModeCancelBasicPathState function handles the flush - * cancel mode basic path state. The state sets the state to complete and - * raises an alarm. + * The handleChemicalDisinfectFlushCancelModeBasicPathState function handles the + * chemical disinfect cancel mode basic path state. The state sets the state + * to complete and raises an alarm. * @details Inputs: none - * @details Outputs: none - * @return next state of the flush state machine + * @details Outputs: cancellationMode, ChemDisinfectFlushUIState + * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - // Once the fault alarm is raised, the DG Software will - // deenergize all the actuators - failFlushMode(); - flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + // Set the cancellation mode + cancellationMode = CANCELLATION_MODE_BASIC; + + failChemicalDisinfectFlush(); + return state; } /*********************************************************************//** * @brief - * The handleFlushModeCancelWaterPathState function handles the flush mode - * cancel water path state. The state drains the 2 reservoirs. If the drain - * times out, it transitions to basic cancellation path. - * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer, - * hasWaterCancellationBeenSet - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer, - * hasWaterCancellationBeenSet - * @return next state of the flush state machine + * The handleChemicalDisinfectFlushCancelModeWaterPathState function handles the + * chemical disinfect flush cancel mode cold water path state. + * @details Inputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer + * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer, + * ChemDisinfectFlushUIState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - if ( FALSE == hasWaterCancellationBeenSet ) + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + + if ( CANCELLATION_MODE_NONE == cancellationMode ) { // Stop all the actuators first then decide who should run next deenergizeActuators(); - // Set the actuators - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_OPEN ); + cancellationMode = CANCELLATION_MODE_WATER; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Set both reservoirs to be considered as full - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - - // Water cancellation path was set - hasWaterCancellationBeenSet = TRUE; - - // The drain is set to start from reservoir 2 since all the actuators have been de-energized - // Start the drain pump + // The drain is set to start from reservoir 2 + setValveState( VRD2, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; - // Start the timer for drain timeout - stateTimerStart = getMSTimerCount(); + stateTimer = getMSTimerCount(); } // If reservoir 2 is empty, set to drain reservoir 1 if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { + // Set the drain valve to reservoir 1 setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); } } + // Could not drain reservoir 2. Transition to basic cancellation path else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; } // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) ) { - // If the cancellation water path cannot be done, go to basic cancellation path - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); + // If the cancellation water path cannot be done, got to basic cancellation path + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - setValveState( VRD2, VALVE_STATE_CLOSED ); - // Done with draining - signalDrainPumpHardStop(); - - // Raise the alarm - failFlushMode(); + failChemicalDisinfectFlush(); } + // Could not drain reservoir 1. Transition to basic cancellation path + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + } } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - } return state; } /*********************************************************************//** * @brief - * The handleFlushModeComplete function handles the complete state. + * The handleChemicalDisinfectFlushCompleteState function handles the chemical + * disinfect complete state. The state stops chemical disinfect and + * requests transition to mode standby. * @details Inputs: none - * @details Outputs: none - * @return next state of the flush state machine + * @details Outputs: ChemDisinfectFlushUIState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeComplete( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_COMPLETE; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; - stopDGFlush(); + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; + stopChemicalDisinfectFlush(); + return state; } /*********************************************************************//** * @brief - * The failFlushMode function sets the alarm that failed the flush mode. - * @details Inputs: alarm, prevHeatDisinfectState + * The failChemicalDisinfectFlush function sets the alarm that failed the + * chemical disinfect mode. + * @details Inputs: alarmDetectedPendingTrigger, prevChemDisinfectFlushState * @details Outputs: none * @return none *************************************************************************/ -static void failFlushMode( void ) +static void failChemicalDisinfectFlush( void ) { - SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevFlushState ) + SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevChemDisinfectFlushState ) } /*********************************************************************//** * @brief - * The getRsrvrFillStatus function checks whether the target reservoir is - * full or not. If the fill times out, the function sets the status to did - * not reach to target. - * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, flushState, - * prevFlushState - * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer + * The getRsrvrFillStatus function checks whether the target reservoir + * is full or not. If the fill times out, it sets the state machine to + * complete and exits the chemical disinfect mode. + * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, chemDisinfectFlushState + * @details Outputs: prevChemDisinfectFlushState * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param targetVol is the target fill volume - * @param timeout is the fill up time out that is checked against + * @param timeout is the fill up timeout * @return the status of the reservoirs during filling *************************************************************************/ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ) @@ -955,34 +948,28 @@ { volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) + } // Check the volume of the reservoir against the target volume if ( volume >= targetVol ) { if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) { - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check - if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_2 == r) ) - { - if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) - { - stateTimerStart = getMSTimerCount(); - } - } - else - { - stateTimerStart = getMSTimerCount(); - } + stateTimer = getMSTimerCount(); } } - else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) + else if ( TRUE == didTimeout( stateTimer, timeout ) ) { - // Failed to fill on time - prevFlushState = flushState; + // Failed to fill ontime. Update the previous chemical disinfect state and transition to basic cancellation + prevChemDisinfectFlushState = chemDisinfectFlushState; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -991,11 +978,10 @@ /*********************************************************************//** * @brief * The getRsrvrDrainStatus function returns the status of draining a - * reservoir. If the drain times out, it set the status to did not reach - * target. - * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer - * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer, - * prevFlushState + * reservoir. + * @details Inputs: stateTimer, chemDisinfectFlushState + * alarm + * @details Outputs: stateTimer, prevChemDisinfectFlushState, alarm * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param drainSteadyStateTimeout which is the time the reservoir's level * does not change and is steady state @@ -1008,7 +994,7 @@ DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; // If the drain parameters of the reservoir is not initialized, initialize them - if ( FALSE == haveDrainParamsBeenInit [ r ] ) + if ( FALSE == haveDrainParamsBeenInit[ r ] ) { initDrainParameters( r ); haveDrainParamsBeenInit[ r ] = TRUE; @@ -1018,84 +1004,162 @@ if ( TRUE == isDrainComplete ) { - if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_1 == r) ) - { - if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status) && ( 0 == getDrainPumpTargetRPM() ) ) - { - stateTimerStart = getMSTimerCount(); - } - } - else - { - stateTimerStart = getMSTimerCount(); - } - + // Set the state timer in case it needs to be used for another timeout check + stateTimer = getMSTimerCount(); haveDrainParamsBeenInit[ r ] = FALSE; - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; } - else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) + else if ( TRUE == didTimeout( stateTimer, timeout ) ) { - // Failed to drain on time - prevFlushState = flushState; - haveDrainParamsBeenInit [ r ] = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + // Failed to drain on time. Update the previous chemical disinfect state + prevChemDisinfectFlushState = chemDisinfectFlushState; + haveDrainParamsBeenInit[ r ] = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; } + /*********************************************************************//** * @brief - * The publishFlushData function publishes the flush mode data at the set - * interval. + * The publishChemicalDisinfectFlushData function publishes chemical disinfect + * flush data at the set interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ -static void publishFlushData( void ) + +static void publishChemicalDisinfectFlushData( void ) { - if ( ++dataPublishCounter >= FLUSH_DATA_PUB_INTERVAL ) + + + if ( ++dataPublishCounter >= CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ) { + MODE_FLUSH_DATA_T data; - data.flushState = (U32)flushState; - data.overallElapsedTime = calcTimeSince( overallFlushElapsedTimeStart ); - data.stateElapsedTime = calcTimeSince( stateTimerStart ); - data.drainLineVolume = flushLinesVolumeL; - data.flushUIState = (U32)flushUIState; + data.flushState = (U32)chemDisinfectFlushState; + data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimerStart ); + data.stateElapsedTime = calcTimeSince( stateTimer ); + data.drainLineVolume = 0; + data.flushUIState = (U32)chemDisinfectFlushUIState; broadcastData( MSG_ID_DG_FLUSH_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_FLUSH_DATA_T ) ); dataPublishCounter = 0; } + /* + MODE_CHEMICAL_DISINFECT_FLUSH_DATA_T data; + MODE_CHEMICAL_DISINFECT_UI_DATA_T uiData; + + data.chemDisinfectFlushState = (U32)chemDisinfectFlushState; + data.stateElapsedTime = calcTimeSince( stateTimer ); + data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimer ); + data.cancellationMode = (U32)cancellationMode; + + // General data publish channel + broadcastData( MSG_ID_DG_CHEM_DISINFECT_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_CHEMICAL_DISINFECT_FLUSH_DATA_T ) ); + + // Publish data to UI + broadcastData( MSG_ID_DG_CHEM_DISINFECT_TIME_DATA, COMM_BUFFER_OUT_CAN_DG_2_UI, (U08*)&uiData, sizeof( MODE_CHEMICAL_DISINFECT_FLUSH_UI_DATA_T ) ); + + dataPublishCounter = 0; + }*/ } + /*********************************************************************//** * @brief - * The monitorModeFlush 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: prevFlushState, flushState, alarmDetectedPendingTrigger + * The monitorModeChemicalDisinfectFlush 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. It also monitors inlet water conditions. + * @details Inputs: chemDisinfectState + * @details Outputs: prevChemDisinfectFlushState, chemDisinfectState, + * alarmDetectedPendingTrigger * @return: none *************************************************************************/ -static void monitorModeFlush( void ) +static void monitorModeChemicalDisinfectFlush( void ) { + BOOL hasConductivityFailed = TRUE; + #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif { + // If either the dialysate cap or the concentrate cap is open during any state, alarm if ( ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) { + // Set the variables to fail and go to cancel water path. Set the pending alarm to no alarm so the cancel water path // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function - U32 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); - prevFlushState = flushState; - flushState = DG_FLUSH_STATE_CANCEL_WATER_PATH; + U32 ConcCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); + U32 DialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); + prevChemDisinfectFlushState = chemDisinfectFlushState; + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; } } + + // In all states, check inlet temperature, inlet pressure, and inlet conductivity. + haveInletWaterChecksPassed= TRUE; + hasConductivityFailed = ( ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) >= MAX_INLET_CONDUCTIVITY_US_PER_CM ) || + ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MIN_INLET_CONDUCTIVITY_US_PER_CM ) ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) + { + hasConductivityFailed = FALSE; + } +#endif + if ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) < MIN_INLET_TEMPERATURE_C || + hasConductivityFailed || + getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) < MIN_INLET_PRESSURE_PSI) + { + // Inlet check failed, alarm unless in the start, drain, or flush drain states + haveInletWaterChecksPassed= FALSE; // set flag for flush drain state + switch( chemDisinfectFlushState ) + { + case DG_CHEM_DISINFECT_FLUSH_STATE_START: + case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1: + case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2: + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN: + break; + + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE: + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF: + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1: + case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2: + prevChemDisinfectFlushState = chemDisinfectFlushState; + alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_NEW_WAT; + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + break; + } + } + + } + +/*********************************************************************//** + * @brief + * The writeDisinfectDataToNV function writes the disinfection data to the + * non-volatile memory. + * @details Inputs: disinfectNVOps + * @details Outputs: disinfectNVOps + * @return: none + *************************************************************************/ +static void writeDisinfectDataToNV( void ) +{ + ; ///< Boolean flag to indicate whether the disinfect flush status been written to NV or not. + BOOL ; + if ( FALSE == disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV ) + { + disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV = setDisinfectStatus( TRUE ); + } + + if ( FALSE == disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV ) + { + disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV = setLastDisinfectDate( USAGE_INFO_CHEMICAL_DISINFECT, getRTCTimestamp() ); + } } /**@}*/