Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r269d7db0f5a8e7b1a14210e316e9823ec3ea9e3d -rca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 269d7db0f5a8e7b1a14210e316e9823ec3ea9e3d) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision ca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Dara Navaei -* @date (last) 08-May-2023 +* @author (last) Sean Nash +* @date (last) 17-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 08-Dec-2020 @@ -47,8 +47,8 @@ #define BLOOD_PUMP_FAST_FLOW_RATE_CIRC_BLOOD_CIRCUIT_ML_MIN 300 ///< Blood pump fast flow rate during prime recirculate blood circuit state. #define BLOOD_PUMP_FLOW_RATE_SALINE_DIALYZER_ML_MIN 300 ///< Blood pump flow rate during prime the saline dialyzer dialysate state. #define DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN 300 ///< Dialysate pump flow rate during priming fluid path. -#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump flow rate during priming fluid path. -#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 225 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. +#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump faster flow rate during priming fluid path. +#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 240 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. #define DIALYSATE_DIALYZER_TUBE_VOLUME_ML 115 ///< This total tube volume is used to calculate the Dpi & Dpo time out in the dialysate dialyzer state. #define DIALYSATE_DIALYZER_BYPASS_TUBE_VOLUME_ML 75 ///< This volume is used to calculate the DPi pump time out in the dialyzer bypass state. @@ -57,12 +57,15 @@ #define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. #define PURGE_AIR_TIME_OUT_COUNT ( 240 * MS_PER_SECOND ) ///< Time period count for purge air time out. -#define PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for prime saline dialyzer time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 8 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. -#define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 55 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. -#define STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ( 25 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during bypass dialysate prime state. +#define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 90 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. +#define STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ( 62 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during bypass dialysate prime state. +#define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG 50.0F ///< +/- offset from start pressure that defines a range to keep PBo in during dialysate dialyzer prime state. +#define DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN 1 ///< DPo rate step to maintain pressure during dialysate dialyzer prime state. #define VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum venous pressure reading (in mmHg) for bubble clear. #define BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS ( 10 * MS_PER_SECOND ) ///< Time in msec to wait for initial bubble clear pressure. @@ -133,17 +136,21 @@ static U32 primeSalineDialyzerStartTime; ///< Starting time of priming saline dialyzer circuit. static U32 primeSalineDialyzerBubbleClearStartTime; ///< Starting time of priming saline dialyzer bubble clear. static U32 primeDialysateDialyzerStartTime; ///< Starting time of priming dialysate dialyzer circuit. +static F32 primeDialysateDialyzerStartVenPres; ///< Starting venous pressure (mmHg) for dialysate dialyzer prime state. +static U32 primeDialysateDialyzerDPoRate; ///< Record of last given DPo target rate for dialysate dialyzer prime state. static U32 primeDialysateBypassStartTime; ///< Starting time of priming dialysate bypass circuit. static U32 steadyVolumeSamplingStartTime; ///< Load cell steady volume sampling interval starting time. static F32 minimumReservoirVolume; ///< Minimum reservoir volume in mL. static U32 steadyVolumeCount; ///< Use to keep track the number of dVolume/dt < Threshold +static BOOL bubbleClearEnded; ///< Bubble clear ended boolean signal. // ********** private function prototypes ********** static void resetPrimeFlags(); static void setupForPrimePause( void ); static void broadcastPrimingStatus( void ); static void purgeAirValvesBloodPumpControl( void ); +static void handlePrimeBubbleClear( void ); static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeWaitForUserStartState( void ); static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineDialyzerSetupState( void ); @@ -173,26 +180,27 @@ primeStartTime = 0; primePauseStartTime = 0; primeStatusBroadcastTimerCounter = 0; + bubbleClearEnded = FALSE; } /*********************************************************************//** * @brief * The transitionToPrime function prepares for transition to prime sub-mode. * This function will reset anything required before the start of priming sequence. * @details Inputs: none - * @details Outputs: currentPrimeState, wetSelfTestsResult, primeStartReqReceived, reservoirFilledStatus[] + * @details Outputs: currentPrimeState, wetSelfTestsResult, primeStartReqReceived, + * reservoirFilledStatus[], bubbleClearEnded, primeDialyzerBubbleClearState * @return none *************************************************************************/ void transitionToPrime( void ) { primeStartTime = getMSTimerCount(); primeFirstPurgePass = TRUE; - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - + setCurrentSubState( (U32)currentPrimeState ); doorClosedRequired( TRUE, TRUE ); // Pumps should be off @@ -210,6 +218,17 @@ setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); resetPrimeFlags(); + + if ( getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) != TRUE ) + { + bubbleClearEnded = FALSE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; + } + else + { // if using a wet cartridge, we do not want to do the bubble clearing of dialyzer in blood side prime states + bubbleClearEnded = TRUE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_COMPLETE_STATE; + } } /*********************************************************************//** @@ -288,6 +307,7 @@ if ( priorSubState != currentPrimeState ) { + setCurrentSubState( (U32)currentPrimeState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentPrimeState ); } @@ -416,15 +436,20 @@ *************************************************************************/ static void broadcastPrimingStatus( void ) { - U32 const elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + U32 elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + // If the elapsed time is greater than the maximum prime time, it is capped to max prime time so the remaining time + // is a large number + elapsedPrimeTimeInSecs = CAP( elapsedPrimeTimeInSecs, MAX_PRIME_TIME ); + // timeout alarm that used to trigger when max prime time elapsed was removed. if ( ++primeStatusBroadcastTimerCounter >= PRIME_DATA_PUB_INTERVAL ) { PRIMING_DATA_PAYLOAD_T primeData; - primeData.totalTime = MAX_PRIME_TIME; - primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + primeData.totalTime = MAX_PRIME_TIME; + primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + broadcastData( MSG_ID_HD_PRIMING_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&primeData, sizeof( PRIMING_DATA_PAYLOAD_T ) ); primeStatusBroadcastTimerCounter = 0; } @@ -460,7 +485,76 @@ /*********************************************************************//** * @brief - * The handlePrimeSalineSetupState function checks user's request to start + * The handlePrimeBubbleClear function handles bubble clear pressurizing + * of dialyzer. + * @details Inputs: air trap levels, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime + * @details Outputs: control valves to pressurize, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime + * @return none + *************************************************************************/ +static void handlePrimeBubbleClear( void ) +{ + U32 timeout; + + switch ( primeDialyzerBubbleClearState ) + { + case PRIME_BUBBLE_CLEAR_READY_STATE: + case PRIME_BUBBLE_CLEAR_FLOW_STATE: + if ( PRIME_BUBBLE_CLEAR_READY_STATE == primeDialyzerBubbleClearState ) + { + timeout = BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS; + } + else + { + timeout = BUBBLE_CLEAR_WAIT_TIME_MS; + } + + if ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, timeout ) ) + { + // Close valve to create pressure to clear Dialyzer bubbles + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + if ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_PRESSURE_STATE; + } + } + break; + + case PRIME_BUBBLE_CLEAR_PRESSURE_STATE: + case PRIME_BUBBLE_CLEAR_VENT_STATE: + if ( ( getMeasuredVenousPressure() > VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ) || + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_MAX_TIME_MS ) ) ) + { + // Pressure max reached. or timeout, release pressure + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + bubbleClearEnded = TRUE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_VENT_STATE; + } + else if ( ( TRUE == bubbleClearEnded ) && + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_OPEN ); + bubbleClearEnded = FALSE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_FLOW_STATE; + } + break; + + case PRIME_BUBBLE_CLEAR_COMPLETE_STATE: + default: + // do nothing + break; + + } // end switch +} + +/*********************************************************************//** + * @brief + * The handlePrimeWaitForUserStartState function checks user's request to start * priming. * @details Inputs: primeStartReqReceived * @details Outputs: control valves to purge air @@ -472,6 +566,8 @@ // Keep updating start time until the user requested priming primeStartTime = getMSTimerCount(); + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) @@ -515,8 +611,12 @@ purgeAirValvesBloodPumpControl(); purgeAirTimeOutStartTime = getMSTimerCount(); primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; + if ( getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) != TRUE ) + { + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; + } + if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForPrimePause(); @@ -528,74 +628,6 @@ /*********************************************************************//** * @brief - * The handlePrimeBubbleClear function handles bubble clear pressurizing - * of dialyzer. - * @details Inputs: air trap levels, primeDialyzerBubbleClearState, primeSalineDialyzerBubbleClearStartTime - * @details Outputs: control valves to pressurize, primeDialyzerBubbleClearState, primeSalineDialyzerBubbleClearStartTime - * @return none - *************************************************************************/ -static void handlePrimeBubbleClear( void ) -{ - static BOOL bubble_clear_ended = FALSE; - U32 timeout; - - switch ( primeDialyzerBubbleClearState ) - { - case PRIME_BUBBLE_CLEAR_READY_STATE: - case PRIME_BUBBLE_CLEAR_FLOW_STATE: - if ( PRIME_BUBBLE_CLEAR_READY_STATE == primeDialyzerBubbleClearState ) - { - timeout = BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS; - } - else - { - timeout = BUBBLE_CLEAR_WAIT_TIME_MS; - } - - if ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, timeout ) ) - { - // Close valve to create pressure to clear Dialyzer bubbles - primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - if ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) - { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValveAirTrap( STATE_CLOSED ); - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_PRESSURE_STATE; - } - } - break; - - case PRIME_BUBBLE_CLEAR_PRESSURE_STATE: - case PRIME_BUBBLE_CLEAR_VENT_STATE: - if ( ( getMeasuredVenousPressure() > VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ) || - ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_MAX_TIME_MS ) ) ) - { - // Pressure max reached. or timeout, release pressure - setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); - primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - bubble_clear_ended = TRUE; - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_VENT_STATE; - } - else if ( ( TRUE == bubble_clear_ended ) && - ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) - { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValveAirTrap( STATE_OPEN ); - bubble_clear_ended = FALSE; - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_FLOW_STATE; - } - break; - - case PRIME_BUBBLE_CLEAR_COMPLETE_STATE: - default: - // do nothing - break; - - } // end switch -} - -/*********************************************************************//** - * @brief * The handlePrimePurgeAirState function checks for air trap level and moves * to blood circuit circulation state if fluid is detected at upper sensor. * @details Inputs: air trap levels, primeFirstPurgePass, purgeAirTimeOutStartTime @@ -703,13 +735,15 @@ signalBloodPumpHardStop(); setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( DPO_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + primeDialysateDialyzerDPoRate = DPO_PUMP_PRIME_FLOW_RATE_ML_MIN; // Calculate the time out value that must passed prior to checking for the steady state volume in the reservoir - primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); - minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - steadyVolumeCount = 0; - steadyVolumeSamplingStartTime = getMSTimerCount(); - primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); + minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + steadyVolumeCount = 0; + steadyVolumeSamplingStartTime = getMSTimerCount(); + primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerStartVenPres = getFilteredVenousPressure(); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) @@ -739,8 +773,10 @@ * @brief * The handlePrimeDialysateDialyzerState function handles priming for * dialysate dialyzer fluid path. - * @details Inputs: reservoir 1 filtered weight - * @details Outputs: primed dialysate dialyzer fluid path + * @details Inputs: reservoir 1 filtered weight, minimumReservoirVolume, + * steadyVolumeCount + * @details Outputs: primed dialysate dialyzer fluid path, minimumReservoirVolume, + * steadyVolumeCount * @return current state *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ) @@ -752,9 +788,9 @@ { if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { - F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + F32 currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -763,15 +799,30 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; // required 10 seconds continuous steady volume to transition to next state } - - steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next dVolume/dt check + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } } } - else + + // Adjust DPo speed to maintain venous pressure if necessary (re-using 1 sec steady volume timer to do this @ 1Hz) + if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { + F32 venPres = getFilteredVenousPressure(); + + if ( venPres > ( primeDialysateDialyzerStartVenPres + PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate += DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + else if ( venPres < ( primeDialysateDialyzerStartVenPres - PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate -= DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } steadyVolumeSamplingStartTime = getMSTimerCount(); } @@ -841,11 +892,6 @@ { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; } - // TODO: Rework alarm and timeout logic here. PRIME_SALINE_DIALYZER_TIME_OUT_COUNT may not be reached. - if ( TRUE == didTimeout( primeSalineDialyzerStartTime, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_SALINE_DIALYZER_TIME_OUT, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ); // Trigger HD prime saline dialyzer time out alarm. - } if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -917,7 +963,7 @@ { F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -927,9 +973,12 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; } + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next 1 second iteration } @@ -974,12 +1023,14 @@ if ( TRUE == isWetSelfTestsPassed() ) { + setCurrent4thLevelState( NO_SUB_STATE ); state = HD_PRIME_COMPLETE; } else if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForPrimePause(); state = HD_PRIME_PAUSE; + setCurrent4thLevelState( NO_SUB_STATE ); } return state;