Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r19fc8f015489be63932eed969d28329d123332e0 -r70ccc0b282f1dafcd1f6b95dd53f4efe2efd3b2b --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 19fc8f015489be63932eed969d28329d123332e0) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 70ccc0b282f1dafcd1f6b95dd53f4efe2efd3b2b) @@ -17,11 +17,13 @@ #include "AirTrap.h" #include "BloodFlow.h" +#include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "FPGA.h" #include "PresOccl.h" #include "SelfTests.h" +#include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" @@ -32,19 +34,29 @@ // ********** private definitions ********** -#define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. -#define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. +#define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. +#define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. -#define BLOOD_LEAK_SELF_TEST_SET 0x1 ///< Initiate blood leak self-test. -#define BLOOD_LEAK_NORMAL_OPERATION 0x0 ///< Return blood leak to normal operation. +#define BLOOD_LEAK_SELF_TEST_SET 0x1 ///< Initiate blood leak self-test. +#define BLOOD_LEAK_NORMAL_OPERATION 0x0 ///< Return blood leak to normal operation. -#define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. +#define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. -#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -50.0 ///< Arterial pressure low limit after running blood pump. -#define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 400 ///< Venous pressure high limit after running blood pump. +#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -50.0 ///< Arterial pressure low limit after running blood pump. +#define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 400 ///< Venous pressure high limit after running blood pump. -#define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). +#define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). +#define DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN 100 ///< Dialysate inlet pump flow rate during the first displacement in wet self-test. +#define DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 300 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. + +#define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100 ///< Target of first displacement volume in ml. +#define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 300 ///< Target of second displacement volume in ml. +#define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 5 ///< Tolerance on integrated volume in percentage. +#define WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G 1.5 ///< Tolerance in the load cell readings of the displacement in grams. +#define WET_SELF_TEST_DISPLACEMENT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Time to displace dialysate in wet self-test in ms. +#define RESERVOIR_SETTLE_TIME_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time allotted for reservoir to settle in ms. + /// No cartridge self-tests state machine. typedef enum No_Cart_Self_Tests_State { @@ -59,8 +71,8 @@ NO_CART_SELF_TESTS_DOOR_SWITCH_STATE, ///< No cartridge door switch self-test state. NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE, ///< No cartridge home valves and pumps self-test state. NO_CART_SELF_TESTS_HOME_IDLE_STATE, ///< Wait for valves and pumps finish homing state. - NO_CART_SELF_TESTS_STOPPED, ///< No cart self-test stopped state. - NO_CART_SELF_TESTS_COMPLETE, ///< No cartridge self-test complete state. + NO_CART_SELF_TESTS_STOPPED_STATE, ///< No cart self-test stopped state. + NO_CART_SELF_TESTS_COMPLETE_STATE, ///< No cartridge self-test complete state. NUM_OF_NO_CART_SELF_TESTS_STATES ///< Number of no cartridge self-tests states. } NO_CART_SELF_TESTS_STATE_T; @@ -75,8 +87,8 @@ DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE, ///< Pressure sensors dry self-test setup valves and pump state. DRY_SELF_TESTS_PRESSURE_SENSORS_STATE, ///< Pressure sensors verify pressure readings state. DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE, ///< Preassure sensors verify normal pressure readings state. - DRY_SELF_TESTS_STOPPED, ///< Dry self-test stopped state. - DRY_SELF_TESTS_COMPLETE, ///< Dry self-test complete state. + DRY_SELF_TESTS_STOPPED_STATE, ///< Dry self-test stopped state. + DRY_SELF_TESTS_COMPLETE_STATE, ///< Dry self-test complete state. NUM_OF_DRY_SELF_TESTS_STATES ///< Number of dry self-tests states. } DRY_SELF_TESTS_STATE_T; @@ -85,8 +97,13 @@ { WET_SELF_TESTS_START_STATE = 0, ///< Wet self-tests starting state. WET_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors wet self-tests state. - WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE, ///< Fill reservoir 1 with 100 mL of dialysate from reservoir 2 start state. - WET_SELF_TESTS_COMPLETE, ///< Wet self-test complete state. + WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE, ///< Setup valve and start dialysate pump for first displacement. + WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE, ///< Fill reservoir 2 with 100 mL of dialysate from reservoir 1 state. + WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE, ///< After first displacement completed verify state. + WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE, ///< Setup valve and start dialysate pump for second displacement. + WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE, ///< Fill reservoir 1 with 300 mL of dialysate from reservoir 2 state. + WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE, ///< After first displacement completed verify state. + WET_SELF_TESTS_COMPLETE_STATE, ///< Wet self-test complete state. NUM_OF_WET_SELF_TESTS_STATES ///< Number of wet self-tests states. } WET_SELF_TESTS_STATE_T; @@ -105,6 +122,10 @@ static BOOL wetSelfTestsResult; ///< Result of wet self-tests. static WET_SELF_TESTS_STATE_T currentWetSelfTestsState; ///< Current state of the wet self-tests state machine. +static U32 settleStartTime; ///< Wait for reservoir to settle start time. +static U32 displacementStartTime; ///< Dialysate displacement starting time. +static F32 fmdIntegratedVolume; ///< FMD integrated volume over displacement time. +static F32 reservoirVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Hold the current volume of all reservoirs. static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. static BOOL selfTestsStopRequested; ///< Flag indicates alarm requesting to stop self-test. @@ -129,6 +150,14 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( SELF_TEST_STATUS_T *result ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( SELF_TEST_STATUS_T *result ); + /*********************************************************************//** * @brief * The initSelfTests function initializes the SelfTests module. @@ -190,9 +219,9 @@ void transitionToNoCartSelfTests( void ) { noCartSelfTestsResult = FALSE; - hasPumpsStarted = FALSE; currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; runPumpStartTime = 0; + hasPumpsStarted = FALSE; resetSelfTestsFlags(); } @@ -264,15 +293,15 @@ case NO_CART_SELF_TESTS_HOME_IDLE_STATE: if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE; + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE_STATE; } break; - case NO_CART_SELF_TESTS_STOPPED: + case NO_CART_SELF_TESTS_STOPPED_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestStoppedState(); break; - case NO_CART_SELF_TESTS_COMPLETE: + case NO_CART_SELF_TESTS_COMPLETE_STATE: noCartSelfTestsResult = TRUE; break; @@ -290,7 +319,7 @@ if ( SELF_TEST_STATUS_FAILED == result ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_NO_CART_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); } } @@ -318,6 +347,9 @@ { drySelfTestsResult = FALSE; currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; + pressureSelfTestBloodPumpRunStartTime = 0; + previousNormalArterialPressure = 0.0; + previousNormalVenousPressure = 0.0; resetSelfTestsFlags(); } @@ -338,7 +370,7 @@ { case DRY_SELF_TESTS_START_STATE: #ifdef SKIP_SELF_TESTS - currentDrySelfTestsState = DRY_SELF_TESTS_COMPLETE; + currentDrySelfTestsState = DRY_SELF_TESTS_COMPLETE_STATE; #else currentDrySelfTestsState = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; #endif @@ -375,11 +407,11 @@ currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalState( &result ); break; - case DRY_SELF_TESTS_STOPPED: + case DRY_SELF_TESTS_STOPPED_STATE: currentDrySelfTestsState = handleDrySelfTestStoppedState(); break; - case DRY_SELF_TESTS_COMPLETE: + case DRY_SELF_TESTS_COMPLETE_STATE: drySelfTestsResult = TRUE; break; @@ -397,7 +429,7 @@ if ( SELF_TEST_STATUS_FAILED == result ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentDrySelfTestsState ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_DRY_SELF_TEST_FAILURE, currentDrySelfTestsState ); } } @@ -425,6 +457,9 @@ { wetSelfTestsResult = FALSE; currentWetSelfTestsState = WET_SELF_TESTS_START_STATE; + settleStartTime = 0; + displacementStartTime = 0; + fmdIntegratedVolume = 0.0; resetSelfTestsFlags(); } @@ -445,45 +480,53 @@ { case WET_SELF_TESTS_START_STATE: #ifdef SKIP_SELF_TESTS - currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; + currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE_STATE; #else currentWetSelfTestsState = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; #endif break; case WET_SELF_TESTS_BUBBLE_DETECTOR_STATE: - { - BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); - BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); + currentWetSelfTestsState = handleWetSelfTestBubbleDetectorsState( &result ); + break; - if ( ( FALSE == isADADetectedAir ) && ( FALSE == isADADetectedAir ) ) - { - currentWetSelfTestsState = WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } - } + case WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementSetupState(); break; - case WET_SELF_TESTS_START_100_ML_DISPLACEMENT_STATE: - currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; + case WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementState(); break; - case WET_SELF_TESTS_COMPLETE: + case WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE: + currentWetSelfTestsState = handleWetSelfTestFirstDisplacementVerifyState( &result ); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementSetupState(); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementState(); + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE: + currentWetSelfTestsState = handleWetSelfTestSecondDisplacementVerifyState( &result ); + break; + + case WET_SELF_TESTS_COMPLETE_STATE: wetSelfTestsResult = TRUE; break; default: - currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE; + currentWetSelfTestsState = WET_SELF_TESTS_START_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_WET_SELF_TEST_STATE, (U32)currentWetSelfTestsState ); break; } if ( SELF_TEST_STATUS_FAILED == result ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_SELF_TEST_FAILURE, currentWetSelfTestsState ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_WET_SELF_TEST_FAILURE, currentWetSelfTestsState ); } } @@ -515,7 +558,7 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_STOPPED; + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_STOPPED_STATE; selfTestsStopRequested = FALSE; } } @@ -608,6 +651,7 @@ * The handleNoCartSelfTestLeakDetectorsState function verify leak detectors status. * @details Inputs: none * @details Outputs: none + * @param result self-test result * @return the next state of no cartridge self-tests state machine *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ) @@ -637,7 +681,7 @@ *************************************************************************/ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ) { - NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_STOPPED; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_STOPPED_STATE; if ( TRUE == selfTestsResumeRequested ) { @@ -663,7 +707,7 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); - currentDrySelfTestsState = DRY_SELF_TESTS_STOPPED; + currentDrySelfTestsState = DRY_SELF_TESTS_STOPPED_STATE; selfTestsStopRequested = FALSE; } } @@ -770,6 +814,7 @@ * pressure sensors and verify they are in correct range. * @details Inputs: none * @details Outputs: none + * @param result self-test result * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ) @@ -802,6 +847,7 @@ * pressure sensors after returning to normal state. * @details Inputs: none * @details Outputs: none + * @param result self-test result * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ) @@ -813,7 +859,7 @@ if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) { - state = DRY_SELF_TESTS_COMPLETE; + state = DRY_SELF_TESTS_COMPLETE_STATE; } else { @@ -833,7 +879,7 @@ *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ) { - DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED; + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED_STATE; if ( TRUE == selfTestsResumeRequested ) { @@ -843,4 +889,209 @@ return state; } +/*********************************************************************//** + * @brief + * The handleWetSelfTestBubbleDetectorsState function handles the wet self-test + * for bubble detectors. + * @details Inputs: Arterial and venous air bubble status + * @details Outputs: Test pass/fail + * @param result self-test result + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + + BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); + BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); + + if ( ( FALSE == isADADetectedAir ) && ( FALSE == isADADetectedAir ) ) + { + settleStartTime = getMSTimerCount(); + currentWetSelfTestsState = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + } + else + { + *result = SELF_TEST_STATUS_FAILED; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestStartFirstDisplacementState function setups the valves + * and pumps to start first dialysate displacement. + * @details Inputs: settleStartTime + * @details Outputs: setup valves and pump, reservoirVolume[] + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + + if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + { + reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + // TODO: send command to DG to change VRi, VRo valve setting + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0; + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestFirstDisplacementState function handles the first + * dialysate displacement from reservoir 1 to reservoir 2. + * @details Inputs: firstDisplacementStartTime, measured dialysate flow rate + * @details Outputs: integrated volume + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + + fmdIntegratedVolume += getMeasuredDialInFlowRate(); + + if ( TRUE == didTimeout( displacementStartTime, WET_SELF_TEST_DISPLACEMENT_TIME_MS ) ) + { + signalDialInPumpHardStop(); + fmdIntegratedVolume = ( ( fmdIntegratedVolume * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); + + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestFirstDisplacementVerifyState function checks the load cell + * readings and FMD integrated volume after the first dialysate displacement. + * @details Inputs: settleStartTime, reservoirVolume[], reservoirs' weights + * @details Outputs: verify correctness of dialysate flow meter and load cell + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( SELF_TEST_STATUS_T *result ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; + + if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + { + F32 const resOneDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ] ); + F32 const resTwoDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ] ); + F32 const integratedVolumeToTargetPercent = fabs( fmdIntegratedVolume - WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ) / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML; + + if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && + ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE ) ) + { + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + } + else + { + *result = SELF_TEST_STATUS_FAILED; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementSetupState function setups the valves + * and pumps to start second dialysate displacement. + * @details Inputs: settleStartTime + * @details Outputs: setup valves and pump, reservoirVolume[] + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + + if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + { + reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + // TODO: send command to DG to change VRi, VRo valve setting + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0; + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementState function handles the first + * dialysate displacement from reservoir 2 to reservoir 1. + * @details Inputs: firstDisplacementStartTime, measured dialysate flow rate + * @details Outputs: integrated volume + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + + fmdIntegratedVolume += getMeasuredDialInFlowRate(); + + if ( TRUE == didTimeout( displacementStartTime, WET_SELF_TEST_DISPLACEMENT_TIME_MS ) ) + { + signalDialInPumpHardStop(); + fmdIntegratedVolume = ( ( fmdIntegratedVolume * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); + + settleStartTime = getMSTimerCount(); + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSecondDisplacementVerifyState function checks the load cell + * readings and FMD integrated volume after the second dialysate displacement. + * @details Inputs: settleStartTime, reservoirVolume[], reservoirs' weights + * @details Outputs: verify correctness of dialysate flow meter and load cell + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( SELF_TEST_STATUS_T *result ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; + + if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + { + F32 const resOneDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ] ); + F32 const resTwoDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ] ); + F32 const integratedVolumeToTargetPercent = fabs( fmdIntegratedVolume - WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ) / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML; + + if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && + ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE ) ) + { + state = WET_SELF_TESTS_COMPLETE_STATE; + } + else + { + *result = SELF_TEST_STATUS_FAILED; + } + } + + return state; +} + /**@}*/