Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -ra13e66c2bfd38ac3548b1c341dfd46f0c8db4292 -r8b2fa02992f4c8b10071a331a48e2b02ea07ef50 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision a13e66c2bfd38ac3548b1c341dfd46f0c8db4292) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 8b2fa02992f4c8b10071a331a48e2b02ea07ef50) @@ -7,8 +7,8 @@ * * @file SelfTests.c * -* @author (last) Sean Nash -* @date (last) 12-Jul-2023 +* @author (last) Dara Navaei +* @date (last) 13-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 28-Jan-2021 @@ -91,6 +91,8 @@ #define PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG 10.0F ///< Prior to dry pressure leak test, arterial and venous pressure sensors should read zero +/- this tolerance. #define MAX_EMPTY_RESERVOIR_WEIGHT_G 15.0F ///< Maximum reservoir weight to be considered empty for cartridge pressure leak test. +#define BLOOD_LEAK_DETECTOR_DEBUBBLE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Blood leak detector debubble timeout in milliseconds. + // ********** private data ********** static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; ///< Current state of the no cartridge self-tests state machine. @@ -115,6 +117,7 @@ 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 WET_SELF_TESTS_STATE_T checkpointWetSelfTestsState; ///< Checkpoint 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. @@ -125,6 +128,7 @@ static U32 selfTestStartTime; ///< Starting time of self-test (in ms). static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. +static U32 bloodLeakDebubbleStartTimeMS; ///< Blood leak detector debubble start time in milliseconds. static BOOL useHeparin; ///< Flag indicates the user of heparin. static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. @@ -164,6 +168,7 @@ static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorDebubbleState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); @@ -577,12 +582,14 @@ { wetSelfTestsResult = FALSE; currentWetSelfTestsState = WET_SELF_TESTS_START_STATE; + checkpointWetSelfTestsState = WET_SELF_TESTS_START_STATE; settleStartTime = 0; displacementStartTime = 0; fmdIntegratedVolume = 0.0; isValvesSettingSent = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); + bloodLeakDebubbleStartTimeMS = getMSTimerCount(); // Pumps should be off signalBloodPumpHardStop(); @@ -638,6 +645,10 @@ currentWetSelfTestsState = handleWetSelfTestPrimeCheckState(); break; + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE: + currentWetSelfTestsState = handleWetSelfTestBloodLeakDetectorDebubbleState(); + break; + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE: currentWetSelfTestsState = handleWetSelfTestBloodLeakDetectorState(); break; @@ -1593,7 +1604,7 @@ * The handleWetSelfTestSetupState function setup for bubble self-test * check. * @details Inputs: none - * @details Outputs: bubble detector self-test requested + * @details Outputs: bubble detector self-test requested, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ) @@ -1604,6 +1615,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_BUBBLE_CHECK_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1616,7 +1628,7 @@ * The handleWetSelfTestBubblesState function waiting for air bubble detectors * self-tests to finish. * @details Inputs: bubbleSelfTestStatus - * @details Outputs: none + * @details Outputs: checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ) @@ -1630,6 +1642,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_BUBBLE_CHECK_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1642,7 +1655,7 @@ * The handleWetSelfTestPrimeCheckState function checks arterial and venous * lines to make sure they are primed. * @details Inputs: Arterial and venous bubble detectors status - * @details Outputs: Test pass/fail + * @details Outputs: Test pass/fail, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ) @@ -1656,19 +1669,6 @@ { state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; } - else - { -#ifndef _RELEASE_ - if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) ) - { - state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; - } - else -#endif - { - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); - } - } } else { @@ -1677,6 +1677,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_PRIME_CHECK_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1686,25 +1687,83 @@ /*********************************************************************//** * @brief + * The handleWetSelfTestBloodLeakDetectorDebubbleState function runs the + * dialin pump in bypass mode to remove the potential bubbles from the + * blood leak detector prior to command another zero sequence. + * @details Inputs: bloodLeakDebubbleStartTimeMS + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorDebubbleState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE; + + if ( TRUE == didTimeout( bloodLeakDebubbleStartTimeMS, BLOOD_LEAK_DETECTOR_DEBUBBLE_TIMEOUT_MS ) ) + { + signalDialInPumpHardStop(); + + if ( getMeasuredDialInFlowRate() <= NEARLY_ZERO ) + { + if ( TRUE == zeroBloodLeak() ) + { + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + } + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleWetSelfTestBloodLeakDetectorState function handles zeroing and * self-test for blood leak detector. * @details Inputs: none - * @details Outputs: next self-test state + * @details Outputs: bloodLeakDebubbleStartTimeMS, settleStartTime, + * isValvesSettingSent, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ) { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + SELF_TEST_STATUS_T status = getBloodLeakSelfTestStatus(); - if ( SELF_TEST_STATUS_PASSED == getBloodLeakSelfTestStatus() ) + if ( SELF_TEST_STATUS_PASSED == status ) { settleStartTime = getMSTimerCount(); isValvesSettingSent = FALSE; state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; } + else if ( SELF_TEST_STATUS_FAILED == status ) + { + if ( TRUE == hasBloodLeakZeroSequenceFailed() ) + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); + } + } + else + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + bloodLeakDebubbleStartTimeMS = getMSTimerCount(); + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE; + } + } if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1717,7 +1776,7 @@ * The handleWetSelfTestStartFirstDisplacementState function setups the valves * and pumps to start first dialysate displacement. * @details Inputs: settleStartTime, isValvesSettingSent - * @details Outputs: isValvesSettingSent + * @details Outputs: isValvesSettingSent, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ) @@ -1750,6 +1809,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1762,7 +1822,7 @@ * The handleWetSelfTestFirstDisplacementState function handles the first * dialysate displacement from reservoir 1 to reservoir 2. * @details Inputs: displacementStartTime, fmdIntegratedVolume, settleStartTime - * @details Outputs: settleStartTime, displacementStartTime + * @details Outputs: settleStartTime, displacementStartTime, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ) @@ -1795,6 +1855,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1807,7 +1868,7 @@ * The handleWetSelfTestFirstDisplacementVerifyState function checks the load cell * readings and FMD integrated volume after the first dialysate displacement. * @details Inputs: settleStartTime, fmdIntegratedVolume - * @details Outputs: none + * @details Outputs: checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( void ) @@ -1857,6 +1918,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1869,7 +1931,7 @@ * The handleWetSelfTestSecondDisplacementSetupState function setups the valves * and pumps to start second dialysate displacement. * @details Inputs: settleStartTime, isValvesSettingSent - * @details Outputs: isValvesSettingSent + * @details Outputs: isValvesSettingSent, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ) @@ -1902,6 +1964,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1914,7 +1977,7 @@ * The handleWetSelfTestSecondDisplacementState function handles the first * dialysate displacement from reservoir 2 to reservoir 1. * @details Inputs: displacementStartTime, fmdIntegratedVolume, settleStartTime - * @details Outputs: displacementStartTime + * @details Outputs: displacementStartTime, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ) @@ -1945,6 +2008,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1957,7 +2021,7 @@ * 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 + * @details Outputs: verify correctness of dialysate flow meter and load cell, checkpointWetSelfTestsState * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( void ) @@ -2007,6 +2071,7 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + checkpointWetSelfTestsState = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; state = WET_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -2018,7 +2083,7 @@ * @brief * The handleWetSelfTestStoppedState function handles the stopped wet self-tests * operation. - * @details Inputs: selfTestsResumeRequested + * @details Inputs: selfTestsResumeRequested, checkpointWetSelfTestsState * @details Outputs: selfTestsResumeRequested, selfTestStartTime * @return the next state of wet self-tests state machine *************************************************************************/ @@ -2035,7 +2100,37 @@ selfTestStartTime = getMSTimerCount(); doorClosedRequired( TRUE, TRUE ); selfTestsResumeRequested = FALSE; - state = WET_SELF_TESTS_START_STATE; // TODO - should start state make sure there is sufficient/appropriate res volumes to restart wet self-tests? and if not, should it signal res mgmt to drain and fill R1 and R2 before resuming wet self-tests? + + switch( checkpointWetSelfTestsState ) + { + case WET_SELF_TESTS_BUBBLE_CHECK_SETUP_STATE: + case WET_SELF_TESTS_BUBBLE_CHECK_STATE: + case WET_SELF_TESTS_PRIME_CHECK_STATE: + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE: + state = WET_SELF_TESTS_START_STATE; + break; + + case WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE: + case WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE: + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + break; + + case WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE: + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE: + case WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE: + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + break; + + case WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE: + case WET_SELF_TESTS_COMPLETE_STATE: + state = WET_SELF_TESTS_COMPLETE_STATE; + + default: + state = WET_SELF_TESTS_START_STATE; + } } return state;