Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rd91a24c730aeb5cd7e3eba9ef4eca78e442911f8 -ra4f5ed3748870d287a4c2c6fcc003fc4d3b9233f --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision d91a24c730aeb5cd7e3eba9ef4eca78e442911f8) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision a4f5ed3748870d287a4c2c6fcc003fc4d3b9233f) @@ -23,7 +23,9 @@ #include "Dialysis.h" #include "DialInFlow.h" #include "DialOutFlow.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "ModeTreatment.h" @@ -39,8 +41,12 @@ #define MAX_UF_RATE_ACCURACY_ERROR_ML_HR 100.0 ///< Maximum ultrafiltration rate accuracy error in mL/hr over each hour of treatment. #define MAX_UF_RATE_ACCURACY_ERROR_PCT 0.05 ///< Minimum ultrafilteration rate accuracy in percentage of set point (5%) over each hour of treatment. #define MAX_UF_ACCURACY_ERROR_ML 250.0 ///< Maximum ultrafiltration accuracy error in mL over the entire treatment. -#define UF_ACCURACY_CHECK_INTERVAL ((1 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL) ///< Ultrafiltration rate accuracy check interval count +/// Ultrafiltration rate accuracy check interval count +#define UF_ACCURACY_CHECK_INTERVAL ((1 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL) +#define MAX_SALINE_VOLUME_DELIVERED 800.0 ///< Maximum saline volume delivered for a treatment. +#define SALINE_BOLUS_RATE_ML_MIN 150 ///< Fixed rate for saline bolus delivery. + // ********** private data ********** static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. @@ -60,8 +66,15 @@ static U32 setDialysateFlowRate; ///< Currently set dialysate flow rate (from prescription). static F32 maxUFVolumeML; ///< Currently set total ultrafiltration volume for treatment (from prescription). static F32 setUFRate; ///< Currently set ultrafiltration rate (from prescription). -static F32 maxUFRateAccuracyError_Ml_hr; ///< Minimum ultrafiltration rate accuracy over 1 hour duration (5% or 100 mL, whichever is greater). +static F32 maxUFRateAccuracyError_Ml_hr; ///< Minimum ultrafiltration rate accuracy over 1 hour duration (5% or 100 mL, whichever is greater). +static BOOL salineBolusStartRequested; ///< Flag indicates a saline bolus start has been requested by user. +static BOOL salineBolusAbortRequested; ///< Flag indicates a salien bolus abort has been requested by user. +static BOOL salineBolusAutoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. +static F32 totalSalineVolumeDelivered; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). +static F32 bolusSalineVolumeDelivered; ///< Volume (mL) of current bolus delivered so far. +static F32 bolusSalineVolumeDelivered_Safety; ///< Volume (mL) of current bolus delivered so far according to safety monitor. + static U32 uFAccuracyCheckTimerCtr; ///< Timer counter to determine when next to check ultrafiltration accuracy. static F32 lastUFVolumeChecked; ///< Starting ultrafiltration volume for accuracy check. @@ -70,12 +83,16 @@ static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ); -static UF_STATE_T handleUFStartState( void ); -static UF_STATE_T handleUFPausedState( void ); -static UF_STATE_T handleUFRunningState( void ); -static UF_STATE_T handleUFOffState( void ); -static UF_STATE_T handleUFCompletedState( void ); +static UF_STATE_T handleUFStartState( DIALYSIS_STATE_T *dialysisState ); +static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); +static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); +static UF_STATE_T handleUFOffState( DIALYSIS_STATE_T *dialysisState ); +static UF_STATE_T handleUFCompletedState( DIALYSIS_STATE_T *dialysisState ); +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( DIALYSIS_STATE_T *dialysisState ); +static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); +static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); + static void checkUFAccuracyAndVolume( void ); static void updateUFVolumes( void ); @@ -112,6 +129,10 @@ setUFRate = 0.0; maxUFRateAccuracyError_Ml_hr = MAX_UF_RATE_ACCURACY_ERROR_ML_HR; + salineBolusStartRequested = FALSE; + salineBolusAbortRequested = FALSE; + salineBolusAutoResumeUF = FALSE; + uFAccuracyCheckTimerCtr = 0; lastUFVolumeChecked = 0.0; } @@ -222,6 +243,90 @@ /*********************************************************************//** * @brief + * The signalStartSalineBolus function handles user request to initiate a + * saline bolus. + * @details Inputs: TBD + * @details Outputs: TBD + * @return none + *************************************************************************/ +void signalStartSalineBolus( void ) +{ + BOOL accept = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + U32 salineBolusVolume = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + HD_OP_MODE_T currOpMode = getCurrentOperationMode(); + TREATMENT_STATE_T currTreatSubMode = getTreatmentState(); + SALINE_BOLUS_STATE_T currSalineBolusState = getSalineBolusState(); + + // must be in treatment mode, dialysis sub-mode, saline bolus in idle state in order to start a saline bolus + if ( currOpMode != MODE_TREA ) + { + rejReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; + } + else if ( currTreatSubMode != TREATMENT_DIALYSIS_STATE ) + { + rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + else if ( currSalineBolusState != SALINE_BOLUS_STATE_IDLE ) + { + rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; + } + else if ( totalSalineVolumeDelivered >= MAX_SALINE_VOLUME_DELIVERED ) + { + rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; + } + else + { + accept = TRUE; + salineBolusStartRequested = TRUE; + } + + // send response + sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); +} + +/*********************************************************************//** + * @brief + * The signalAbortSalineBolus function handles user request to abort a + * saline bolus. + * @details Inputs: TBD + * @details Outputs: TBD + * @return none + *************************************************************************/ +void signalAbortSalineBolus( void ) +{ + BOOL accept = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + U32 salineBolusVolume = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + HD_OP_MODE_T currOpMode = getCurrentOperationMode(); + TREATMENT_STATE_T currTreatSubMode = getTreatmentState(); + SALINE_BOLUS_STATE_T currSalineBolusState = getSalineBolusState(); + + // must be in treatment mode, dialysis sub-mode, saline bolus in delivery state in order to abort a saline bolus + if ( currOpMode != MODE_TREA ) + { + rejReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; + } + else if ( currTreatSubMode != TREATMENT_DIALYSIS_STATE ) + { + rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + else if ( currSalineBolusState != SALINE_BOLUS_STATE_IN_PROGRESS ) + { + rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_NOT_IN_PROGRESS; + } + else + { + accept = TRUE; + salineBolusAbortRequested = TRUE; + } + + // send response + sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); +} + +/*********************************************************************//** + * @brief * The getDialysisState function gets the current dialysis state (sub-mode). * @details * Inputs : currentDialysisState @@ -425,27 +530,28 @@ switch ( currentUFState ) { case UF_START_STATE: - currentUFState = handleUFStartState(); + currentUFState = handleUFStartState( &result ); break; case UF_PAUSED_STATE: - currentUFState = handleUFPausedState(); + currentUFState = handleUFPausedState( &result ); break; case UF_RUNNING_STATE: - currentUFState = handleUFRunningState(); + currentUFState = handleUFRunningState( &result ); break; case UF_OFF_STATE: - currentUFState = handleUFOffState(); + currentUFState = handleUFOffState( &result ); break; case UF_COMPLETED_STATE: - currentUFState = handleUFCompletedState(); + currentUFState = handleUFCompletedState( &result ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_UF_STATE, currentUFState ) + currentUFState = UF_COMPLETED_STATE; break; } @@ -465,8 +571,26 @@ { DIALYSIS_STATE_T result = DIALYSIS_SALINE_BOLUS_STATE; - // TODO - + switch ( currentSalineBolusState ) + { + case SALINE_BOLUS_STATE_IDLE: + currentSalineBolusState = handleSalineBolusIdleState( &result ); + break; + case SALINE_BOLUS_STATE_IN_PROGRESS: + currentSalineBolusState = handleSalineBolusInProgressState( &result ); + break; + + case SALINE_BOLUS_STATE_MAX_DELIVERED: + currentSalineBolusState = handleSalineBolusMaxDeliveredState( &result ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_SALINE_BOLUS_STATE, currentSalineBolusState ) + currentSalineBolusState = SALINE_BOLUS_STATE_MAX_DELIVERED; + break; + } + return result; } @@ -478,9 +602,10 @@ * Inputs : maxUFVolumeML * Outputs : if ultrafiltration prescribed, ultrafiltration time is * initialized. + * @param dialysisState next dialysis state * @return next ultrafiltration state. *************************************************************************/ -static UF_STATE_T handleUFStartState( void ) +static UF_STATE_T handleUFStartState( DIALYSIS_STATE_T *dialysisState ) { UF_STATE_T result; @@ -505,15 +630,38 @@ * @details * Inputs : none * Outputs : if ultrafiltration resumption requested, UF time is set to resume. + * @param dialysisState next dialysis state * @return next ultrafiltration state. *************************************************************************/ -static UF_STATE_T handleUFPausedState( void ) +static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ) { UF_STATE_T result = UF_PAUSED_STATE; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); + // handle saline bolus start request from user + if ( TRUE == salineBolusStartRequested ) + { + salineBolusAutoResumeUF = FALSE; + // go to saline bolus state + if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + { + *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; + } + } + // handle auto-resume after saline bolus + else if ( TRUE == salineBolusAutoResumeUF ) + { + salineBolusAutoResumeUF = FALSE; + // set outlet pump to dialysate rate + set UF rate + setDialOutPumpTargetRate( setDialysateFlowRate + FLOAT_TO_INT_WITH_ROUND( setUFRate ), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // restart UF time accumulation for reference volume calculation + lastUFTimeStamp = getMSTimerCount(); + // resume UF + result = UF_RUNNING_STATE; + } + // TODO - test code - remove later if ( TRUE == isStopButtonPressed() ) { @@ -532,9 +680,10 @@ * Inputs : ms timer, lastUFTimeStamp * Outputs : UF timer incremented, UF volumes updated and provided to DPo * pump controller. + * @param dialysisState next dialysis state * @return next ultrafiltration state. *************************************************************************/ -static UF_STATE_T handleUFRunningState( void ) +static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ) { UF_STATE_T result = UF_RUNNING_STATE; U32 newTime = getMSTimerCount(); @@ -555,6 +704,21 @@ { result = UF_COMPLETED_STATE; } + // handle saline bolus start request from user + else if ( TRUE == salineBolusStartRequested ) + { + if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + { + // set outlet pump to dialysate rate + setDialOutPumpTargetRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // since we were doing UF prior to saline bolus, we want to auto-resume when done + salineBolusAutoResumeUF = TRUE; + // go to UF paused state + result = UF_PAUSED_STATE; + // go to saline bolus state + *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; + } + } // TODO - test code - remove later if ( TRUE == isStopButtonPressed() ) @@ -573,15 +737,27 @@ * @details * Inputs : none * Outputs : UF volumes updated and provided to DPo pump controller. + * @param dialysisState next dialysis state * @return next ultrafiltration state *************************************************************************/ -static UF_STATE_T handleUFOffState( void ) +static UF_STATE_T handleUFOffState( DIALYSIS_STATE_T *dialysisState ) { UF_STATE_T result = UF_OFF_STATE; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); + // handle saline bolus start request from user + if ( TRUE == salineBolusStartRequested ) + { + salineBolusAutoResumeUF = FALSE; + // go to saline bolus state + if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + { + *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; + } + } + return result; } @@ -592,20 +768,86 @@ * @details * Inputs : none * Outputs : UF volumes updated and provided to DPo pump controller. + * @param dialysisState next dialysis state * @return next ultrafiltration state *************************************************************************/ -static UF_STATE_T handleUFCompletedState( void ) +static UF_STATE_T handleUFCompletedState( DIALYSIS_STATE_T *dialysisState ) { UF_STATE_T result = UF_COMPLETED_STATE; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); + // handle saline bolus start request from user + if ( TRUE == salineBolusStartRequested ) + { + salineBolusAutoResumeUF = FALSE; + // go to saline bolus state + if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + { + *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; + } + } + return result; } /*********************************************************************//** * @brief + * The handleSalineBolusIdleState function handles the idle state of the + * saline bolus state machine. + * @details Inputs: none + * @details Outputs: + * @param dialysisState next dialysis state + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( DIALYSIS_STATE_T *dialysisState ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IDLE; + + // handle saline bolus start request from user + if ( TRUE == salineBolusStartRequested ) + { + salineBolusStartRequested = FALSE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleSalineBolusInProgressState function handles the in-progress state of the + * saline bolus state machine. + * @details Inputs: none + * @details Outputs: + * @param dialysisState next dialysis state + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IN_PROGRESS; + + return result; +} + +/*********************************************************************//** + * @brief + * The handleSalineBolusMaxDeliveredState function handles the max saline delivered + * state of the saline bolus state machine. This is a terminal state. + * @details Inputs: none + * @details Outputs: + * @param dialysisState next dialysis state + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_MAX_DELIVERED; + + return result; +} + +/*********************************************************************//** + * @brief * The checkUF function checks ultrafiltration accuracy for the last * hour and checks total UF volume. Triggers an alarm if out of spec. * @details