Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -rc7f14267973d4c9731fa0dc42607eeea23722b13 -r62200ed6423dfd6ff7881bd0fc308162384e663e --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision c7f14267973d4c9731fa0dc42607eeea23722b13) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 62200ed6423dfd6ff7881bd0fc308162384e663e) @@ -11,7 +11,7 @@ * @date (last) 28-Jan-2021 * * @author (original) Quang Nguyen -* @date (original) 28-Jan-2021s +* @date (original) 28-Jan-2021 * ***************************************************************************/ @@ -21,8 +21,11 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "FPGA.h" +#include "ModeTreatmentParams.h" #include "PresOccl.h" #include "SelfTests.h" +#include "SyringePump.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" @@ -41,68 +44,39 @@ #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 NORMALIZED_PRESSURE_SELF_TEST_TIME ( 2 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize 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 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.0 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). -#define DIP_FLOW_RATE_SETUP_ML_MIN 100 ///< Dialysate inlet pump flow rate during the setup for wet self-test. +#define DIP_FLOW_RATE_SETUP_ML_MIN 150 ///< Dialysate inlet pump flow rate during the setup for wet self-test. #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 DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 600 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. -#define WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML 1500 ///< Setup volume for reservoir one before wet self-test in ml. -#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_RESERVOIR_ONE_SETUP_VOLUME_ML 1200.0 ///< Setup volume for reservoir one before wet self-test in ml. +#define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100.0 ///< Target of first displacement volume in ml. +#define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 600.0 ///< Target of second displacement volume in ml. +#define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 5.0 ///< 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. +#define RESERVOIR_SETTLE_TIME_MS ( 4 * MS_PER_SECOND ) ///< Time allotted for reservoir to settle in ms. +#define MAX_NO_CARTRIDGE_SELF_TEST_TIME 30 ///< Maximum no cartridge self-test time (in seconds). +#define MAX_DRY_SELF_TEST_TIME ( 3 * SEC_PER_MIN ) ///< Maximum dry self-test time (in seconds). + +#define SELF_TEST_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND ) ///< Interval (ms/task time) at which self-test time data is published on the CAN bus. + /// Multiplier to conver flow (mL/min) into volume (mL) for period of general task interval. static const F32 SELF_TEST_FLOW_INTEGRATOR = ( ( 1.0 * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); -/// No cartridge self-tests state machine. -typedef enum No_Cart_Self_Tests_State -{ - NO_CART_SELF_TESTS_START_STATE = 0, ///< No cartridge self-tests starting state. - NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE, ///< Wait for door to be closed before running self-tests. - NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE, ///< No cartridge occlusion sensors self-test state. - NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE, ///< No cartridge blood flow meter self-test state. - NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE, ///< No cartridge dialysate flow meter self-test state. - NO_CART_SELF_TESTS_PUMPS_STATE, ///< No cartridge self-test for blood pump, dialysate in pump, dialysate out pump state. - NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE, ///< No cartridge leak detectors self-test state. - NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE, ///< No cartridge board temperature self-test state. - 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_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; - -/// Dry self-tests state machine. -typedef enum Dry_Self_Tests_State -{ - DRY_SELF_TESTS_START_STATE = 0, ///< Dry self-tests starting state. - DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE, ///< Wait for door to close before executing self-tests. - DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors dry self-test state. - DRY_SELF_TESTS_AIR_TRAP_STATE, ///< Air trap fill level ultrasonic sensor dry self-test state. - DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE, ///< Occlusion sensors dry self-test state. - 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_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; - /// Wet self-tests state machine. typedef enum Wet_Self_Tests_State { WET_SELF_TESTS_START_STATE = 0, ///< Wet self-tests starting state. WET_SELF_TESTS_SETUP_STATE, ///< Setup reservoirs for wet self-tests. - WET_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors wet self-tests state. + WET_SELF_TESTS_PRIME_CHECK_STATE, ///< Prime check wet self-tests state, checks for primed patient lines. 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. @@ -116,14 +90,13 @@ // ********** private data ********** -static BOOL noCartSelfTestsResult; ///< Result of no cartridge self-tests. static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; ///< Current state of the no cartridge self-tests state machine. static U32 runPumpStartTime; ///< Beginning time when pumps start running -static BOOL hasPumpsStarted; ///< Flag indicates if pumps have started running for self-test. +static BOOL havePumpsStarted; ///< Flag indicates pumps have started running for self-test. -static BOOL drySelfTestsResult; ///< Result of dry self-tests. static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of the dry self-tests state machine. static U32 pressureSelfTestBloodPumpRunStartTime; ///< Pressure dry self-test blood pump runs start time. +static U32 pressureSelfTestNormalizedStartTime; ///< Normalized pressure dry self-test start time. static F32 previousNormalArterialPressure; ///< Holds the previous normal arterial pressure reading. static F32 previousNormalVenousPressure; ///< Holds the previous normal venous pressure reading. @@ -136,34 +109,37 @@ static F32 setupDisplacementVolume; ///< Hold the setup displacement volume to get reservoir one to target volume. static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been send to DG. +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 BOOL useHeparin; ///< Flag indicates the user of heparin. + static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. -static BOOL selfTestsStopRequested; ///< Flag indicates alarm requesting to stop self-test. // ********** private function prototypes ********** static void resetSelfTestsFlags( void ); static void setupForSelfTestsStop( void ); -static void handleNoCartSelfTestsStopRequest( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeSyringePumpState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ); -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ); -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeIdleState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ); -static void handleDrySelfTestsStopRequest( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); -static DRY_SELF_TESTS_STATE_T handleDrySelfTestBubbleDetectorsState( void ); -static DRY_SELF_TESTS_STATE_T handleDrySelfTestAirTrapState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); -static void handleWetSelfTestsStopRequest( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); -static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( 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 ); @@ -181,6 +157,8 @@ *************************************************************************/ void initSelfTests( void ) { + selfTestStartTime = 0; + selfTestPreviousPublishDataTime = 0; } /*********************************************************************//** @@ -198,19 +176,6 @@ /*********************************************************************//** * @brief - * The signalStopPrime function signals self-tests to stop when an - * alarm with stop property has been triggered. - * @details Inputs: none - * @details Outputs: primeStopRequested - * @return none - *************************************************************************/ -void signalStopSelfTests( void ) -{ - selfTestsStopRequested = TRUE; -} - -/*********************************************************************//** - * @brief * The resetSelfTestsFlags function resets all self-tests signal flags. * @details Inputs: none * @details Outputs: signal flags set to FALSE @@ -219,7 +184,6 @@ static void resetSelfTestsFlags( void ) { selfTestsResumeRequested = FALSE; - selfTestsStopRequested = FALSE; } /*********************************************************************//** @@ -235,6 +199,7 @@ signalBloodPumpHardStop(); signalDialInPumpHardStop(); signalDialOutPumpHardStop(); + stopSyringePump(); } /*********************************************************************//** @@ -247,10 +212,19 @@ *************************************************************************/ void transitionToNoCartSelfTests( void ) { - noCartSelfTestsResult = FALSE; + F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + +#ifndef DISABLE_SYRINGE_PUMP + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ); +#else + useHeparin = FALSE; +#endif currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; runPumpStartTime = 0; - hasPumpsStarted = FALSE; + havePumpsStarted = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -260,90 +234,70 @@ * The execNoCartSelfTests function executes the no cartridge self-tests * state machine. * @details Inputs: currentNoCartSelfTestsState - * @details Outputs: currentNoCartSelfTestsState, noCartSelfTestsResult + * @details Outputs: currentNoCartSelfTestsState * @return none *************************************************************************/ void execNoCartSelfTests( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - // execute no cartridge self-tests state machine switch ( currentNoCartSelfTestsState ) { case NO_CART_SELF_TESTS_START_STATE: -#ifdef SKIP_SELF_TESTS - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; -#else currentNoCartSelfTestsState = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; -#endif break; case NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestsWaitForClosedDoor(); break; case NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE: - result = execPresOcclTest(); - - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE; - } + execPresOcclTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE: - result = execBloodFlowTest(); - - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE; - } + execBloodFlowTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE: - result = execDialInFlowTest(); + execDialInFlowTest(); - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_PUMPS_STATE; - } + // TODO: Use appropriate sensor driver + setFPGASensorTest( BLOOD_LEAK_SELF_TEST_SET ); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; break; - case NO_CART_SELF_TESTS_PUMPS_STATE: - currentNoCartSelfTestsState = handleNoCartSelfTestPumpsState(); - break; - case NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE: - currentNoCartSelfTestsState = handleNoCartSelfTestLeakDetectorsState( &result ); + currentNoCartSelfTestsState = handleNoCartSelfTestLeakDetectorsState(); break; case NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE: // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DOOR_SWITCH_STATE; + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_STATE; break; - case NO_CART_SELF_TESTS_DOOR_SWITCH_STATE: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; + case NO_CART_SELF_TESTS_HOME_VALVES_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestHomeValvesState(); break; - case NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE: - currentNoCartSelfTestsState = handleNoCartSelfTestHomeValvesAndPumpState(); + case NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestHomeSyringePumpState(); break; + case NO_CART_SELF_TESTS_PUMPS_STATE: + currentNoCartSelfTestsState = handleNoCartSelfTestPumpsState(); + break; + case NO_CART_SELF_TESTS_HOME_IDLE_STATE: - if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE_STATE; - } + currentNoCartSelfTestsState = handleNoCartSelfTestHomeIdleState(); break; case NO_CART_SELF_TESTS_STOPPED_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestStoppedState(); break; case NO_CART_SELF_TESTS_COMPLETE_STATE: - noCartSelfTestsResult = TRUE; break; default: @@ -352,28 +306,30 @@ break; } - // Transition to stopped state when alarm with stop property has been triggered - handleNoCartSelfTestsStopRequest(); - // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); - if ( SELF_TEST_STATUS_FAILED == result ) + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_NO_CART_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + broadcastNoCartSelfTestTime( MAX_NO_CARTRIDGE_SELF_TEST_TIME, ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); } } /*********************************************************************//** * @brief - * The isNoCartSelfTestsPassed function returns the status of no cartridge self-tests. - * @details Inputs: none + * The getNoCartSelfTestsState function returns the current state of no + * cartridge self-tests sub-mode. + * @details Inputs: currentNoCartSelfTestsState * @details Outputs: none - * @return TRUE if no cartridge self-tests passed, otherwise FALSE + * @return current no cartridge self-tests state *************************************************************************/ -BOOL isNoCartSelfTestsPassed( void ) +U32 getNoCartSelfTestsState( void ) { - return noCartSelfTestsResult; + return (U32)currentNoCartSelfTestsState; } /*********************************************************************//** @@ -386,11 +342,21 @@ *************************************************************************/ void transitionToDrySelfTests() { - drySelfTestsResult = FALSE; + F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + +#ifndef DISABLE_SYRINGE_PUMP + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ); +#else + useHeparin = FALSE; +#endif currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; pressureSelfTestBloodPumpRunStartTime = 0; + pressureSelfTestNormalizedStartTime = 0; previousNormalArterialPressure = 0.0; previousNormalVenousPressure = 0.0; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -399,7 +365,7 @@ * @brief * The execDrySelfTests function executes the dry self-tests state machine. * @details Inputs: currentDrySelfTestsState - * @details Outputs: currentDrySelfTestsState, drySelfTestsResult + * @details Outputs: currentDrySelfTestsState * @return none *************************************************************************/ void execDrySelfTests( void ) @@ -410,8 +376,9 @@ switch ( currentDrySelfTestsState ) { case DRY_SELF_TESTS_START_STATE: -#ifdef SKIP_SELF_TESTS - currentDrySelfTestsState = DRY_SELF_TESTS_COMPLETE_STATE; +#ifdef SKIP_DRY_SELF_TESTS + // TODO: Remove once dry self-test is ready to use + currentDrySelfTestsState = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; #else currentDrySelfTestsState = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; #endif @@ -421,17 +388,18 @@ currentDrySelfTestsState = handleDrySelfTestWaitForDoorCloseState(); break; - case DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE: - currentDrySelfTestsState = handleDrySelfTestBubbleDetectorsState(); + case DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestUsedCartridgeCheckState(); break; - case DRY_SELF_TESTS_AIR_TRAP_STATE: - currentDrySelfTestsState = handleDrySelfTestAirTrapState(); - break; - case DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE: if ( SELF_TEST_STATUS_PASSED == execPresOcclDryTest() ) { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_OPEN ); currentDrySelfTestsState = DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE; } break; @@ -448,12 +416,15 @@ currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalState( &result ); break; + case DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); + break; + case DRY_SELF_TESTS_STOPPED_STATE: currentDrySelfTestsState = handleDrySelfTestStoppedState(); break; case DRY_SELF_TESTS_COMPLETE_STATE: - drySelfTestsResult = TRUE; break; default: @@ -462,28 +433,34 @@ break; } - // Transition to stopped state when alarm with stop property has been triggered - handleDrySelfTestsStopRequest(); - // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); if ( SELF_TEST_STATUS_FAILED == result ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_DRY_SELF_TEST_FAILURE, currentDrySelfTestsState ); } + + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) + { + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + broadcastDrySelfTestTime( MAX_DRY_SELF_TEST_TIME, ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); + } } /*********************************************************************//** * @brief - * The isDrySelfTestsPassed function returns the status of dry self-tests. - * @details Inputs: none + * The getDrySelfTestsState function returns the current state of dry self-tests sub-mode. + * @details Inputs: currentDrySelfTestsState * @details Outputs: none - * @return TRUE if dry self-tests passed, otherwise FALSE + * @return current dry self-tests state *************************************************************************/ -BOOL isDrySelfTestsPassed( void ) +U32 getDrySelfTestsState( void ) { - return drySelfTestsResult; + return (U32)currentDrySelfTestsState; } /*********************************************************************//** @@ -502,6 +479,8 @@ displacementStartTime = 0; fmdIntegratedVolume = 0.0; isValvesSettingSent = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -528,8 +507,8 @@ currentWetSelfTestsState = handleWetSelfTestSetupState(); break; - case WET_SELF_TESTS_BUBBLE_DETECTOR_STATE: - currentWetSelfTestsState = handleWetSelfTestBubbleDetectorsState( &result ); + case WET_SELF_TESTS_PRIME_CHECK_STATE: + currentWetSelfTestsState = handleWetSelfTestPrimeCheckState( &result ); break; case WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE: @@ -570,9 +549,6 @@ break; } - // Transition to stopped state when alarm with stop property has been triggered - handleWetSelfTestsStopRequest(); - // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); @@ -596,25 +572,6 @@ /*********************************************************************//** * @brief - * The handleNoCartSelfTestsStopRequest function handles stop request from alarm - * and transition to stopped state. - * @details Inputs: none - * @details Outputs: none - * @return the next state of no cart self-tests state machine - *************************************************************************/ -static void handleNoCartSelfTestsStopRequest( void ) -{ - if ( TRUE == selfTestsStopRequested ) - { - setupForSelfTestsStop(); - - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; - } -} - -/*********************************************************************//** - * @brief * The handleNoCartridgeWaitForClosedDoor function executes the wait for * door to be closed state of no cartridge self-tests state machine. * @details Inputs: none @@ -629,198 +586,250 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); + // TODO: Use appropriate sensor driver if ( STATE_CLOSED == getFPGADoorState() ) { state = NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + return state; } /*********************************************************************//** * @brief - * The handleNoCartSelfTestPumpsState function runs blood, dialysate inlet, - * dialysate outlet pumps for certain time to make sure no alarms occur. + * The handleNoCartSelfTestLeakDetectorsState function verifies leak detectors status. * @details Inputs: none * @details Outputs: none * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( void ) { - NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_PUMPS_STATE; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; + // TODO: Use appropriate sensor driver + BOOL const bloodLeakDetector = getFPGABloodLeakDetectorStatus(); - if ( FALSE == hasPumpsStarted ) + if ( TRUE == bloodLeakDetector ) { - hasPumpsStarted = TRUE; - - setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - runPumpStartTime = getMSTimerCount(); + // TODO: Use appropriate sensor driver + setFPGASensorTest( BLOOD_LEAK_NORMAL_OPERATION ); + state = NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE; } - - if ( TRUE == didTimeout( runPumpStartTime, PUMP_RUN_SELF_TEST_TIME_MS ) ) + else { - signalBloodPumpHardStop(); - signalDialInPumpHardStop(); - signalDialOutPumpHardStop(); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE, (U32)bloodLeakDetector ); + } - setFPGASensorTest( BLOOD_LEAK_SELF_TEST_SET ); - state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; } return state; } /*********************************************************************//** * @brief - * The handleNoCartSelfTestHomeValvesAndPumpState function homes all valves - * and pumps. + * The handleNoCartSelfTestHomeValvesState function starts homing process for + * all the valves. * @details Inputs: none - * @details Outputs: none + * @details Outputs: Home all valves * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesState( void ) { + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE; VALVE_T valve; for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) { homeValve( valve ); } - homeBloodPump(); - homeDialInPump(); - homeDialOutPump(); + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } - return NO_CART_SELF_TESTS_HOME_IDLE_STATE; + return state; } /*********************************************************************//** * @brief - * The handleNoCartSelfTestLeakDetectorsState function verify leak detectors status. - * @details Inputs: none - * @details Outputs: none - * @param result self-test result + * The handleNoCartSelfTestHomeSyringePumpState function homes syringe pump. + * @details Inputs: useHeparin + * @details Outputs: Home syringe pump * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeSyringePumpState( void ) { - NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_SYRINGE_PUMP_STATE; - if ( TRUE == getFPGABloodLeakDetectorStatus() ) + if ( TRUE == useHeparin ) { - setFPGASensorTest( BLOOD_LEAK_NORMAL_OPERATION ); - state = NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE; + if ( ( FALSE == isSyringePumpHome() ) && ( TRUE == isSyringePumpStopped() ) ) + { + retractSyringePump(); + } } - else + + if ( TRUE == isSyringePumpHome() ) { - *result = SELF_TEST_STATUS_FAILED; + state = NO_CART_SELF_TESTS_PUMPS_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + return state; } /*********************************************************************//** * @brief - * The handleNoCartSelfTestStoppedState function handles the stopped no - * cartridge self-tests operation. + * The handleNoCartSelfTestPumpsState function runs blood, dialysate inlet, + * dialysate outlet pumps for certain time to make sure no alarms occur. * @details Inputs: none - * @details Outputs: none - * @return the next state of no cart self-tests state machine + * @details Outputs: Ran self-test for blood, dialysate in, dialysate out pumps + * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ) { - NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_STOPPED_STATE; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_PUMPS_STATE; - if ( TRUE == selfTestsResumeRequested ) + if ( FALSE == havePumpsStarted ) { - selfTestsResumeRequested = FALSE; - state = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + havePumpsStarted = TRUE; + + setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + runPumpStartTime = getMSTimerCount(); } + if ( TRUE == didTimeout( runPumpStartTime, PUMP_RUN_SELF_TEST_TIME_MS ) ) + { + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + + // Home pumps for cartridge installation + homeBloodPump(); + homeDialInPump(); + homeDialOutPump(); + state = NO_CART_SELF_TESTS_HOME_IDLE_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; + } + return state; } /*********************************************************************//** * @brief - * The handleDrySelfTestsStopRequest function handles stop request from alarm - * and transition to stopped state. + * The handleNoCartSelfTestHomeIdleState function waits for all pumps finish homing. * @details Inputs: none - * @details Outputs: none - * @return the next state of dry self-tests state machine + * @details Outputs: All pumps finished homing + * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static void handleDrySelfTestsStopRequest( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeIdleState( void ) { - if ( TRUE == selfTestsStopRequested ) + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_IDLE_STATE; + + if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) { - setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_COMPLETE_STATE; + } - currentDrySelfTestsState = DRY_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForSelfTestsStop(); + state = NO_CART_SELF_TESTS_STOPPED_STATE; } + + return state; } /*********************************************************************//** * @brief - * The handleDrySelfTestWaitForDoorCloseState function verify no fluid is detected - * by bubble detectors. + * The handleNoCartSelfTestStoppedState function handles the stopped no + * cartridge self-tests operation. * @details Inputs: none * @details Outputs: none - * @return the next state of dry self-tests state machine + * @return the next state of no cart self-tests state machine *************************************************************************/ -static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ) { - DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_STOPPED_STATE; - if ( STATE_CLOSED == getFPGADoorState() ) + if ( TRUE == selfTestsResumeRequested ) { - state = DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE; + selfTestsResumeRequested = FALSE; + havePumpsStarted = FALSE; + state = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } return state; } /*********************************************************************//** * @brief - * The handleDrySelfTestBubbleDetectorsState function verify no fluid is detected - * by bubble detectors. + * The handleDrySelfTestWaitForDoorCloseState function makes sure door is + * closed before starting self-tests. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ -static DRY_SELF_TESTS_STATE_T handleDrySelfTestBubbleDetectorsState( void ) +static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ) { - DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_BUBBLE_DETECTOR_STATE; + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; - BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); - BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); - - if ( ( TRUE == isADADetectedAir ) && ( TRUE == isADVDetectedAir ) ) + // TODO: Use appropriate sensor driver + if ( STATE_CLOSED == getFPGADoorState() ) { - state = DRY_SELF_TESTS_AIR_TRAP_STATE; + state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; } - else + + if ( TRUE == doesAlarmStatusIndicateStop() ) { - activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); } return state; } /*********************************************************************//** * @brief - * The handleDrySelfTestAirTrapState function verify no fluid is detected - * by air trap. + * The handleDrySelfTestUsedCartridgeCheckState function verify no fluid is + * detected by bubble detectors to ensure the cartridge is new. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ -static DRY_SELF_TESTS_STATE_T handleDrySelfTestAirTrapState( void ) +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) { - DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_AIR_TRAP_STATE; + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; - if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && + // TODO: Use appropriate sensor driver + BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); + BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); + + if ( ( TRUE == isADADetectedAir ) && ( TRUE == isADVDetectedAir ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) { state = DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE; @@ -830,6 +839,12 @@ activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -843,18 +858,28 @@ *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsSetupState( void ) { - previousNormalArterialPressure = getMeasuredArterialPressure(); - previousNormalVenousPressure = getMeasuredVenousPressure(); + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - setValveAirTrap( STATE_CLOSED ); - setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - pressureSelfTestBloodPumpRunStartTime = getMSTimerCount(); + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + previousNormalArterialPressure = getMeasuredArterialPressure(); + previousNormalVenousPressure = getMeasuredVenousPressure(); - return DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + pressureSelfTestBloodPumpRunStartTime = getMSTimerCount(); + } + + return state; } /*********************************************************************//** @@ -869,16 +894,20 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; - F32 const arterialPressure = getMeasuredArterialPressure(); F32 const venousPressure = getMeasuredVenousPressure(); + + // End the test when reaching target pressure or time out if ( ( TRUE == didTimeout( pressureSelfTestBloodPumpRunStartTime, BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ) ) || ( ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG >= arterialPressure ) || ( VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG <= venousPressure ) ) { + // Test pass when reading positive arterial pressure and negative venous pressure if ( ( arterialPressure < 0) && ( venousPressure > 0 ) ) { + signalBloodPumpHardStop(); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - setValveAirTrap( STATE_CLOSED ); + setValveAirTrap( STATE_OPEN ); + pressureSelfTestNormalizedStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; } else @@ -887,6 +916,12 @@ } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -903,59 +938,97 @@ { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; - F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure); - F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure); + F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure ); + F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure ); - if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_TIME ) ) { - state = DRY_SELF_TESTS_COMPLETE_STATE; + if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + { + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else + { + *result = SELF_TEST_STATUS_FAILED; + } } - else + + if ( TRUE == doesAlarmStatusIndicateStop() ) { - *result = SELF_TEST_STATUS_FAILED; + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); } return state; } /*********************************************************************//** * @brief - * The handleDrySelfTestStoppedState function handles the stopped dry self-tests - * operation. + * The handleDrySelfTestSyringePumpPrimeState function handles the prime + * operation for syringe pump. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ -static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ) +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ) { - DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED_STATE; + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; - if ( TRUE == selfTestsResumeRequested ) + if ( TRUE == useHeparin ) { - selfTestsResumeRequested = FALSE; - state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + if ( TRUE == isSyringePlungerFound() ) + { + if ( TRUE == isSyringePumpPrimed() ) + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + else + { + primeSyringePump(); + } + } + else + { + seekSyringePlunger(); + } } + else + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } /*********************************************************************//** * @brief - * The handleWetSelfTestsStopRequest function handles stop request from alarm - * and transition to stopped state. + * The handleDrySelfTestStoppedState function handles the stopped dry self-tests + * operation. * @details Inputs: none * @details Outputs: none - * @return the next state of wet self-tests state machine + * @return the next state of dry self-tests state machine *************************************************************************/ -static void handleWetSelfTestsStopRequest( void ) +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ) { - if ( TRUE == selfTestsStopRequested ) - { - setupForSelfTestsStop(); + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED_STATE; - currentWetSelfTestsState = WET_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; + if ( TRUE == selfTestsResumeRequested ) + { + selfTestsResumeRequested = FALSE; +#ifndef SKIP_DRY_SELF_TESTS + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; +#else + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; +#endif } + + return state; } /*********************************************************************//** @@ -976,20 +1049,18 @@ if ( FALSE == isValvesSettingSent ) { + isValvesSettingSent = TRUE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + if ( resOneWeight > WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML ) { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); cmdChangeDGValveSetting( DG_VALVE_SETTING_R1_TO_R2 ); } else { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); cmdChangeDGValveSetting( DG_VALVE_SETTING_R2_TO_R1 ); } - - isValvesSettingSent = TRUE; } if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) @@ -1000,14 +1071,16 @@ if ( FALSE == cmdResp.rejected ) { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SETUP_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_SETUP_STATE; } } -#ifdef SKIP_SELF_TESTS - state = WET_SELF_TESTS_COMPLETE_STATE; -#endif + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } return state; } @@ -1029,36 +1102,49 @@ if ( setupDisplacementVolume <= 0 ) { signalDialInPumpHardStop(); - state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + state = WET_SELF_TESTS_PRIME_CHECK_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } /*********************************************************************//** * @brief - * The handleWetSelfTestBubbleDetectorsState function handles the wet self-test - * for bubble detectors. - * @details Inputs: Arterial and venous air bubble status + * 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 * @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 ) +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( SELF_TEST_STATUS_T *result ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_PRIME_CHECK_STATE; + *result = SELF_TEST_STATUS_FAILED; + // TODO: Use appropriate sensor driver BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); +#ifndef SKIP_AIR_BUBBLE_CHECK if ( ( FALSE == isADADetectedAir ) && ( FALSE == isADVDetectedAir ) ) +#endif { settleStartTime = getMSTimerCount(); - currentWetSelfTestsState = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + *result = SELF_TEST_STATUS_PASSED; } - else + + if ( TRUE == doesAlarmStatusIndicateStop() ) { - *result = SELF_TEST_STATUS_FAILED; + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); } return state; @@ -1097,11 +1183,17 @@ { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -1128,6 +1220,12 @@ state = WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -1145,9 +1243,9 @@ 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 = 1 - ( fmdIntegratedVolume / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ); + F32 const resOneDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_1 ] - getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + F32 const resTwoDiffAfterDisplacement = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ]; + F32 const integratedVolumeToTargetPercent = fabs( 1.0 - ( fmdIntegratedVolume / 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 ) ) @@ -1160,6 +1258,12 @@ } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -1176,7 +1280,7 @@ WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; DG_CMD_RESPONSE_T cmdResp; - if ( ( FALSE == isValvesSettingSent ) && ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) ) + if ( FALSE == isValvesSettingSent ) { reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); @@ -1196,11 +1300,17 @@ { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -1228,6 +1338,12 @@ state = WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; } @@ -1245,9 +1361,9 @@ 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 = 1 - ( fmdIntegratedVolume / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ); + F32 const resOneDiffAfterDisplacement = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ]; + F32 const resTwoDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_2 ] - getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); + F32 const integratedVolumeToTargetPercent = fabs( 1.0 - ( fmdIntegratedVolume / WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML ) ); if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE ) ) @@ -1260,6 +1376,12 @@ } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; }