Index: firmware/App/Services/StateServices/FluidBolus.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/FluidBolus.c (.../FluidBolus.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/StateServices/FluidBolus.c (.../FluidBolus.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file FluidBolus.c * * @author (last) Praneeth Bunne -* @date (last) 04-Jun-2026 +* @date (last) 02-Jul-2026 * * @author (original) Praneeth Bunne * @date (original) 04-Jun-2026 @@ -20,13 +20,15 @@ #include "DDInterface.h" #include "FluidBolus.h" #include "Messaging.h" -#include "Pressures.h" +#include "ModeStandby.h" #include "ModeTreatment.h" +#include "Pressures.h" #include "StateTxBloodPrime.h" #include "StateTxDialysis.h" #include "StateTxPaused.h" #include "TaskGeneral.h" #include "Timers.h" +#include "TubeSetInstall.h" #include "TxParams.h" #include "Valves.h" @@ -37,48 +39,32 @@ // ********** private definitions ********** -#define NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS 6U ///< Number of permitted alarms for fluid bolus from paused state. - static const U32 FLUID_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL); ///< Saline bolus data broadcast interval (ms/task time) count. // ********** private data ********** static FLUID_BOLUS_STATE_T currentFluidBolusState; ///< Current fluid bolus state -static FLUID_BOLUS_MEDIUM_T currentFluidBolusMedium; ///< Current fluid bolus medium +static FLUID_TYPE_T fluidType; ///< Fluid type for bolus static U32 fluidBolusBroadCastTimerCtr; ///< Broadcast Timer counter static BOOL fluidBolusStartRequested; ///< Flag indicates a fluid bolus start has been requested by user. static BOOL fluidBolusAbortRequested; ///< Flag indicates a fluid bolus abort has been requested by user. static BOOL pubBolusPermitted; ///< Flag indicates a bolus is permitted or not to UI (used to broadcast). +static BOOL newAlarmIndicateStop; ///< Flag indicating alarm with stop property is triggered. static U32 targetBloodFlowMLPM; ///< Blood pump flow rate (mL/min) to use for current bolus delivery. static F32 totalFluidVolumeDelivered_mL; ///< Volume (mL) in total of fluid delivered so far (cumulative for all boluses including current one). static F32 bolusFluidVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). static U32 bolusVolumeLastUpdateTimeStamp; ///< Time stamp for last bolus volume update. -// TODO: replace TRUE with getDialysateGoodToDeliverStatus() when we are ready -BOOL isDialysateGoodToDeliver = TRUE; ///< Flag indicating dialysate is good to deliver to the patient. - -///< Permitted alarm list-bolus allowed from paused state -static const ALARM_ID_T FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[ NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS ] = -{ - ALARM_ID_TD_TREATMENT_STOPPED_BY_USER, - ALARM_ID_TD_ARTERIAL_PRESSURE_HIGH, - ALARM_ID_TD_ARTERIAL_PRESSURE_LOW, - ALARM_ID_TD_VENOUS_PRESSURE_HIGH, - ALARM_ID_TD_TMP_PRESSURE_HIGH, - ALARM_ID_TD_TMP_PRESSURE_LOW -}; - // ********** private function prototypes ********** static void updateFluidBolusVolumeDelivered( void ); static void completeBolusToCumulative( void ); static FLUID_BOLUS_STATE_T handleFluidBolusIdleState( void ); static FLUID_BOLUS_STATE_T handleFluidBolusWait4Pumps2Stop( void ); -static FLUID_BOLUS_STATE_T handleFluidBolusSalineInProgressState( void ); -static FLUID_BOLUS_STATE_T handleFluidBolusSubstituteInProgressState( void ); +static FLUID_BOLUS_STATE_T handleFluidBolusInProgressState( void ); /*********************************************************************//** * @brief @@ -89,13 +75,14 @@ * @details \b Outputs: currentFluidBolusState, currentFluidBolusMedium, * fluidBolusBroadCastTimerCtr, targetBloodFlowMLPM, totalFluidVolumeDelivered_mL, * bolusFluidVolumeDelivered_mL, fluidBolusStartRequested, - * fluidBolusAbortRequested, bolusVolumeLastUpdateTimeStamp, pubBolusPermitted + * fluidBolusAbortRequested, bolusVolumeLastUpdateTimeStamp, pubBolusPermitted, + * newAlarmIndicateStop * @return none *************************************************************************/ void initFluidBolus( void ) { currentFluidBolusState = FLUID_BOLUS_IDLE_STATE; - currentFluidBolusMedium = getFluidBolusMedium(); + fluidType = getFluidType(); fluidBolusBroadCastTimerCtr = FLUID_BOLUS_DATA_PUB_INTERVAL - 10; // setup to stagger publish from other broadcasters targetBloodFlowMLPM = 0; totalFluidVolumeDelivered_mL = 0.0F; @@ -104,23 +91,24 @@ fluidBolusAbortRequested = FALSE; bolusVolumeLastUpdateTimeStamp = getMSTimerCount(); pubBolusPermitted = TRUE; + newAlarmIndicateStop = FALSE; } /*********************************************************************//** * @brief * The execFluidBolus function executes the fluid bolus state machine. - * @details \b Inputs: currentFluidBolusState - * @details \b Outputs: currentFluidBolusState + * @details \b Inputs: currentFluidBolusState, newAlarmIndicateStop + * @details \b Outputs: currentFluidBolusState, newAlarmIndicateStop * @return none *************************************************************************/ void execFluidBolus( void ) { FLUID_BOLUS_STATE_T priorState = currentFluidBolusState; // If alarm fires while bolus is active, abort the bolus - if ( ( TRUE == doesAlarmStatusIndicateStop() ) && ( TRUE == isFluidBolusActive() ) && - ( TREATMENT_PAUSED_STATE != getTreatmentState() ) ) + if ( ( TRUE == newAlarmIndicateStop ) && ( TRUE == isFluidBolusActive() ) ) { + newAlarmIndicateStop = FALSE; signalAbortFluidBolus(); } @@ -134,14 +122,10 @@ currentFluidBolusState = handleFluidBolusWait4Pumps2Stop(); break; - case FLUID_BOLUS_SALINE_IN_PROGRESS_STATE: - currentFluidBolusState = handleFluidBolusSalineInProgressState(); + case FLUID_BOLUS_IN_PROGRESS_STATE: + currentFluidBolusState = handleFluidBolusInProgressState(); break; - case FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE: - currentFluidBolusState = handleFluidBolusSubstituteInProgressState(); - break; - default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FLUID_BOLUS_STATE, currentFluidBolusState ) currentFluidBolusState = FLUID_BOLUS_IDLE_STATE; @@ -172,29 +156,6 @@ /*********************************************************************//** * @brief - * The getFluidBolusMedium function determines the fluid bolus medium based - * on the current treatment modality and online fluid configuration. - * Substitution fluid applies to HDF treatment, or HD treatment with online - * fluid enabled. Saline applies to standard HD without online fluid. - * @details \b Inputs: none - * @details \b Outputs: none - * @return FLUID_BOLUS_MEDIUM_SUBSTITUTE for HDF or HD-online, FLUID_BOLUS_MEDIUM_SALINE otherwise. - *************************************************************************/ -FLUID_BOLUS_MEDIUM_T getFluidBolusMedium( void ) -{ - FLUID_BOLUS_MEDIUM_T medium = FLUID_BOLUS_MEDIUM_SALINE; - U32 modality = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_MODALITY ); - - if ( ( modality == TREATMENT_MODALITY_HDF ) ) // || ( modality == TREATMENT_MODALITY_HD ) && ( check online fluid enabled ) - { - medium = FLUID_BOLUS_MEDIUM_SUBSTITUTE; - } - - return medium; -} - -/*********************************************************************//** - * @brief * The isFluidBolusActive function determines whether a fluid bolus is * currently being delivered. * @details \b Inputs: currentFluidBolusState @@ -298,7 +259,8 @@ * The handleFluidBolusIdleState function handles the idle state of the * fluid bolus state machine. * @details \b Inputs: fluidBolusStartRequested - * @details \b Outputs: fluidBolusStartRequested, bolusVolumeLastUpdateTimeStamp + * @details \b Outputs: fluidBolusStartRequested, bolusVolumeLastUpdateTimeStamp, + * newAlarmIndicateStop * @return next fluid bolus state *************************************************************************/ static FLUID_BOLUS_STATE_T handleFluidBolusIdleState( void ) @@ -309,6 +271,8 @@ if ( TRUE == fluidBolusStartRequested ) { fluidBolusStartRequested = FALSE; + // Clear when alarm is triggered and can be set when new alarm is triggered. + newAlarmIndicateStop = FALSE; // Stop blood pump signalBloodPumpHardStop(); // Stop substitution pump @@ -349,93 +313,67 @@ setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - if ( FLUID_BOLUS_MEDIUM_SALINE == currentFluidBolusMedium ) + if ( FLUID_TYPE_SALINE == fluidType ) { setBloodPumpTargetFlowRate( targetBloodFlowMLPM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - state = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; } - else if ( TRUE == isDialysateGoodToDeliver ) + else { // set D92 flow rate cmdSubstitutionRate( (F32)targetBloodFlowMLPM ); - state = FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE; } - else - { - state = FLUID_BOLUS_IDLE_STATE; - } + + state = FLUID_BOLUS_IN_PROGRESS_STATE; } return state; } /*********************************************************************//** * @brief - * The handleFluidBolusSalineInProgressState function handles the saline - * in-progress state of the fluid bolus state machine. Integrates delivered - * volume from measured blood flow, fires an alarm if the saline bag is empty, - * and completes the bolus when the target volume is reached or an abort is requested. - * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested + * The handleFluidBolusInProgressState function handles the in-progress + * state of the fluid bolus state machine. Integrates delivered volume from + * measured flow rate every tick. For saline medium, fires an alarm if the + * saline bag is empty. For substitution medium, aborts if dialysate is no + * longer good to deliver. Completes the bolus when the target volume is + * reached or an abort is requested. + * @details \b Alarms: ALARM_ID_TD_EMPTY_SALINE_BAG if saline bag is empty or + * saline line is clamped. + * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested, + * currentFluidBolusMedium * @details \b Outputs: fluidBolusAbortRequested * @return next fluid bolus state *************************************************************************/ -static FLUID_BOLUS_STATE_T handleFluidBolusSalineInProgressState( void ) +static FLUID_BOLUS_STATE_T handleFluidBolusInProgressState( void ) { - FLUID_BOLUS_STATE_T state = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); + FLUID_BOLUS_STATE_T state = FLUID_BOLUS_IN_PROGRESS_STATE; + F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); updateFluidBolusVolumeDelivered(); - // Check for empty saline bag per arterial line pressure - if ( TRUE == isSalineBagEmpty() ) + if ( FLUID_TYPE_SALINE == fluidType ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_EMPTY_SALINE_BAG, getFilteredArterialPressure() ); - state = FLUID_BOLUS_IDLE_STATE; + // Check for empty saline bag per arterial line pressure + if ( TRUE == isSalineBagEmpty() ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_EMPTY_SALINE_BAG, getFilteredArterialPressure() ); + state = FLUID_BOLUS_IDLE_STATE; + } } - // Determine if bolus is complete or stopped by user - else if ( ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) ) - { - fluidBolusAbortRequested = FALSE; - state = FLUID_BOLUS_IDLE_STATE; - } else { - // No action required + if ( FALSE == getDialysateGoodToDeliverStatus() ) + { + state = FLUID_BOLUS_IDLE_STATE; + } } - // Bolus ended, stop blood pump and record delivered volume - if ( state != FLUID_BOLUS_SALINE_IN_PROGRESS_STATE ) + // Bolus ended or target volume reached or aborted, stop delivery and record volume. + if ( ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) || + ( FLUID_BOLUS_IDLE_STATE == state ) ) { - signalBloodPumpHardStop(); - completeBolusToCumulative(); - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleFluidBolusSubstituteInProgressState function handles the - * substitute in-progress state state of the fluid bolus state machine. - * Integrates delivered volume from measured blood flow. Monitors dialysate - * readiness every tick, aborts if dialysate is no longer good to deliver. - * Completes the bolus when target is reached or an abort is requested. - * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested - * @details \b Outputs: fluidBolusAbortRequested, - * totalFluidVolumeDelivered_mL via completeBolusToCumulative() - * @return next fluid bolus state. - *************************************************************************/ -static FLUID_BOLUS_STATE_T handleFluidBolusSubstituteInProgressState( void ) -{ - FLUID_BOLUS_STATE_T state = FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE; - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); - - updateFluidBolusVolumeDelivered(); - - // Check for dialysate, target volume delivered or abort from user - if ( ( FALSE == isDialysateGoodToDeliver ) || ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) ) - { fluidBolusAbortRequested = FALSE; + signalBloodPumpHardStop(); cmdSubstitutionRate( 0.0F ); completeBolusToCumulative(); state = FLUID_BOLUS_IDLE_STATE; @@ -476,58 +414,6 @@ } /*********************************************************************//** - * @brief - * The isBolusAllowedByActiveAlarms function checks whether all - * currently active alarms permit a fluid bolus from the paused state. - * For saline medium, a non-permitted alarm blocks the bolus only if it is - * TD source. For substitute medium, any non-permitted alarm blocks the bolus. - * @details \b Inputs: FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[], currentFluidBolusMedium - * @details \b Outputs: none - * @return TRUE if all active alarms permit the bolus, FALSE otherwise. - *************************************************************************/ -BOOL isBolusAllowedByActiveAlarms( void ) -{ - U32 alarm; - U32 permittedIndex; - BOOL permitted = FALSE; - BOOL result = TRUE; - - for ( alarm = 0; alarm < NUM_OF_ALARM_IDS; alarm++ ) - { - if ( TRUE == isAlarmActive( alarm ) ) - { - for ( permittedIndex = 0; permittedIndex < NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS; permittedIndex++ ) - { - if ( FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[ permittedIndex ] == alarm ) - { - permitted = TRUE; - break; - } - } - - if ( FALSE == permitted ) - { - if ( FLUID_BOLUS_MEDIUM_SALINE == currentFluidBolusMedium ) - { - if ( ALM_SRC_TD == getAlarmSource( alarm ) ) - { - result = FALSE; - break; - } - } - else - { - result = FALSE; - break; - } - } - } - } - - return result; -} - -/*********************************************************************//** * @brief * The handleFluidBolusRequest function handles the UI fluid bolus request. * @details \b Message \b Sent: MSG_ID_TD_FLUID_BOLUS_RESPONSE @@ -553,18 +439,6 @@ // TD Fluid Bolus Additional Bolus Prevention rejReason = REQUEST_REJECT_REASON_FLUID_BOLUS_IN_PROGRESS; } - else if ( TREATMENT_PAUSED_STATE == getTreatmentState() ) - { - if ( ( TRUE == isBolusAllowedByActiveAlarms() ) ) - { - result = signalPauseTreatFluidBolusRequest(); - rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; - } - else - { - rejReason = REQUEST_REJECT_REASON_ALARM_IS_ACTIVE; - } - } else { // Route to whichever calling state is currently active @@ -580,6 +454,11 @@ rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; break; + case TREATMENT_PAUSED_STATE: + result = signalPauseTreatFluidBolusRequest(); + rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; + break; + // case TREATMENT_HDF_STATE: // result = signalHdfFluidBolusRequest(); // rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; @@ -632,4 +511,17 @@ return result; } +/*********************************************************************//** + * @brief + * The signalNewStopAlarmActivated function is called by the alarm system + * when an alarm with the stop property is activated. + * @details \b Inputs: none + * @details \b Outputs: newAlarmIndicateStop + * @return none + *************************************************************************/ +void signalNewStopAlarmActivated( void ) +{ + newAlarmIndicateStop = TRUE; +} + /**@}*/