Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r2810cc8c4792de6df6232b57b4d2cfb01fe8e8ac -rca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 2810cc8c4792de6df6232b57b4d2cfb01fe8e8ac) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision ca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2) @@ -7,8 +7,8 @@ * * @file SelfTests.c * -* @author (last) Dara Navaei -* @date (last) 16-May-2023 +* @author (last) Sean Nash +* @date (last) 17-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. @@ -125,10 +127,12 @@ 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. +static BOOL cartridgeUsedTestRun; ///< Flag indicates whether the used cartridge test has been run. +static BOOL doorStateAfterCartridgeInstall; ///< Flag indicates state of front door for saline clamp check after cartridge installed. // ********** private function prototypes ********** @@ -163,6 +167,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 ); @@ -184,6 +189,7 @@ selfTestStartTime = 0; selfTestPreviousPublishDataTime = 0; syringeOcclusionDelayStartTime = 0; + doorStateAfterCartridgeInstall = TRUE; } /*********************************************************************//** @@ -378,21 +384,13 @@ if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; selfTestPreviousPublishDataTime = getMSTimerCount(); - if ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ) - { - SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; - - data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; - data.countdown = ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); - broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); - } - else - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CART_SELF_TEST_TIMEOUT, currentNoCartSelfTestsState ); - } + data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; + data.countdown = ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ? MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs : 0 ); + broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); } } @@ -413,8 +411,9 @@ * @brief * The transitionToDrySelfTests function resets anything required before * the start of dry self-tests. - * @details Inputs: none - * @details Outputs: Dry self-tests re-initialized. + * @details Inputs: front door state + * @details Outputs: Dry self-tests re-initialized, VBA state changed depending + * on front door state * @return none *************************************************************************/ void transitionToDrySelfTests() @@ -425,6 +424,7 @@ previousNormalArterialPressure = 0.0; previousNormalVenousPressure = 0.0; dryPressureTestsCompleted = FALSE; + cartridgeUsedTestRun = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); selfTestCartridgeSettleTime = getMSTimerCount(); @@ -440,7 +440,14 @@ setValveAirTrap( STATE_CLOSED ); setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + if ( STATE_CLOSED == getSwitchStatus( FRONT_DOOR ) ) + { + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + } + else + { + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + } setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); resetSelfTestsFlags(); @@ -580,6 +587,7 @@ isValvesSettingSent = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); + bloodLeakDebubbleStartTimeMS = getMSTimerCount(); // Pumps should be off signalBloodPumpHardStop(); @@ -635,6 +643,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; @@ -681,6 +693,7 @@ if ( priorSubState != currentWetSelfTestsState ) { + setCurrent4thLevelState( currentWetSelfTestsState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentWetSelfTestsState ); } } @@ -937,15 +950,15 @@ DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_START_STATE; OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + handleDoorCloseAfterCartridgeInsertion(); // want to pinch off saline once door closed after cartridge install + if ( STATE_CLOSED == pumpTrack ) { // Ensure occlusion sensor has time to settle after cartridge insertion before starting dry self-tests if ( TRUE == didTimeout( selfTestCartridgeSettleTime, CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ) ) { setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed doorClosedRequired( TRUE, TRUE ); - signalAllowDGFillRes1(); - signalAllowDGFillRes2(); state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } @@ -984,7 +997,7 @@ state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); } @@ -1002,7 +1015,7 @@ * The handleDrySelfTestUsedCartridgeCheckState function verify no fluid is * detected by bubble detectors to ensure the cartridge is new. * @details Inputs: none - * @details Outputs: none + * @details Outputs: cartridgeUsedTestRun * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) @@ -1024,6 +1037,7 @@ { // If either of the test configurations are set go to loaded check state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + cartridgeUsedTestRun = TRUE; } else { @@ -1057,8 +1071,8 @@ { setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); // need open path from PBA to VBT + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // need open path from PBA to VBT setValveAirTrap( STATE_OPEN ); pressureSelfTestPreNormalStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_SETUP_STATE; @@ -1457,19 +1471,6 @@ setupForSelfTestsStop(); } -#ifndef _RELEASE_ - if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) || // Allow res 1&2 fills now if air pump not disabled - ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) ) - { - if ( state != DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE ) - { - signalAllowDGFlushFills(); - signalAllowDGFillRes1(); - signalAllowDGFillRes2(); - } - } -#endif - return state; } @@ -1550,7 +1551,15 @@ else { doorClosedRequired( FALSE, TRUE ); - state = DRY_SELF_TESTS_START_STATE; + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + if ( TRUE == cartridgeUsedTestRun ) + { + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else + { + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } } } @@ -1656,19 +1665,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 { @@ -1686,22 +1682,79 @@ /*********************************************************************//** * @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 * @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() ) { @@ -2041,4 +2094,29 @@ return state; } +/*********************************************************************//** + * @brief + * The handleDoorCloseAfterCartridgeInsertion function handles the check + * for door close after cartridge install so that saline line can be pinched. + * @details Inputs: door and latch states, doorStateAfterCartridgeInstall + * @details Outputs: doorStateAfterCartridgeInstall + * @return none + *************************************************************************/ +void handleDoorCloseAfterCartridgeInsertion( void ) +{ + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + if ( ( STATE_OPEN == frontDoor ) && ( TRUE == doorStateAfterCartridgeInstall ) ) + { + doorStateAfterCartridgeInstall = FALSE; + } + // when transitioning from door open to door closed, pinch off saline bag to prevent saline from running up the line + if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) && ( FALSE == doorStateAfterCartridgeInstall ) ) + { + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + doorStateAfterCartridgeInstall = TRUE; + } +} + /**@}*/