Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rfba69244d94307e50fefaa1e88bcbb979584461e -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision fba69244d94307e50fefaa1e88bcbb979584461e) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -29,6 +29,7 @@ #include "OperationModes.h" #include "PresOccl.h" #include "Reservoirs.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -44,12 +45,6 @@ #define MAX_UF_VOLUME_ACCURACY_ERROR_ML 100.0F ///< Maximum ultrafiltration volume accuracy error in mL over the entire treatment. #define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 20.0F ///< Reservoir load cell drift difference allowed -/// Saline bolus data broadcast interval (ms/task time) count. -static const U32 SALINE_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - -#define MAX_SALINE_VOLUME_DELIVERED 800 ///< Maximum saline volume delivered for a treatment. -#define SALINE_BOLUS_RATE_ML_MIN 300 ///< Fixed rate for saline bolus delivery. - #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. // 3.07 + 12.28 has been received from the mechanical team and extra volume as margin has been added for safety @@ -86,9 +81,8 @@ BLOOD_LEAK_ZEROING_STATE_T bloodLeakZeroingState; ///< Blood leak zeroing state. } BLOOD_LEAK_ZEROING_T ; -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 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). static F32 resStartVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir start volume for ultrafiltration (i.e. where did we start with each reservoir). @@ -98,7 +92,7 @@ static F32 resCurrVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir current volume. static F32 resLastVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Previous reading of reservoir volume. static F32 measUFVolumeFromPriorReservoirs; ///< Current total ultrafiltration volume from previous reservoirs in current treatment. -static F32 lcLastSteadyWeight[NUM_OF_RESERVOIR_STEADY_CYCLES][NUM_OF_LOAD_CELLS]; ///< Load Cell Last Steady Weight for drift test Start/Final cycle +static F32 lcLastSteadyWeight[ NUM_OF_RESERVOIR_STEADY_CYCLES ][ NUM_OF_LOAD_CELLS ]; ///< Load Cell Last Steady Weight for drift test Start/Final cycle static U32 uFTimeMS; ///< Current elapsed ultrafiltration time (in ms). Used for calculating UF reference volume. static U32 lastUFTimeStamp; ///< HD timer value when we last took stock of ultrafiltration time (so we can determine how much time has elapsed since). @@ -108,13 +102,7 @@ static F32 setUFVolumeML; ///< Currently set total ultrafiltration volume for treatment (from prescription). static F32 setUFRate; ///< Currently set ultrafiltration rate (from prescription). -static U32 salineBolusBroadcastTimerCtr; ///< Saline bolus data broadcast timer counter used to schedule when to transmit data. -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 autoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. -static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). -static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). -static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. static BLOOD_LEAK_ZEROING_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // ********** private function prototypes ********** @@ -126,11 +114,6 @@ static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ); -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ); -static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); - static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ); static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushReservoir2DPiState( void ); static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushDPi2BLDState( void ); @@ -141,7 +124,7 @@ static void checkUFControl( void ); static void updateUFVolumes( void ); -static void publishSalineBolusData( void ); +//static void publishSalineBolusData( void ); static void checkLoadCellsStablePrimaryBackupDriftOutOfRange( DG_RESERVOIR_ID_T reservoirID, RESERVOIR_STEADY_CYCLE_T cycle ); /*********************************************************************//** @@ -159,7 +142,6 @@ currentDialysisState = DIALYSIS_UF_STATE; currentUFState = UF_RUNNING_STATE; - currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; lastUFTimeStamp = getMSTimerCount(); uFTimeMS = 0; @@ -178,14 +160,12 @@ setUFRate = 0.0; resetDialOutRateOffset(); - salineBolusBroadcastTimerCtr = 0; - totalSalineVolumeDelivered_mL = 0.0; autoResumeUF = FALSE; for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_START][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; - lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_FINAL][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; + lcLastSteadyWeight[ RESERVOIR_STEADY_CYCLE_START ][ i ] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; + lcLastSteadyWeight[ RESERVOIR_STEADY_CYCLE_FINAL ][ i ] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; } for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) @@ -202,27 +182,16 @@ /*********************************************************************//** * @brief - * The resetSalineBolus function initializes the saline bolus variables - * at start of treatment or after stopping a bolus (e.g. alarm). Total - * saline bolus volume delivered will not be affected by this function. + * The resetUF function resets the ultrafiltration state and status. * @details Inputs: autoResumeUF - * @details Outputs: salineBolusStartRequested, salineBolusAbortRequested, - * bolusSalineVolumeDelivered_mL, currentSalineBolusState, autoResumeUF, - * currentUFState, currentDialysisState + * @details Outputs: autoResumeUF, currentUFState, currentDialysisState * @return none *************************************************************************/ -void resetSalineBolus( void ) +void resetUF( void ) { - salineBolusStartRequested = FALSE; - salineBolusAbortRequested = FALSE; - bolusSalineVolumeDelivered_mL = 0.0; - if ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) - { - currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; - } if ( TRUE == autoResumeUF ) { - autoResumeUF = FALSE; + autoResumeUF = FALSE; currentUFState = UF_RUNNING_STATE; } currentDialysisState = DIALYSIS_UF_STATE; @@ -418,91 +387,6 @@ /*********************************************************************//** * @brief - * The signalStartSalineBolus function handles user request to initiate a - * saline bolus. - * @details Inputs: set bolus volume, current mode/sub-mode, bolus state - * @details Outputs: salineBolusStartRequested, response sent - * @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(); - - // 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 ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; - } - else if ( DIALYSIS_SALINE_BOLUS_STATE == currentDialysisState ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; - } - else - { - accept = TRUE; - salineBolusStartRequested = TRUE; - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - } - - // Send response - sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); -} - -/*********************************************************************//** - * @brief - * The signalAbortSalineBolus function handles user request to abort a - * saline bolus. - * @details Inputs: set bolus volume, current mode/sub-mode, bolus state - * @details Outputs: salineBolusAbortRequested, response sent - * @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; - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - } - - // Send response - sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); -} - -/*********************************************************************//** - * @brief * The getDialysisState function gets the current dialysis state (sub-mode). * @details Inputs: currentDialysisState * @details Outputs: none @@ -527,18 +411,6 @@ /*********************************************************************//** * @brief - * The getSalineBolusState function gets the current saline bolus state. - * @details Inputs: currentSalineBolusState - * @details Outputs: none - * @return currentSalineBolusState - *************************************************************************/ -SALINE_BOLUS_STATE_T getSalineBolusState( void ) -{ - return currentSalineBolusState; -} - -/*********************************************************************//** - * @brief * The getBloodLeakZeroingState function gets the current blood leak zeroing * state of the state machine. * @details Inputs: bloodLeakZeroingStatus @@ -578,19 +450,6 @@ /*********************************************************************//** * @brief - * The getTotalSalineBolusVolumeDelivered function gets the current total - * saline volume delivered. - * @details Inputs: totalSalineVolumeDelivered - * @details Outputs: none - * @return totalSalineVolumeDelivered - *************************************************************************/ -F32 getTotalSalineBolusVolumeDelivered( void ) -{ - return totalSalineVolumeDelivered_mL; -} - -/*********************************************************************//** - * @brief * The pauseUF function pauses ultrafiltration. * @details Inputs: currentDialysisState, currentUFState, setUFRate * @details Outputs: currentUFState, outlet pump set point @@ -754,8 +613,9 @@ setCurrentSubState( (U32)currentDialysisState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDialysisState ); } + // Publish saline bolus data at set interval (whether we are delivering one or not) - publishSalineBolusData(); + publishSalineBolusData( bloodLeakZeroingStatus.DPi2BLDFlushedVolML, bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML, (U32)bloodLeakZeroingStatus.zeroingRequestState ); } /*********************************************************************//** @@ -816,41 +676,31 @@ *************************************************************************/ static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ) { - DIALYSIS_STATE_T result = DIALYSIS_SALINE_BOLUS_STATE; + DIALYSIS_STATE_T result = DIALYSIS_SALINE_BOLUS_STATE; + SALINE_BOLUS_STATE_T currSalineBolusState = execSalineBolus(); - SALINE_BOLUS_STATE_T priorSubState = currentSalineBolusState; - - switch ( currentSalineBolusState ) + if ( currSalineBolusState != SALINE_BOLUS_STATE_IN_PROGRESS ) { - case SALINE_BOLUS_STATE_IDLE: - currentSalineBolusState = handleSalineBolusIdleState(); - break; + result = DIALYSIS_UF_STATE; - case SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP: - currentSalineBolusState = handleSalineBolusWait4Pumps2Stop(); - 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; + if ( ( FALSE == isAlarmActive( ALARM_ID_HD_EMPTY_SALINE_BAG ) ) && ( currSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) ) + { + // Resume UF if appropriate + if ( TRUE == autoResumeUF ) + { + autoResumeUF = FALSE; + currentUFState = UF_RUNNING_STATE; + //Set substate for event + setCurrentSubState( (U32)DIALYSIS_UF_STATE ); + setCurrent4thLevelState( (U32)currentUFState ); + sendOperationStatusEvent(); + } + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Resume dialysis + transitionToDialysis(); + } } - // MAX DELIVERED transitions different and sends the event on its own. - if ( priorSubState != currentSalineBolusState && currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) - { - setCurrent4thLevelState( (U32)currentSalineBolusState ); - SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentSalineBolusState ); - } - return result; } @@ -885,18 +735,18 @@ UF_STATE_T result = UF_PAUSED_STATE; // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) + if ( TRUE == isSalineBolusStartRequested() ) { autoResumeUF = FALSE; // Go to saline bolus state if we can - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + if ( SALINE_BOLUS_STATE_IDLE == getSalineBolusState() ) { *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - setCurrent4thLevelState( (U32)currentSalineBolusState ); + setCurrent4thLevelState( (U32)getSalineBolusState() ); } else { - salineBolusStartRequested = FALSE; + setSalineBolusStartRequestStatus( FALSE ); } } else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) @@ -947,21 +797,21 @@ } // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) + if ( TRUE == isSalineBolusStartRequested() ) { - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + if ( SALINE_BOLUS_STATE_IDLE == getSalineBolusState() ) { // Since we were doing UF prior to saline bolus, we want to auto-resume when done autoResumeUF = TRUE; // Go to UF paused state result = UF_PAUSED_STATE; // Go to saline bolus state *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - setCurrent4thLevelState( (U32)currentSalineBolusState ); + setCurrent4thLevelState( (U32)getSalineBolusState() ); } else { - salineBolusStartRequested = FALSE; + setSalineBolusStartRequestStatus( FALSE ); } } else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) @@ -984,177 +834,6 @@ /*********************************************************************//** * @brief - * The handleSalineBolusIdleState function handles the idle state of the - * saline bolus state machine. - * @details Inputs: none - * @details Outputs: - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IDLE; - - // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) - { - salineBolusStartRequested = FALSE; - // Cmd all pumps to stop - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - stopSyringePump(); - // Begin saline bolus - result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSalineBolusWait4Pumps2Stop function handles the wait for pumps - * to stop state of the saline bolus state machine. - * @details Inputs: none - * @details Outputs: - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; - - if ( ( FALSE == isBloodPumpRunning() ) && ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) - { - // Reset bolus data before we start - bolusSalineVolumeDelivered_mL = 0.0; - bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - - // Bypass dialyzer - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - // Switch to saline bag - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - // Start blood pump at saline bolus rate - setBloodPumpTargetFlowRate( SALINE_BOLUS_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Start dialysate inlet pump at re-circ rate - setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Begin saline bolus - result = SALINE_BOLUS_STATE_IN_PROGRESS; - } - - 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; - BOOL errorFound = FALSE; - F32 timeSinceLastVolumeUpdateMin = (F32)calcTimeSince( bolusSalineLastVolumeTimeStamp ) / (F32)( MS_PER_SECOND * SEC_PER_MIN ); - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - F32 bldFlowRate = getMeasuredBloodFlowRate(); - F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; - F32 expVolSinceLastUpdateMl = (F32)getTargetBloodFlowRate() * timeSinceLastVolumeUpdateMin; - - // Update saline bolus volumes - bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; - totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; - - // Check for empty saline bag per arterial line pressure - if ( TRUE == isSalineBagEmpty() ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_EMPTY_SALINE_BAG, getMeasuredArterialPressure() ); - errorFound = TRUE; - result = SALINE_BOLUS_STATE_IDLE; - } - - // Determine if we have reached maximum saline delivery volume - if ( ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) - { - result = SALINE_BOLUS_STATE_MAX_DELIVERED; - setCurrent4thLevelState( (U32)result ); - sendOperationStatusEvent(); - } - else - { - // Determine if bolus is complete - if ( bolusSalineVolumeDelivered_mL >= bolusTargetVolume ) - { - result = SALINE_BOLUS_STATE_IDLE; - } - // User is aborting saline bolus - else if ( TRUE == salineBolusAbortRequested ) - { - salineBolusAbortRequested = FALSE; - result = SALINE_BOLUS_STATE_IDLE; - } - } - - // Are we stopping the bolus? - if ( result != SALINE_BOLUS_STATE_IN_PROGRESS ) - { - // Hard stop blood and dialysate pumps - signalBloodPumpHardStop(); - signalDialInPumpHardStop(); - // Send last saline bolus data - salineBolusBroadcastTimerCtr = SALINE_BOLUS_DATA_PUB_INTERVAL; - publishSalineBolusData(); - sendTreatmentLogEventData( SALINE_BOLUSES_CHANGE_EVENT, bolusSalineVolumeDelivered_mL, totalSalineVolumeDelivered_mL ); - bolusSalineVolumeDelivered_mL = 0.0; - // Dialysis back to UF state - *dialysisState = DIALYSIS_UF_STATE; - // End dialyzer bypass and resume dialysis if no alarms triggered - if ( FALSE == errorFound ) - { - // Resume UF if appropriate - if ( TRUE == autoResumeUF ) - { - autoResumeUF = FALSE; - currentUFState = UF_RUNNING_STATE; - //Set substate for event - setCurrentSubState( (U32)DIALYSIS_UF_STATE ); - setCurrent4thLevelState( (U32)currentUFState ); - sendOperationStatusEvent(); - } - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - // Resume dialysis - transitionToDialysis(); - } - } - - 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; - - // This is a terminal state for a given treatment - no more saline may be delivered to patient - // If we get here, pop back to UF - *dialysisState = DIALYSIS_UF_STATE; - - return result; -} - -/*********************************************************************//** - * @brief * The handleBloodLeakZeroingIdleState function handles the blood leak zeroing * idle state. In this state the actuators and parameters are set to run * the blood leak zeroing state machine. @@ -1332,33 +1011,6 @@ /*********************************************************************//** * @brief - * The publishSalineBolusData 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 void publishSalineBolusData( void ) -{ - if ( ++salineBolusBroadcastTimerCtr >= SALINE_BOLUS_DATA_PUB_INTERVAL ) - { - SALINE_BOLUS_DATA_PAYLOAD_T data; - - data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; - data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; - data.bloodLeakZeroingDPi2BLDFlushVolumeML = bloodLeakZeroingStatus.DPi2BLDFlushedVolML; - data.bloodLeakZeroingRsrvr2DPiFlushVolumeML = bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML; - data.bloodLeakZeroingNeededAfterRsrvrSwitch = (U32)bloodLeakZeroingStatus.zeroingRequestState; - - broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); - salineBolusBroadcastTimerCtr = 0; - } -} - -/*********************************************************************//** - * @brief * The checkUFControl function checks ultrafiltration control to ensure measured * UF volume does not deviate too far from the UF reference volume (indicating * poor UF control). Index: firmware/App/Modes/Dialysis.h =================================================================== diff -u -rfba69244d94307e50fefaa1e88bcbb979584461e -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision fba69244d94307e50fefaa1e88bcbb979584461e) +++ firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -36,25 +36,10 @@ // ********** public definitions ********** -#pragma pack(push,1) - -/// Payload record structure for a saline bolus data broadcast message. -typedef struct -{ - U32 tgtSalineVolumeMl; ///< Target saline volume in mL. - F32 cumSalineVolumeMl; ///< Cumulative saline volume in mL. - F32 bolSalineVolumeMl; ///< Bolus saline volume in mL. - F32 bloodLeakZeroingDPi2BLDFlushVolumeML; ///< Blood leak zeroing DPi to BLD flush volume in mL. - F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML; ///< Blood leak zeroing reservoir to DPi flush volume in mL. - U32 bloodLeakZeroingNeededAfterRsrvrSwitch; ///< Blood leak zeroing needed after reservoir switch. -} SALINE_BOLUS_DATA_PAYLOAD_T; - -#pragma pack(pop) - // ********** public function prototypes ********** void initDialysis( void ); -void resetSalineBolus( void ); +void resetUF( void ); void transitionToDialysis( void ); void execDialysis( void ); @@ -63,17 +48,12 @@ void stopDialysis( void ); void startHeparinPump( void ); -void signalStartSalineBolus( void ); -void signalAbortSalineBolus( void ); - DIALYSIS_STATE_T getDialysisState( void ); UF_STATE_T getUltrafiltrationState( void ); -SALINE_BOLUS_STATE_T getSalineBolusState( void ); BLOOD_LEAK_ZEROING_STATE_T getBloodLeakZeroingState( void ); F32 getUltrafiltrationVolumeCollected( void ); F32 getUltrafiltrationReferenceVolume( void ); -F32 getTotalSalineBolusVolumeDelivered( void ); BOOL pauseUF( void ); BOOL resumeUF( void ); Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -rfba69244d94307e50fefaa1e88bcbb979584461e -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision fba69244d94307e50fefaa1e88bcbb979584461e) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -30,6 +30,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "RTC.h" +#include "SalineBolus.h" #include "SampleWater.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -red2a4cf95e008d002016dd40d7bb79efc135ad36 -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision ed2a4cf95e008d002016dd40d7bb79efc135ad36) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -33,6 +33,7 @@ #include "Reservoirs.h" #include "Rinseback.h" #include "RTC.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -221,6 +222,7 @@ // Initialize treatment mode each time we transition to it initTreatmentMode(); initReservoirs(); + initSalineBolus(); // Initialize treatment sub-modes each time we transition to treatment mode initBloodPrime(); initDialysis(); Index: firmware/App/Modes/SalineBolus.c =================================================================== diff -u --- firmware/App/Modes/SalineBolus.c (revision 0) +++ firmware/App/Modes/SalineBolus.c (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -0,0 +1,445 @@ + + +#include "BloodFlow.h" +#include "Dialysis.h" +#include "ModeTreatment.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PresOccl.h" +#include "SalineBolus.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup Dialysis + * @{ + */ + +// ********** private definitions ********** + +#define MAX_SALINE_VOLUME_DELIVERED_ML 800 ///< Maximum saline volume delivered for a treatment in milliliters. + +static const U32 SALINE_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND + / TASK_GENERAL_INTERVAL); ///< Saline bolus data broadcast interval (ms/task time) count. + +// ********** private data ********** + +static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. +static U32 salineBolusBroadcastTimerCtr; ///< Saline bolus data broadcast timer counter used to schedule when to transmit data. +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 F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). +static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). +static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. + +// ********** private function prototypes ********** + +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ); +static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ); +static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( void ); +static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( void ); + +/*********************************************************************//** + * @brief + * The initSalineBolus function initializes the Saline Bolus module. + * Calling this function will reset saline bolus and therefore should only + * be called when a new treatment is due to begin. + * @details Inputs: none + * @details Outputs: currentSalineBolusState, salineBolusBroadcastTimerCtr, + * totalSalineVolumeDelivered_mL, bolusSalineVolumeDelivered_mL, + * salineBolusStartRequested, salineBolusAbortRequested + * @return none + *************************************************************************/ +void initSalineBolus( void ) +{ + currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; + salineBolusBroadcastTimerCtr = 0; + totalSalineVolumeDelivered_mL = 0.0; + bolusSalineVolumeDelivered_mL = 0.0; + salineBolusStartRequested = FALSE; + salineBolusAbortRequested = FALSE; +} + +/*********************************************************************//** + * @brief + * The resetSalineBolus function resets the saline bolus variables. + * @details Inputs: currentSalineBolusState + * @details Outputs: bolusSalineVolumeDelivered_mL, salineBolusStartRequested, + * salineBolusAbortRequested, currentSalineBolusState + * @return none + *************************************************************************/ +void resetSalineBolus( void ) +{ + bolusSalineVolumeDelivered_mL = 0.0; + salineBolusStartRequested = FALSE; + salineBolusAbortRequested = FALSE; + + if ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) + { + currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; + } + resetUF(); +} + +/*********************************************************************//** + * @brief + * The execSalineBolus function executes the saline bolus state machine. + * @details Inputs: currentSalineBolusState + * @details Outputs: currentSalineBolusState + * @return Current saline bolus state machine. + *************************************************************************/ +SALINE_BOLUS_STATE_T execSalineBolus( void ) +{ + SALINE_BOLUS_STATE_T priorSubState = currentSalineBolusState; + + switch ( currentSalineBolusState ) + { + case SALINE_BOLUS_STATE_IDLE: + currentSalineBolusState = handleSalineBolusIdleState(); + break; + + case SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP: + currentSalineBolusState = handleSalineBolusWait4Pumps2Stop(); + break; + + case SALINE_BOLUS_STATE_IN_PROGRESS: + currentSalineBolusState = handleSalineBolusInProgressState(); + break; + + case SALINE_BOLUS_STATE_MAX_DELIVERED: + currentSalineBolusState = handleSalineBolusMaxDeliveredState(); + 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; + } + + // MAX DELIVERED transitions different and sends the event on its own. + if ( ( priorSubState != currentSalineBolusState ) && ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) ) + { + setCurrent4thLevelState( (U32)currentSalineBolusState ); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentSalineBolusState ); + } + + return currentSalineBolusState; +} + +/*********************************************************************//** + * @brief + * The getSalineBolusState function gets the current saline bolus state. + * @details Inputs: currentSalineBolusState + * @details Outputs: none + * @return currentSalineBolusState + *************************************************************************/ +SALINE_BOLUS_STATE_T getSalineBolusState( void ) +{ + return currentSalineBolusState; +} + +/*********************************************************************//** + * @brief + * The getTotalSalineBolusVolumeDelivered function gets the current total + * saline volume delivered. + * @details Inputs: totalSalineVolumeDelivered + * @details Outputs: none + * @return totalSalineVolumeDelivered + *************************************************************************/ +F32 getTotalSalineBolusVolumeDelivered( void ) +{ + return totalSalineVolumeDelivered_mL; +} + +/*********************************************************************//** + * @brief + * The isSalineBolusStartRequested function returns the status of a saline + * bolus start request. + * @details Inputs: salineBolusStartRequested + * @details Outputs: none + * @return Saline bolus start request status + *************************************************************************/ +BOOL isSalineBolusStartRequested( void ) +{ + return salineBolusStartRequested; +} + +/*********************************************************************//** + * @brief + * The setSalineBolusStartRequestStatus function sets the status of a saline + * bolus start request. + * @details Inputs: none + * @details Outputs: salineBolusStartRequested + * @return none + *************************************************************************/ +void setSalineBolusStartRequestStatus( BOOL status ) +{ + salineBolusStartRequested = status; +} + +/*********************************************************************//** + * @brief + * The signalStartSalineBolus function handles user request to initiate a + * saline bolus. + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusStartRequested, response sent + * @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(); + + // 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 ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED_ML ) + { + rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; + } + else if ( currentSalineBolusState != SALINE_BOLUS_STATE_IDLE ) + { + rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; + } + else + { + accept = TRUE; + salineBolusStartRequested = TRUE; + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + } + + // Send response + sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); +} + +/*********************************************************************//** + * @brief + * The signalAbortSalineBolus function handles user request to abort a + * saline bolus. + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusAbortRequested, response sent + * @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; + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + } + + // Send response + sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); +} + +/*********************************************************************//** + * @brief + * The publishSalineBolusData function publishes the saline bolus and + * blood leak zeroing at 1 Hz interval. + * @details Inputs: salineBolusBroadcastTimerCtr + * @details Outputs: salineBolusBroadcastTimerCtr + * @param blood leak zeroing DPi to BLD flush volume in milliliters + * @param blood leak zeroing reserver to DPi flush volume in milliliters + * @param blood leak zeroing needed after reservoir switch boolean flag + * @return none + *************************************************************************/ +void publishSalineBolusData( F32 bloodLeakZeroingDPi2BLDFlushVolumeML, F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML, U32 bloodLeakZeroingNeededAfterRsrvrSwitch ) +{ + if ( ++salineBolusBroadcastTimerCtr >= SALINE_BOLUS_DATA_PUB_INTERVAL ) + { + SALINE_BOLUS_DATA_PAYLOAD_T data; + + data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; + data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; + data.bloodLeakZeroingDPi2BLDFlushVolumeML = bloodLeakZeroingDPi2BLDFlushVolumeML; + data.bloodLeakZeroingRsrvr2DPiFlushVolumeML = bloodLeakZeroingRsrvr2DPiFlushVolumeML; + data.bloodLeakZeroingNeededAfterRsrvrSwitch = bloodLeakZeroingNeededAfterRsrvrSwitch; + + broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); + salineBolusBroadcastTimerCtr = 0; + } +} + +// ********** private function prototypes ********** + +/*********************************************************************//** + * @brief + * The handleSalineBolusIdleState function handles the idle state of the + * saline bolus state machine. + * @details Inputs: none + * @details Outputs: + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IDLE; + + // Handle saline bolus start request from user + if ( TRUE == salineBolusStartRequested ) + { + salineBolusStartRequested = FALSE; + // Cmd all pumps to stop + setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stopSyringePump(); + // Begin saline bolus + result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleSalineBolusWait4Pumps2Stop function handles the wait for pumps + * to stop state of the saline bolus state machine. + * @details Inputs: none + * @details Outputs: + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; + + if ( ( FALSE == isBloodPumpRunning() ) && ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) + { + // Reset bolus data before we start + bolusSalineVolumeDelivered_mL = 0.0; + bolusSalineLastVolumeTimeStamp = getMSTimerCount(); + + // Bypass dialyzer + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + // Switch to saline bag + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + // Start blood pump at saline bolus rate + setBloodPumpTargetFlowRate( SALINE_BOLUS_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Start dialysate inlet pump at re-circ rate + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Begin saline bolus + result = SALINE_BOLUS_STATE_IN_PROGRESS; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleSalineBolusInProgressState function handles the in-progress state of the + * saline bolus state machine. + * @details Inputs: none + * @details Outputs: + * @return next saline bolus state + *************************************************************************/ +static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( void ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IN_PROGRESS; + F32 timeSinceLastVolumeUpdateMin = (F32)calcTimeSince( bolusSalineLastVolumeTimeStamp ) / (F32)( MS_PER_SECOND * SEC_PER_MIN ); + F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + F32 bldFlowRate = getMeasuredBloodFlowRate(); + F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; + F32 expVolSinceLastUpdateMl = (F32)getTargetBloodFlowRate() * timeSinceLastVolumeUpdateMin; + + // Update saline bolus volumes + bolusSalineLastVolumeTimeStamp = getMSTimerCount(); + bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; + totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; + + // Check for empty saline bag per arterial line pressure + if ( TRUE == isSalineBagEmpty() ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_EMPTY_SALINE_BAG, getMeasuredArterialPressure() ); + result = SALINE_BOLUS_STATE_IDLE; + } + + // Determine if we have reached maximum saline delivery volume + if ( ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED_ML ) ) + { + result = SALINE_BOLUS_STATE_MAX_DELIVERED; + setCurrent4thLevelState( (U32)result ); + sendOperationStatusEvent(); + } + else + { + // Determine if bolus is complete + if ( bolusSalineVolumeDelivered_mL >= bolusTargetVolume ) + { + result = SALINE_BOLUS_STATE_IDLE; + } + // User is aborting saline bolus + else if ( TRUE == salineBolusAbortRequested ) + { + salineBolusAbortRequested = FALSE; + result = SALINE_BOLUS_STATE_IDLE; + } + } + + // Are we stopping the bolus? + if ( result != SALINE_BOLUS_STATE_IN_PROGRESS ) + { + // Hard stop blood and dialysate pumps + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + // Send last saline bolus data + salineBolusBroadcastTimerCtr = SALINE_BOLUS_DATA_PUB_INTERVAL; + bolusSalineVolumeDelivered_mL = 0.0; + // Just pass the blood leak related as 0 since only saline bolus data is published + publishSalineBolusData( 0.0, 0.0, 0 ); + sendTreatmentLogEventData( SALINE_BOLUSES_CHANGE_EVENT, bolusSalineVolumeDelivered_mL, totalSalineVolumeDelivered_mL ); + } + + 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( void ) +{ + SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_MAX_DELIVERED; + + return result; +} + +/**@}*/ Index: firmware/App/Modes/SalineBolus.h =================================================================== diff -u --- firmware/App/Modes/SalineBolus.h (revision 0) +++ firmware/App/Modes/SalineBolus.h (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -0,0 +1,53 @@ + +#ifndef __SALINEBOLUS_H__ +#define __SALINEBOLUS_H__ + +#include "HDCommon.h" +#include "HDDefs.h" + +/** + * @defgroup SalineBolus SalineBolus + * @brief SalineBolus sub-mode of treatment mode. The SalineBolus sub-mode is where + * saline bolus is administered. A saline bolus may be requested + * by the user; however, dialysis and ultrafiltration would not be provided during + * a saline bolus. + * + * @addtogroup SalineBolus + * @{ + */ + +// ********** public definitions ********** + +#pragma pack(push,1) +/// Payload record structure for a saline bolus data broadcast message. +typedef struct +{ + U32 tgtSalineVolumeMl; ///< Target saline volume in mL. + F32 cumSalineVolumeMl; ///< Cumulative saline volume in mL. + F32 bolSalineVolumeMl; ///< Bolus saline volume in mL. + F32 bloodLeakZeroingDPi2BLDFlushVolumeML; ///< Blood leak zeroing DPi to BLD flush volume in mL. + F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML; ///< Blood leak zeroing reservoir to DPi flush volume in mL. + U32 bloodLeakZeroingNeededAfterRsrvrSwitch; ///< Blood leak zeroing needed after reservoir switch. +} SALINE_BOLUS_DATA_PAYLOAD_T; +#pragma pack(pop) + +// ********** public function prototypes ********** + +void initSalineBolus( void ); +void resetSalineBolus( void ); + +SALINE_BOLUS_STATE_T execSalineBolus( void ); +SALINE_BOLUS_STATE_T getSalineBolusState( void ); +F32 getTotalSalineBolusVolumeDelivered( void ); + +BOOL isSalineBolusStartRequested( void ); +void setSalineBolusStartRequestStatus( BOOL status ); + +void signalStartSalineBolus( void ); +void signalAbortSalineBolus( void ); + +void publishSalineBolusData( F32 bloodLeakZeroingDPi2BLDFlushVolumeML, F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML, U32 bloodLeakZeroingNeededAfterRsrvrSwitch ); + +/**@}*/ + +#endif Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -rfba69244d94307e50fefaa1e88bcbb979584461e -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision fba69244d94307e50fefaa1e88bcbb979584461e) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -23,6 +23,7 @@ #include "DialOutFlow.h" #include "ModeTreatment.h" #include "OperationModes.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TreatmentStop.h" @@ -58,6 +59,7 @@ static TREATMENT_STOP_STATE_T handleTreatmentStopDialysateRecircState( void ); static TREATMENT_STOP_STATE_T handleTreatmentStopBloodRecircState( void ); static TREATMENT_STOP_STATE_T handleTreatmentStopRecoverBloodDetectState( void ); +static TREATMENT_STOP_STATE_T handleTreatmentStopDeliverSalineBolusState( void ); static void handleTreatmentStopBloodSittingTimer( void ); static void publishTreatmentStopData( void ); @@ -279,6 +281,10 @@ currentTxStopState = handleTreatmentStopRecoverBloodDetectState(); break; + case TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE: + currentTxStopState = handleTreatmentStopDeliverSalineBolusState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_TREATMENT_STOP_INVALID_STATE, currentTxStopState ); break; @@ -347,6 +353,10 @@ setupForBloodRecirculationStopState(); result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; } + else if ( ( TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE != state ) /*&&*/ ) + { + result = TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE; + } } return result; @@ -383,7 +393,7 @@ handleTreatmentStopBloodSittingTimer(); - result = handleTreatmentStopAlarmsAndSignals(result); + result = handleTreatmentStopAlarmsAndSignals( result ); return result; } @@ -400,7 +410,7 @@ { TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; - result = handleTreatmentStopAlarmsAndSignals(result); + result = handleTreatmentStopAlarmsAndSignals( result ); return result; } @@ -449,6 +459,27 @@ /*********************************************************************//** * @brief + * The handleTreatmentStopDeliverSalineBolusState function handles the + * delivery of saline bolus state in treatment stop. + * @details Inputs: none + * @details Outputs: none + * @return next treatment stop state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopDeliverSalineBolusState( void ) +{ + TREATMENT_STOP_STATE_T result = TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE; + + execSalineBolus(); + + // Keep reseting the blood sitting timer + 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. Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -rbf277519f4fcb199d3aeec1748da790d2e0beba9 -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision bf277519f4fcb199d3aeec1748da790d2e0beba9) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -1359,8 +1359,7 @@ } // If in Treatment-Stop state or Fault/Service/Standby Mode, allow user to minimize the alarm window - if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) || - ( ( MODE_TREA == currentMode ) && ( TREATMENT_STOP_STATE == getTreatmentState() ) ) ) + if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) ) { noMinimize = FALSE; } Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rfba69244d94307e50fefaa1e88bcbb979584461e -rc9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision fba69244d94307e50fefaa1e88bcbb979584461e) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision c9890bc0bc9a1d779be9fec7e0478cfc6fba1cfb) @@ -33,8 +33,9 @@ #include "OperationModes.h" #include "Reservoirs.h" #include "RTC.h" -#include "SampleWater.h" #include "SafetyShutdown.h" +#include "SalineBolus.h" +#include "SampleWater.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "Temperatures.h"