Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -raa7b1f5f68aae23c1c52b32658fcb625c29accfb -r44e745e602377ae878e1d31f0469cdcc47248ace --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision aa7b1f5f68aae23c1c52b32658fcb625c29accfb) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 44e745e602377ae878e1d31f0469cdcc47248ace) @@ -8,7 +8,7 @@ * @file ModePostTreat.c * * @author (last) Dara Navaei -* @date (last) 03-Nov-2022 +* @date (last) 08-Dec-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -45,11 +45,14 @@ /// Interval (ms/task time) at which the post-treatment state data is published on the CAN bus. #define POST_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) +#define DIP_DRAIN_DG_FLOW_RATE_ML_MIN 60 ///< DG drain inlet pump flow rate in mL/min. +#define DIP_DRAIN_DG_RUNTIME_MS 20000 ///< DG drain inlet pump run time in ms. /// Post-Treatment drain reservoirs state machine. typedef enum Drain_States { - DRAIN_RESERVOIR_SWITCH_STATE = 0, ///< Switch reservoir state. + DRAIN_DG_DEPRIME_STATE = 0, ///< Drain DG De-prime dialysate lines of excess fluid state. + DRAIN_RESERVOIR_SWITCH_STATE, ///< Switch reservoir state. DRAIN_RESERVOIR_START_DRAIN_STATE, ///< Drain reservoir start drain state. DRAIN_RESERVOIR_DRAIN_STATE, ///< Drain first reservoir state. DRAIN_RESERVOIR_COMPLETE_STATE, ///< Drain complete state. @@ -62,6 +65,9 @@ static BOOL disposableRemovalConfirmed; ///< Flag indicates user confirms disposable removal. static BOOL rinseConcentrateLines; ///< FLag indicates to rinse concentrate lines. static BOOL isThisFirstDrain; ///< Flag to indicate whether this is the first time the reservoir is drained. +static BOOL drainDGDePrimeActive; ///< FLag to indicate DePrime DG Dialysate lines active +static U32 drainDGDePrimeStarttime; ///< DG DePrime start time +static BOOL dgCommandSent; ///< Flag indicates whether a DG command has been already sent. static HD_POST_TREATMENT_STATE_T currentPostTreatmentState; ///< Current state of post-treatment mode state machine. static DRAIN_STATE_T currentDrainReservoirState; ///< Current drain reservoir state. static U32 postTreatmentPublishTimerCounter; ///< Timer counter used to schedule post-treatment data broadcast. @@ -78,6 +84,7 @@ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ); static void execDrainReservoirs( void ); +static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ); static DRAIN_STATE_T handleDrainReservoirSwitchState( void ); static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ); static DRAIN_STATE_T handleDrainReservoirDrainState( void ); @@ -88,7 +95,8 @@ * @details Inputs: none * @details Outputs: patientDisconnectionConfirmed, disposableRemovalConfirmed, * rinseConcentrateLines, isThisFirstDrain, currentPostTreatmentState, - * currentDrainReservoirState, postTreatmentPublishTimerCounter, treatmentLogData + * currentDrainReservoirState, postTreatmentPublishTimerCounter, treatmentLogData, + * dgCommandSent * @return none *************************************************************************/ void initPostTreatmentMode( void ) @@ -97,9 +105,12 @@ disposableRemovalConfirmed = FALSE; rinseConcentrateLines = FALSE; isThisFirstDrain = TRUE; + dgCommandSent = FALSE; currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; - currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; + currentDrainReservoirState = DRAIN_DG_DEPRIME_STATE; postTreatmentPublishTimerCounter = 0; + drainDGDePrimeActive = FALSE; + drainDGDePrimeStarttime = 0; // Reset treatment log data memset( &treatmentLogData, 0x0, sizeof( TREATMENT_LOG_DATA_PAYLOAD_T ) ); @@ -502,6 +513,10 @@ { switch ( currentDrainReservoirState ) { + case DRAIN_DG_DEPRIME_STATE: + currentDrainReservoirState = handleDrainDePrimeDGDialysateLinesState(); + break; + case DRAIN_RESERVOIR_SWITCH_STATE: currentDrainReservoirState = handleDrainReservoirSwitchState(); break; @@ -526,10 +541,46 @@ /*********************************************************************//** * @brief + * The handleDrainDePrimeDGDialysateLinesState function waits for DG to complete + * reservoir switch. + * @details Inputs: + * @details Outputs: + * @return next state + *************************************************************************/ +static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ) +{ + DRAIN_STATE_T state = DRAIN_DG_DEPRIME_STATE; + + if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) + { + if ( FALSE == drainDGDePrimeActive ) + { + // First entry - Run DPi slow reverse, VDi, VDo closed in init, DPo Off in init. + setDialInPumpTargetFlowRate( DIP_DRAIN_DG_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + drainDGDePrimeStarttime = getMSTimerCount(); + drainDGDePrimeActive = TRUE; + } + } + if ( TRUE == drainDGDePrimeActive ) + { + // Thereafter, check for time elapsed + if ( TRUE == didTimeout( drainDGDePrimeStarttime, DIP_DRAIN_DG_RUNTIME_MS ) ) + { + drainDGDePrimeActive = FALSE; + signalDialInPumpHardStop( ); + state = DRAIN_RESERVOIR_SWITCH_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleDrainReservoirSwitchState function waits for DG to complete * reservoir switch. - * @details Inputs: isThisFirstDrain - * @details Outputs: rinseConcentrateLines + * @details Inputs: isThisFirstDrain, dgCommandSent + * @details Outputs: rinseConcentrateLines, dgCommandSent * @return next state *************************************************************************/ static DRAIN_STATE_T handleDrainReservoirSwitchState( void ) @@ -538,20 +589,36 @@ if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { - DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; + DG_CMD_RESPONSE_T dgCmdResp; - // The first drain starts with setting the reservoir 2 as active and then the first reservoir is drained - rsrvrCmd.reservoirID = (U32)( TRUE == isThisFirstDrain ? DG_RESERVOIR_2 : DG_RESERVOIR_1 ); - rsrvrCmd.useLastTrimmerHeaterDC = FALSE; + if ( FALSE == dgCommandSent ) + { + DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; - cmdSetDGActiveReservoir( &rsrvrCmd ); + // The first drain starts with setting the reservoir 2 as active and then the first reservoir is drained + rsrvrCmd.reservoirID = (U32)( TRUE == isThisFirstDrain ? DG_RESERVOIR_2 : DG_RESERVOIR_1 ); + rsrvrCmd.useLastTrimmerHeaterDC = FALSE; + dgCommandSent = TRUE; - if ( TRUE == hasDGCompletedReservoirSwitch() ) + cmdSetDGActiveReservoir( &rsrvrCmd ); + } + else if ( TRUE == getDGCommandResponse( DG_CMD_SWITCH_RESERVOIR, &dgCmdResp ) ) { - // Check if the reservoir switch has been completed - // If this is the first drain, rinse the concentrate lines too - rinseConcentrateLines = ( TRUE == isThisFirstDrain ? TRUE : FALSE ); - state = DRAIN_RESERVOIR_START_DRAIN_STATE; + if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) + { + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + // Check if the reservoir switch has been completed + // If this is the first drain, rinse the concentrate lines too + rinseConcentrateLines = ( TRUE == isThisFirstDrain ? TRUE : FALSE ); + dgCommandSent = FALSE; + state = DRAIN_RESERVOIR_START_DRAIN_STATE; + } + } + else + { + dgCommandSent = FALSE; + } } } @@ -562,8 +629,8 @@ * @brief * The handleDrainReservoirStartDrainState function sends command to DG to * send the drain command to DG. - * @details Inputs: rinseConcentrateLines - * @details Outputs: none + * @details Inputs: rinseConcentrateLines, dgCommandSent + * @details Outputs: dgCommandSent * @return next state *************************************************************************/ static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ) @@ -575,15 +642,21 @@ DG_CMD_RESPONSE_T dgCmdResp; // If DG is still in the Idle mode in the flush water state and the drain command has not been sent, send the drain command - if ( FALSE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) + if ( FALSE == dgCommandSent ) { cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); + dgCommandSent = TRUE; } + else if ( ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) && ( dgCmdResp.rejectCode != DG_CMD_REQUEST_REJECT_REASON_NONE ) ) + { + dgCommandSent = FALSE; + } } else if ( DG_MODE_DRAI == getDGOpMode() ) { // If the drain has started, transition to drain state - state = DRAIN_RESERVOIR_DRAIN_STATE; + dgCommandSent = FALSE; + state = DRAIN_RESERVOIR_DRAIN_STATE; } return state;