Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r30f049651877229042e3f8700c8596e5b9a1e0f4 -r0c3533ac1aa509678a73a8177d648080fa567203 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 30f049651877229042e3f8700c8596e5b9a1e0f4) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 0c3533ac1aa509678a73a8177d648080fa567203) @@ -16,9 +16,14 @@ ***************************************************************************/ #include "AirTrap.h" -#include "Buttons.h" +#include "BloodFlow.h" +#include "DGInterface.h" +#include "DialInFlow.h" +#include "DialOutFlow.h" #include "ModeTreatment.h" #include "OperationModes.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" #include "TreatmentStop.h" #include "Valves.h" @@ -27,10 +32,26 @@ * @{ */ +// ********** private definitions ********** + +/// Maximum time in this mode before blood sitting warning given (in general task intervals). +static const U32 MAX_TIME_BLOOD_SITTING = ( ( 5 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); +/// Treatment stop status broadcast interval. +static const U32 TREATMENT_STOP_DATA_PUBLISH_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + // ********** private data ********** +static TREATMENT_STOP_STATE_T currentTxStopState; ///< Current treatment stop state. +static U32 bloodSittingTimerCtr; ///< Timer counter tracks time in this mode while blood is sitting. +static U32 stopPublishTimerCtr; ///< Timer counter (in GP task intervals) counts time to next status broadcast. + // ********** private function prototypes ********** +static TREATMENT_STOP_STATE_T handleTreatmentStopRecircState( void ); +static TREATMENT_STOP_STATE_T handleTreatmentStopNoRecircState( void ); + +static void publishTreatmentStopData( void ); + /*********************************************************************//** * @brief * The initTreatmentStop function initializes the Treatment Stop sub-mode @@ -41,6 +62,9 @@ *************************************************************************/ void initTreatmentStop( void ) { + currentTxStopState = TREATMENT_STOP_RECIRC_STATE; + bloodSittingTimerCtr = 0; + stopPublishTimerCtr = 0; } /*********************************************************************//** @@ -53,17 +77,56 @@ *************************************************************************/ void transitionToTreatmentStop( void ) { + // Set user alarm recovery actions allowed in this sub-mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); + + // Ensure all pumps except DPi stopped + signalBloodPumpHardStop(); + signalDialOutPumpHardStop(); + 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 setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - // Reset saline bolus state in case alarm interrupted one - resetSalineBolus(); // Stop air trap control endAirTrapControl(); - // Should always have stopped alarm active in treatment stop sub-mode so that user can take action - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); + + // Reset saline bolus state in case alarm interrupted one + resetSalineBolus(); + + // Should always have an alarm active in treatment stop sub-mode so that user can take action + if ( FALSE == isAnyAlarmActive() ) + { + if ( FALSE == getRinsebackCompleted() ) + { + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_AFTER_RINSEBACK ); + } + else + { + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); + } + // coming back to stop state via non-alarm path, so no audio - just want alarm for its options + signalAlarmSilence( ALARM_SILENCE_CMD_CANCEL ); + } + + // Set user alarm recovery actions allowed in this sub-mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + if ( TRUE == getRinsebackCompleted() ) + { // block rinseback action if already done + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); + } + else + { + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); + } + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); } /*********************************************************************//** @@ -76,7 +139,104 @@ *************************************************************************/ void execTreatmentStop( void ) { - // TODO - implement + // Ensure we do not sit in stopped state for too long + if ( ++bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) + { + // TODO has this error been removed? + //activateAlarmNoData( ALARM_ID_BLOOD_SITTING_TOO_LONG_NO_RINSEBACK ); + } + + // Execute treatment stop sub-mode state machine + switch ( currentTxStopState ) + { + case TREATMENT_STOP_RECIRC_STATE: + currentTxStopState = handleTreatmentStopRecircState(); + break; + + case TREATMENT_STOP_NO_RECIRC_STATE: + currentTxStopState = handleTreatmentStopNoRecircState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_TREATMENT_STOP_INVALID_STATE, currentTxStopState ); + break; + } + + // Broadcast treatment stop status + publishTreatmentStopData(); } +/*********************************************************************//** + * @brief + * The handleTreatmentStopRecircState function handles the re-circ dialysate + * state operations. + * @details Inputs: active alarms + * @details Outputs: dialysate re-circulation stopped if active alarm blocks + * @return next treatment stop state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopRecircState( void ) +{ + 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; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentStopNoRecircState function handles the no re-circ dialysate + * state operations. + * @details Inputs: none + * @details Outputs: none + * @return next treatment stop state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopNoRecircState( void ) +{ + 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 + + return result; +} + +/*********************************************************************//** + * @brief + * The getCurrentTreatmentStopState function returns the current state of the + * treatment stop sub-mode. + * @details Inputs: currentTxStopState + * @details Outputs: none + * @return currentTxStopState + *************************************************************************/ +TREATMENT_STOP_STATE_T getCurrentTreatmentStopState( void ) +{ + return currentTxStopState; +} + +/*********************************************************************//** + * @brief + * The publishTreatmentStopData function publishes treatment stop progress to UI + * at 1 Hz interval. + * @details Inputs: stopPublishTimerCtr, bloodSittingTimerCtr + * @details Outputs: treatment stop data published + * @return none + *************************************************************************/ +static void publishTreatmentStopData( void ) +{ + if ( ++stopPublishTimerCtr >= TREATMENT_STOP_DATA_PUBLISH_INTERVAL ) + { + U32 timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + U32 countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + + stopPublishTimerCtr = 0; + broadcastTreatmentStopData( timeout, countdown ); + } +} + /**@}*/