Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r71319ba4a10ae2e8d33c74a388b39cff14e9b636 -r7ed38e9408e5018e9b409351f1aca7a04e356144 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 71319ba4a10ae2e8d33c74a388b39cff14e9b636) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 7ed38e9408e5018e9b409351f1aca7a04e356144) @@ -19,6 +19,7 @@ #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodLeak.h" #include "Buttons.h" #include "Dialysis.h" #include "DialInFlow.h" @@ -51,6 +52,9 @@ #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. +// 3.07 + 12.28 has been received from the mechanical team and 5 mL of margine has been added for safety +#define DPI_TO_BLD_VOLUME_ML ( 3.07F + 12.28F + 5.0F ) ///< Dialysate inlet pump to blood detect sensor volume in milliliters. + /// Defined states for the Load Cell cycles. typedef enum Reservoir_Steady_Cycle { @@ -61,6 +65,15 @@ // ********** private data ********** +/// Blood leak treatment zeroing data structure +typedef struct +{ + F32 DPiToBLDFlushedVolML; ///< Dialysate inlet pump to blood leak flushed volume in milliliters. + BOOL hasBloodLeakZeroingBeenRequested; ///< Flag to indicate blood leak zeroing has been requested. + BOOL isZeroingRequestedFromTreatmentStop; ///< Flag to indicate blood leak zeroing has been requested from treatment stop. + BLOOD_LEAK_ZEROING_STATE_T bloodLeakZeroingState; ///< Blood leak zeroing state. +} BLOOD_LEAK_ZEROING_T ; + static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. @@ -90,11 +103,13 @@ static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. +static BLOOD_LEAK_ZEROING_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // ********** private function prototypes ********** static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ); +static DIALYSIS_STATE_T handleDialysisBloodLeakZeroingState( void ); static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); @@ -104,11 +119,18 @@ static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingZeroState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingVerifyZeroingState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingCompleteState( DIALYSIS_STATE_T *dialysisState ); + static void checkUFControl( void ); static void updateUFVolumes( void ); static void publishSalineBolusData( void ); static void checkLoadCellsStablePrimaryBackupDriftOutOfRange( DG_RESERVOIR_ID_T reservoirID, RESERVOIR_STEADY_CYCLE_T cycle ); +static BOOL hasDPiToBLDVolumeBeenFlushed( void ); /*********************************************************************//** * @brief @@ -164,6 +186,7 @@ } resetSalineBolus(); + resetBloodLeakZeroing(); } /*********************************************************************//** @@ -659,6 +682,13 @@ // Check ultrafiltration control during dialysis (even when ultrafiltration is paused). checkUFControl(); + if ( ( TRUE == isBloodLeakZeroingNeeded() ) && ( DIALYSIS_UF_STATE == currentDialysisState ) ) + { + // Reset the blood leak zeroing variables + resetBloodLeakZeroing(); + requestBloodLeakZeroing( FALSE ); + } + // Dialysis state machine switch ( currentDialysisState ) { @@ -670,6 +700,10 @@ currentDialysisState = handleDialysisSalineBolusState(); break; + case DIALYSIS_BLOOD_LEAK_ZEROING_STATE: + currentDialysisState = handleDialysisBloodLeakZeroingState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_STATE, currentDialysisState ) break; @@ -785,6 +819,23 @@ /*********************************************************************//** * @brief + * The handleDialysisBloodLeakZeroingState function handles the blood leak + * zeroing sub state of the state machine. + * @details Inputs: none + * @details Outputs: none + * @return next Dialysis state. + *************************************************************************/ +static DIALYSIS_STATE_T handleDialysisBloodLeakZeroingState( void ) +{ + DIALYSIS_STATE_T result = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + + result = execBloodLeakZeroing(); + + return result; +} + +/*********************************************************************//** + * @brief * The handleUFPausedState function handles the Paused state of the * ultrafiltration state machine. * @details Inputs: salineBolusStartRequested @@ -811,6 +862,19 @@ salineBolusStartRequested = FALSE; } } + else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + autoResumeUF = FALSE; + if ( BLD_ZEROING_IDLE_STATE == bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + *dialysisState = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + } + else + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + } + } return result; } @@ -863,6 +927,20 @@ salineBolusStartRequested = FALSE; } } + else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + if ( BLD_ZEROING_IDLE_STATE == bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + autoResumeUF = TRUE; + result = UF_PAUSED_STATE; + *dialysisState = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + } + else + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + } + } return result; } @@ -1007,7 +1085,6 @@ setCurrentSubState( (U32)DIALYSIS_UF_STATE ); setCurrent4thLevelState( (U32)currentUFState ); sendOperationStatusEvent(); - } signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Resume dialysis @@ -1040,6 +1117,148 @@ /*********************************************************************//** * @brief + * The handleBloodLeakZeroingIdleState function handles the blood leak zeroing + * idle state. In this state the actuators and parameters are set to run + * the blood leak zeroing state machine. + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_IDLE_STATE; + + if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + bloodLeakZeroingStatus.DPiToBLDFlushedVolML = 0.0F; + + // Cmd all pumps to stop + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stopSyringePump(); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + + state = BLD_ZEROING_FLUSH_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingFlushState function handles the blood leak zeroing + * flush state. In this state, the line in between the dialysate inlet pump + * to blood leak detector is flushed with new dialysate. + * @details Inputs: none + * @details Outputs: none + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_FLUSH_STATE; + + if ( TRUE == hasDPiToBLDVolumeBeenFlushed() ) + { + state = BLD_ZEROING_ZERO_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingZeroState function handles the blood leak zeroing + * zero state. In this state, the zero blood leak command is issued. + * @details Inputs: none + * @details Outputs: none + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingZeroState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_ZERO_STATE; + + if ( TRUE == zeroBloodLeak() ) + { + state = BLD_ZEROING_VERIFY_ZEROING_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingVerifyZeroingState function handles the blood + * leak verifying whether zeroing was successful or not. Based on the pass + * or fail status of the blood leak zeroing the state transition occurs. + * @details Inputs: none + * @details Outputs: none + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingVerifyZeroingState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_VERIFY_ZEROING_STATE; + SELF_TEST_STATUS_T zeroSelfTestStatus = getBloodLeakSelfTestStatus(); + + if ( SELF_TEST_STATUS_PASSED == zeroSelfTestStatus ) + { + state = BLD_ZEROING_COMPLETE_STATE; + } + else if ( SELF_TEST_STATUS_FAILED == zeroSelfTestStatus ) + { + if ( TRUE == hasBloodLeakZeroSequenceFailed() ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); + } + else + { + state = BLD_ZEROING_ZERO_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingCompleteState function handles the blood + * leak complete state. The state requests a transition back to dialysis + * if the request to zero the blood leak was issued from the dialysis sub-mode. + * @details Inputs: bloodLeakZeroingStatus, autoResumeUF + * @details Outputs: bloodLeakZeroingStatus, autoResumeUF, currentUFState + * @param pointer to the local dialysis state + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingCompleteState( DIALYSIS_STATE_T *dialysisState ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_COMPLETE_STATE; + + if ( FALSE == bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop ) + { + *dialysisState = DIALYSIS_UF_STATE; + + // Resume UF if appropriate + if ( TRUE == autoResumeUF ) + { + autoResumeUF = FALSE; + currentUFState = UF_RUNNING_STATE; + //Set substate for event + setCurrentSubState( (U32)DIALYSIS_UF_STATE ); + setCurrent4thLevelState( (U32)currentUFState ); + sendOperationStatusEvent(); + } + + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Resume dialysis + transitionToDialysis(); + } + + return state; +} + +/*********************************************************************//** + * @brief * The publishSalineBolusData function handles the max saline delivered * state of the saline bolus state machine. This is a terminal state. * @details Inputs: none @@ -1232,6 +1451,90 @@ /*********************************************************************//** * @brief + * The execBloodLeakZeroing function handles the blood leak zeroing sequence + * @details Inputs: bloodLeakZeroing + * @details Outputs: bloodLeakZeroing + * @return next state of the dialysis state machine + *************************************************************************/ +DIALYSIS_STATE_T execBloodLeakZeroing( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T prevState = bloodLeakZeroingStatus.bloodLeakZeroingState; + DIALYSIS_STATE_T dialysisState = currentDialysisState; + + switch( bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + case BLD_ZEROING_IDLE_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingIdleState(); + break; + + case BLD_ZEROING_FLUSH_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingFlushState(); + break; + + case BLD_ZEROING_ZERO_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingZeroState(); + break; + + case BLD_ZEROING_VERIFY_ZEROING_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingVerifyZeroingState(); + break; + + case BLD_ZEROING_COMPLETE_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingCompleteState( &dialysisState ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_BLOOD_LEAK_ZEROING_STATE, + bloodLeakZeroingStatus.bloodLeakZeroingState ) + break; + } + + if ( prevState != bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, prevState, bloodLeakZeroingStatus.bloodLeakZeroingState ) + } + + return dialysisState; +} + +/*********************************************************************//** + * @brief + * The requestBloodLeakZeroing function sets the flag the requests the + * blood leak zeroing. + * @details Inputs: none + * @details Outputs: bloodLeakZeroing + * @return none + *************************************************************************/ +void requestBloodLeakZeroing( BOOL isRequestFromTreatmentStop ) +{ + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = TRUE; + bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop = isRequestFromTreatmentStop; + + if ( FALSE == isRequestFromTreatmentStop ) + { + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + } +} + +/*********************************************************************//** + * @brief + * The resetBloodLeakZeroingParameters function resets the blood leak zeroing + * parameters. + * @details Inputs: none + * @details Outputs: bloodLeakZeroing + * @return none + *************************************************************************/ +void resetBloodLeakZeroing( void ) +{ + bloodLeakZeroingStatus.DPiToBLDFlushedVolML = 0.0F; + bloodLeakZeroingStatus.bloodLeakZeroingState = BLD_ZEROING_IDLE_STATE; + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop = FALSE; +} + +/*********************************************************************//** + * @brief * The checkLoadCellsStablePrimaryBackupDriftOutOfRange function checks the * load cells' primary and backup drift when the reservoir level has been stable * for greater than large filter time. @@ -1290,4 +1593,24 @@ } } +/*********************************************************************//** + * @brief + * The hasDPiToBLDVolumeBeenFlushed function checks whether the line in + * between dialysate inlet pump to the blood leak detector has been flushed + * with fresh fluid or not. + * @details Inputs: bloodLeakZeroing + * @details Outputs: bloodLeakZeroing + * @return TRUE if the line has been flushed otherwise, FALSE + *************************************************************************/ +static BOOL hasDPiToBLDVolumeBeenFlushed( void ) +{ + BOOL status = FALSE; + F32 measuredDPiMLPM = getMeasuredDialInFlowRate(); + + bloodLeakZeroingStatus.DPiToBLDFlushedVolML += ( measuredDPiMLPM * TASK_GENERAL_INTERVAL ) / (F32)( SEC_PER_MIN * MS_PER_SECOND ); + status = ( ( bloodLeakZeroingStatus.DPiToBLDFlushedVolML - DPI_TO_BLD_VOLUME_ML ) < NEARLY_ZERO ? TRUE : FALSE ); + + return status; +} + /**@}*/