Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rf760ffc4b10556e5186e9ceb90294262063440ca -rf46a432cf62183516e05aae835cc810cfc964caa --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision f760ffc4b10556e5186e9ceb90294262063440ca) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision f46a432cf62183516e05aae835cc810cfc964caa) @@ -52,6 +52,24 @@ #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. +// Dialyzer reprime constants +static const U32 DIALYZER_REPRIME_INTERVAL = ((30 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Dialyzer reprime interval count. Time between reprime attempts. +static const U32 DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL = ((5 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Final dialyzer reprime interval count. Used to determine whether the final dialyzer reprime has been completed. +static const U32 DIALYZER_REPRIME_REPRIME_INTERVAL = ((40 * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Duration of reprime state interval count. How long to run the pumps to remove air from the dialyzer. +static const U32 DIALYZER_REPRIME_PURGE_PRIOR_1_INTERVAL = ((10 * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Duration of purge lines prior 1 state interval count. +static const U32 DIALYZER_REPRIME_PURGE_PRIOR_2_INTERVAL = ((6 * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Duration of purge lines prior 2 interval count. +static const U32 DIALYZER_REPRIME_PURGE_LINES_INTERVAL = ((10 * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Duration of purge lines state interval count. +#define DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL_SEC 300 ///< Time before end of treatment to perform final dialyzer reprime, sec. +#define DP_FAST_PURGE_FLOW_RATE_ML_MIN 500.0F ///< Dialysate pump speed for purging air in dialyzer reprime states, ml/min. +#define DPI_REPRIME_FLOW_RATE_ML_MIN 64.0F ///< Inlet dialysate pump speed for repriming in dialyzer reprime states, ml/min. +#define DPO_REPRIME_FLOW_RATE_ML_MIN 60.0F ///< Outlet dialysate pump speed for repriming in dialyzer reprime states, ml/min. + /// Defined states for the Load Cell cycles. typedef enum Reservoir_Steady_Cycle { @@ -62,9 +80,10 @@ // ********** private data ********** -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. +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. +static DIALYZER_REPRIME_STATE_T currentDialyzerReprimeState; ///< Current state of the dialyzer reprime state machine. static F32 refUFVolume; ///< Current reference volume for ultrafiltration (Where should we be w/r/t ultrafiltration). static F32 measUFVolume; ///< Current total measured volume for ultrafiltration (Where are we w/r/t ultrafiltration). @@ -95,10 +114,15 @@ static U32 uFAccuracyCheckTimerCtr; ///< Timer counter to determine when next to check ultrafiltration accuracy. static F32 lastUFVolumeChecked; ///< Starting ultrafiltration volume for accuracy check. +static U32 dialyzerReprimeIntervalTimerCtr; ///< Timer counter to determine when the dialyzer reprime should be done. +static BOOL dialyzerReprimeInProgress; ///< Flag indicates whether the dialyzer reprime has been interrupted. +static U32 dialyzerReprimeTimerCtr; ///< General timer counter for delays in dialyzer reprime functions. + // ********** private function prototypes ********** static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ); +static DIALYSIS_STATE_T handleDialysisDialyzerReprimeState( void ); static UF_STATE_T handleUFStartState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); @@ -109,6 +133,12 @@ static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); +static DIALYZER_REPRIME_STATE_T handleDialysatePumpsOffState( DIALYSIS_STATE_T *dialysisState ); +static DIALYZER_REPRIME_STATE_T handlePurgePrior1State( DIALYSIS_STATE_T *dialysisState ); +static DIALYZER_REPRIME_STATE_T handlePurgePrior2State( DIALYSIS_STATE_T *dialysisState ); +static DIALYZER_REPRIME_STATE_T handleRePrimeState( DIALYSIS_STATE_T *dialysisState ); +static DIALYZER_REPRIME_STATE_T handlePurgeLinesState( DIALYSIS_STATE_T *dialysisState ); + static void checkUFAccuracyAndVolume( void ); static void updateUFVolumes( void ); @@ -154,6 +184,11 @@ uFAccuracyCheckTimerCtr = 0; lastUFVolumeChecked = 0.0; + dialyzerReprimeIntervalTimerCtr = 0; + dialyzerReprimeInProgress = FALSE; + dialyzerReprimeTimerCtr = 0; + currentDialyzerReprimeState = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_START][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; @@ -625,6 +660,17 @@ // Check ultrafiltration max rate and accuracy during dialysis (even when ultrafiltration is paused). checkUFAccuracyAndVolume(); + // Check whether it is time for dialyzer reprime + // Either a fixed interval or some interval before treatment end. + if ( ( ++dialyzerReprimeIntervalTimerCtr >= DIALYZER_REPRIME_INTERVAL) || + ( ( dialyzerReprimeIntervalTimerCtr > DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL ) && + ( getTreatmentTimeRemainingSecs() <= DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL_SEC) + ) + ) + { + currentDialysisState = DIALYSIS_DIALYZER_REPRIME_STATE; + } + // Dialysis state machine switch ( currentDialysisState ) { @@ -636,6 +682,10 @@ currentDialysisState = handleDialysisSalineBolusState(); break; + case DIALYSIS_DIALYZER_REPRIME_STATE: + currentDialysisState = handleDialysisDialyzerReprimeState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_STATE, currentDialysisState ) break; @@ -701,8 +751,8 @@ /*********************************************************************//** * @brief - * The handleDialysisSolutionInfusionState function handles the solution - * infustion state of the Dialysis state machine. + * The handleDialysisSalineBolusState function handles the saline bolus + * state of the Dialysis state machine. * @details Inputs: currentSalineBolusState * @details Outputs: currentSalineBolusState * @return next Dialysis state. @@ -747,6 +797,55 @@ /*********************************************************************//** * @brief + * The handleDialysisDialyzerReprimeState function handles the dialyzer reprime + * state of the Dialysis state machine. + * @details Inputs: prior currentDialyzerReprimeState + * @details Outputs: new currentDialyzerReprimeState + * @return next Dialysis state. + *************************************************************************/ +static DIALYSIS_STATE_T handleDialysisDialyzerReprimeState( void ) +{ + DIALYSIS_STATE_T result = DIALYSIS_DIALYZER_REPRIME_STATE; + DIALYZER_REPRIME_STATE_T priorSubState = currentDialyzerReprimeState; + + switch ( currentDialyzerReprimeState ) + { + case DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF: + currentDialyzerReprimeState = handleDialysatePumpsOffState( &result ); + break; + + case DIALYZER_REPRIME_STATE_PURGE_PRIOR_1: + currentDialyzerReprimeState = handlePurgePrior1State( &result ); + break; + + case DIALYZER_REPRIME_STATE_PURGE_PRIOR_2: + currentDialyzerReprimeState = handlePurgePrior2State( &result ); + break; + + case DIALYZER_REPRIME_STATE_REPRIME: + currentDialyzerReprimeState = handleRePrimeState( &result ); + break; + + case DIALYZER_REPRIME_STATE_PURGE_LINES: + currentDialyzerReprimeState = handlePurgeLinesState( &result ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_DIALYZER_REPRIME_STATE, currentDialyzerReprimeState ) + currentDialyzerReprimeState = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + break; + } + + if ( priorSubState != currentDialyzerReprimeState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDialyzerReprimeState ); + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleUFPausedState function handles the Paused state of the * ultrafiltration state machine. * @details Inputs: salineBolusStartRequested @@ -1009,6 +1108,163 @@ /*********************************************************************//** * @brief + * The handleDialysatePumpsOffState function handles the dialysate pumps off state of the + * dialyzer reprime state machine. + * @details Inputs: isDialInPumpRunning(), isDialOutPumpRunning(), dialyzerReprimeInProgress flag + * @details Outputs: next dialyzer reprime state, dialyzerReprimeTimerCtr, dialyzerReprimeInProgress flag + * @param dialysis state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialysatePumpsOffState( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + static BOOL pumpsCmdOff = FALSE; + + if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) + { + // Decide which state to transition to + if ( TRUE == dialyzerReprimeInProgress ) + { // the reprime was interrupted, so it is necessary to purge any air that may have been left in the lines + setDialInPumpTargetFlowRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + dialyzerReprimeTimerCtr = 0; + result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_1; + } + else + { + // Set valves to flow through dialyzer + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setDialInPumpTargetFlowRate ( DPI_REPRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( DPO_REPRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + dialyzerReprimeTimerCtr = 0; + dialyzerReprimeInProgress = TRUE; + result = DIALYZER_REPRIME_STATE_REPRIME; + } + } + else if ( FALSE == pumpsCmdOff ) + { + // Give commands to stop pumps + setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + pumpsCmdOff = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the purge prior 1 state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeTimerCtr + * @details Outputs: dialyzerReprimeTimerCtr, next dialyzer reprime state + * @param dialysis state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handlePurgePrior1State( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_1; + + if ( ++dialyzerReprimeTimerCtr >= DIALYZER_REPRIME_PURGE_PRIOR_1_INTERVAL ) + { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setDialOutPumpTargetRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + dialyzerReprimeTimerCtr = 0; + result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_2; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handlePurgePrior2State function handles the purge prior 2 state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeTimerCtr + * @details Outputs: dialyzerReprimeTimerCtr, next dialyzer reprime state + * @param dialysis state + * @return next dialyzer reprime state state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handlePurgePrior2State( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_2; + + if ( ++dialyzerReprimeTimerCtr >= DIALYZER_REPRIME_PURGE_PRIOR_2_INTERVAL ) + { + setDialInPumpTargetFlowRate( DPI_REPRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( DPO_REPRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + dialyzerReprimeTimerCtr = 0; + result = DIALYZER_REPRIME_STATE_REPRIME; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the reprime state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeTimerCtr + * @details Outputs: dialyzerReprimeTimerCtr, next dialyzer reprime state + * @param dialysis state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleRePrimeState( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_REPRIME; + + if ( ++dialyzerReprimeTimerCtr >= DIALYZER_REPRIME_REPRIME_INTERVAL ) + { + setDialInPumpTargetFlowRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + signalDialOutPumpHardStop(); + dialyzerReprimeTimerCtr = 0; + result = DIALYZER_REPRIME_STATE_PURGE_LINES; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the purge lines state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeTimerCtr + * @details Outputs: dialyzerReprimeTimerCtr, dialyzerReprimeInProgress, + * dialyzerReprimeIntervalTimerCtr, next dialyzer reprime state + * @param dialysis state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handlePurgeLinesState( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_LINES; + + if ( ++dialyzerReprimeTimerCtr >= DIALYZER_REPRIME_PURGE_LINES_INTERVAL ) + { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + signalDialInPumpHardStop(); + // Reset the timer for reprime interval and the reprime in progress flag. + dialyzerReprimeInProgress = FALSE; + dialyzerReprimeTimerCtr = 0; + dialyzerReprimeIntervalTimerCtr = 0; + currentDialyzerReprimeState = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + // Dialysis back to UF state + *dialysisState = DIALYSIS_UF_STATE; + // Resume dialysis + transitionToDialysis(); + result = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + } + + return result; +} + +/*********************************************************************//** + * @brief * The publishSalineBolusData function handles the max saline delivered * state of the saline bolus state machine. This is a terminal state. * @details Inputs: none Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -rf760ffc4b10556e5186e9ceb90294262063440ca -rf46a432cf62183516e05aae835cc810cfc964caa --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision f760ffc4b10556e5186e9ceb90294262063440ca) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision f46a432cf62183516e05aae835cc810cfc964caa) @@ -182,6 +182,7 @@ SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, SW_FAULT_ID_HD_INVALID_ALARM_AUDIO_STATE, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, + SW_FAULT_ID_DIALYSIS_INVALID_DIALYZER_REPRIME_STATE, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T;