Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r3d72b777cf1ceb673d118341c46e2d6d5b7b75f5 -rfeeca8c7b32abfd5e2f8bb8637b0263245d01968 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 3d72b777cf1ceb673d118341c46e2d6d5b7b75f5) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision feeca8c7b32abfd5e2f8bb8637b0263245d01968) @@ -34,12 +34,10 @@ // ********** private definitions ********** -/// Maximum time in this mode before blood sitting alarm given (in general task intervals). -static const U32 MAX_TIME_BLOOD_SITTING = ( ( 5 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); -/// Maximum time in this mode before blood sitting warning given (in general task intervals). -static const U32 WARN_TIME_BLOOD_SITTING = ( ( 4 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); /// Treatment stop status broadcast interval. #define TREATMENT_STOP_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) +/// Target flow rate for re-circulation of saline on blood-side circuit. +#define RECIRC_BP_FLOW_RATE_ML_MIN 100 // ********** private data ********** @@ -53,6 +51,12 @@ static TREATMENT_STOP_STATE_T handleTreatmentStopRecircState( void ); static TREATMENT_STOP_STATE_T handleTreatmentStopNoRecircState( void ); +static void setupForDialysateRecirculationState( void ); +static void setupForBloodRecirculationState( void ); +static TREATMENT_STOP_STATE_T handleTreatmentStopAlarmsAndSignals( TREATMENT_STOP_STATE_T state ); +static TREATMENT_STOP_STATE_T handleTreatmentStopDialysateRecircState( void ); +static TREATMENT_STOP_STATE_T handleTreatmentStopBloodRecircState( void ); +static void handleTreatmentStopBloodSittingTimer( void ); static void publishTreatmentStopData( void ); @@ -95,22 +99,17 @@ } setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - // Ensure all pumps except DPi stopped - signalBloodPumpHardStop(); - signalDialOutPumpHardStop(); + // Ensure syringe pump is stopped stopSyringePump(); - // Start out assuming we re-circulate dialysate while stopped - setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - - // Set valves to safe state + // Set Dialysate valves to bypass filter for recirculation setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - // Stop air trap control - endAirTrapControl(); + setupForBloodRecirculationState(); + + setupForDialysateRecirculationState(); + // Reset saline bolus state in case alarm interrupted one resetSalineBolus(); @@ -132,6 +131,80 @@ /*********************************************************************//** * @brief + * The setupForDialysateRecirculationState function sets actuators appropriately + * for Dialysate recirculation state. + * @details Inputs: none + * @details Outputs: arterial and venous lines opened, blood pump started, + * and air trap leveling control is started. + * @return none + *************************************************************************/ +static void setupForDialysateRecirculationState( void ) +{ + // Re-circulate dialysate side of dialyzer w/ heating to maintain temperature + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + cmdStartDGTrimmerHeater(); +} + +/*********************************************************************//** + * @brief + * The setupForBloodRecirculationState function sets actuators appropriately + * for Blood recirculation state. + * @details Inputs: none + * @details Outputs: arterial and venous lines closed, blood pump started, + * and air trap leveling control is started. + * @return none + *************************************************************************/ +static void setupForBloodRecirculationState( void ) +{ + // Open VBA and VBV valves to patient for blood recirculation + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // Start blood pump at re-circulate flow rate + setBloodPumpTargetFlowRate( RECIRC_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Start air trap leveling control + startAirTrapControl(); + // Reset blood sitting timer, it is now circulating + bloodSittingTimerCtr = 0; +} + +/*********************************************************************//** + * @brief + * The setupForDialysateRecirculationStopState function sets actuators appropriately + * for dialysate re-circulation stopped state. + * @details Inputs: none + * @details Outputs: Blood pump stopped, arterial and venous lines closed, + * and air trap leveling control is stopped. + * @return none + *************************************************************************/ +static void setupForDialysateRecirculationStopState( void ) +{ + // Stop dialysate side of dialyzer and heating + signalDialInPumpHardStop(); + cmdStopDGTrimmerHeater(); +} + +/*********************************************************************//** + * @brief + * The setupForBloodRecirculationStopState function sets actuators appropriately + * for blood re-circulation stopped state. + * @details Inputs: none + * @details Outputs: Blood pump stopped, arterial and venous lines closed, + * and air trap leveling control is stopped. + * @return none + *************************************************************************/ +static void setupForBloodRecirculationStopState( void ) +{ + // Stop blood pump + signalBloodPumpHardStop(); + // Close arterial and venous lines + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + // Stop air trap leveling control + endAirTrapControl(); +} + +/*********************************************************************//** + * @brief * The execTreatmentStop function executes the Treatment Stop sub-mode * state machine. * @details Inputs: none @@ -140,27 +213,21 @@ *************************************************************************/ void execTreatmentStop( void ) { - // Ensure we do not sit in stopped state for too long (if blood in line) - if ( getRinsebackCompleted() != TRUE ) - { - if ( ++bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) - { - activateAlarmNoData( ALARM_ID_BLOOD_SITTING_WARNING ); - } - if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) - { - // Activate the alarm - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_NO_RINSEBACK ); - } - } - // Execute treatment stop sub-mode state machine switch ( currentTxStopState ) { case TREATMENT_STOP_RECIRC_STATE: currentTxStopState = handleTreatmentStopRecircState(); break; + case TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE: + currentTxStopState = handleTreatmentStopDialysateRecircState(); + break; + + case TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE: + currentTxStopState = handleTreatmentStopBloodRecircState(); + break; + case TREATMENT_STOP_NO_RECIRC_STATE: currentTxStopState = handleTreatmentStopNoRecircState(); break; @@ -176,8 +243,61 @@ /*********************************************************************//** * @brief + * The handleTreatmentStopAlarmsAndSignals function handles the Alarms and User Signals + * operations to set new states. + * @details Inputs: state, flags + * @details Outputs: flags handled + * @return next treatment re-circulation state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopAlarmsAndSignals( TREATMENT_STOP_STATE_T state ) +{ + TREATMENT_STOP_STATE_T result = state; + bool bloodRecircBlocked = isBloodRecircBlocked(); + bool dialysateRecircBlocked = isDialysateRecircBlocked(); + + // Both unblocked and not in recirculate both state + if ( (TREATMENT_STOP_RECIRC_STATE != state) && ( FALSE == dialysateRecircBlocked ) + && ( FALSE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationState(); + setupForDialysateRecirculationState(); + result = TREATMENT_STOP_RECIRC_STATE; + } + + // Both blocked and not in stopped state + if ( (TREATMENT_STOP_NO_RECIRC_STATE != state) && ( TRUE == dialysateRecircBlocked ) + && ( TRUE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_NO_RECIRC_STATE; + } + + // Dialysate recirculation blocked and not in blood recirc state + if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) + && ( TRUE == dialysateRecircBlocked ) + && ( FALSE == bloodRecircBlocked ) ) + { + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; + } + + // Blood recirculation blocked and not in dialysate recirc state + if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) + && ( TRUE == bloodRecircBlocked ) + && ( FALSE == dialysateRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleTreatmentStopRecircState function handles the re-circ dialysate - * state operations. + * and blood state operations. * @details Inputs: active alarms * @details Outputs: dialysate re-circulation stopped if active alarm blocks * @return next treatment stop state @@ -186,19 +306,49 @@ { TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECIRC_STATE; - // if any active alarm(s) blocks dialysate re-circulation, stop it - if ( TRUE == isDialysateRecircBlocked() ) - { - signalDialInPumpHardStop(); - cmdStopDGTrimmerHeater(); - result = TREATMENT_STOP_NO_RECIRC_STATE; - } + result = handleTreatmentStopAlarmsAndSignals( result ); return result; } /*********************************************************************//** * @brief + * The handleTreatmentStopDialysateRecircState function handles the Dialysate only + * re-circulating state operations. + * @details Inputs: flags + * @details Outputs: flags handled + * @return next treatment re-circulation state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopDialysateRecircState( void ) +{ + TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; + + handleTreatmentStopBloodSittingTimer(); + + result = handleTreatmentStopAlarmsAndSignals(result); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentStopBloodRecircState function handles the Blood only + * re-circulating state operations. + * @details Inputs: flags + * @details Outputs: flags handled + * @return next treatment re-circulation state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopBloodRecircState( void ) +{ + TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; + + result = handleTreatmentStopAlarmsAndSignals(result); + + return result; +} + +/*********************************************************************//** + * @brief * The handleTreatmentStopNoRecircState function handles the no re-circ dialysate * state operations. * @details Inputs: none @@ -209,13 +359,44 @@ { TREATMENT_STOP_STATE_T result = TREATMENT_STOP_NO_RECIRC_STATE; - // nothing to do in this state - alarm user response will take us to appropriate next sub-mode + handleTreatmentStopBloodSittingTimer(); + result = handleTreatmentStopAlarmsAndSignals(result); + return result; } /*********************************************************************//** * @brief + * The handleTreatmentStopBloodSittingTimer function handles the no re-circ + * blood timer. It should only be called when Blood is NOT circulating. + * Increments and checks for warning and alarm timeouts. + * @details Inputs: none + * @details Outputs: none + * @return next treatment stop state + *************************************************************************/ +static void handleTreatmentStopBloodSittingTimer( void ) +{ + // Ensure we do not sit in stopped state for too long (if blood in line) + if ( getRinsebackCompleted() != TRUE ) + { + if ( ++bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) + { + activateAlarmNoData( ALARM_ID_BLOOD_SITTING_WARNING ); + } + if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) + { + // Activate the alarm + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_NO_RINSEBACK ); + } + } + else + { + bloodSittingTimerCtr = 0; + } +} +/*********************************************************************//** + * @brief * The getCurrentTreatmentStopState function returns the current state of the * treatment stop sub-mode. * @details Inputs: currentTxStopState @@ -241,15 +422,18 @@ { TREATMENT_STOP_PAYLOAD_T data; - data.timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + // Set to zero so UI will not update unless needed below + data.timeout = 0; + data.countdown = 0; + if ( getRinsebackCompleted() != TRUE ) { - data.countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + if ( bloodSittingTimerCtr > 0 ) + { + data.timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + data.countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + } } - else - { - data.countdown = 0; - } stopPublishTimerCtr = 0; broadcastData( MSG_ID_HD_TREATMENT_STOP_TIMER_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_STOP_PAYLOAD_T ) ); }