Index: firmware/App/Modes/StateTxBloodPrime.c =================================================================== diff -u -rb777859b2667c350c6ca9fda60a668c9eb5fe02d -r934ce8fc097623360b8db3619194348fb4fad09f --- firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision b777859b2667c350c6ca9fda60a668c9eb5fe02d) +++ firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 934ce8fc097623360b8db3619194348fb4fad09f) @@ -7,8 +7,8 @@ * * @file StateTxBloodPrime.c * -* @author (last) Varshini Nagabooshanam -* @date (last) 17-Mar-2026 +* @author (last) Praneeth Bunne +* @date (last) 03-Jun-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 09-Jan-2026 @@ -19,6 +19,7 @@ #include "BloodFlow.h" #include "Buttons.h" #include "DDInterface.h" +#include "FluidBolus.h" #include "Messaging.h" #include "ModeTreatment.h" #include "TxParams.h" @@ -66,9 +67,11 @@ static BLOOD_PRIME_STATE_T bloodPrimeState; ///< Current state of the blood prime sub-mode. static BLOOD_PRIME_STATE_T bloodPrimeResumeState; ///< Blood prime sub-state prior to pause. +static BLOOD_PRIME_STATE_T bolusCallingState; ///< Fluid Bolus calling state. static BOOL pendingPauseRequest; ///< Flag indicating UI has requested blood prime pause. static BOOL pendingResumeRequest; ///< Flag indicating UI has requested blood prime resume. static BOOL pendingFlowChangeRequest; ///< Flag indicating UI has requested blood prime flow change +static BOOL fluidBolusRequested; ///< Flag indicating fluid bolus has been requested by user. static F32 bloodPrimeRampFlowRate_mL_min; ///< Current blood pump ramp flow rate. static F32 bloodPrimeRampStep_mL; ///< Blood pump volume step size for ramping. @@ -78,9 +81,10 @@ static U32 bloodPrimePublishTimerCtr; ///< Timer counter for determining interval for blood prime status to be published. static U32 lastBloodPrimeFlowRate_mL_min; ///< Flow rate prior to pausing blood prime. static U32 requestedBloodFlowRate_mL_min; ///< Requested blood flow rate from UI. -static U32 bloodPrimeStartMS = 0; ///< Start time of Blood Prime (ms timer count) -static U32 bloodPrimeTimeoutSec = 0; ///< -static U32 bloodPrimeCountdownSec = 0; ///< +static U32 bloodPrimeStartMS; ///< Start time of Blood Prime (ms timer count) +static U32 bloodPrimeTimeoutSec; ///< Blood prime pause timeout duration (broadcast to UI) +static U32 bloodPrimeCountdownSec; ///< Blood prime pause countdown remaining time (broadcast to UI) +static U32 pausedElapsedMS; ///< Elapsed pause time saved when fluid bolus starts from paused state. /// Interval (in task intervals) at which to publish blood prime data to CAN bus. static OVERRIDE_U32_T bloodPrimePublishInterval = { BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, 0 }; @@ -94,6 +98,7 @@ static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ); static BLOOD_PRIME_STATE_T handleBloodPrimeRunState( void ); static BLOOD_PRIME_STATE_T handleBloodPrimePausedState( void ); +static BLOOD_PRIME_STATE_T handleBloodPrimeFluidBolusState( void ); static void handleBloodPrimePauseTimer( void ); static void publishBloodPrimeData( void ); @@ -112,6 +117,7 @@ bloodPrimeState = BLOOD_PRIME_RAMP_STATE; bloodPrimeResumeState = BLOOD_PRIME_RAMP_STATE; + bolusCallingState = BLOOD_PRIME_RAMP_STATE; bloodPrimeRampControlTimerCtr = 0; bloodPrimePublishTimerCtr = BLOOD_PRIME_DATA_PUBLISH_INTERVAL - 2; // setup so publish will occur time after next cumulativeBloodPrimeVolume_mL.data = 0.0; @@ -130,6 +136,10 @@ } bloodPrimeRampStep_mL = rampRateSpan / estRampSeconds; bloodPrimeStartMS = 0; + bloodPrimeTimeoutSec = 0; + bloodPrimeCountdownSec = 0; + pausedElapsedMS = 0; + fluidBolusRequested = FALSE; } /*********************************************************************//** @@ -234,6 +244,10 @@ bloodPrimeState = handleBloodPrimePausedState(); break; + case BLOOD_PRIME_FLUID_BOLUS_STATE: + bloodPrimeState = handleBloodPrimeFluidBolusState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_PRIME_INVALID_STATE, bloodPrimeState ); break; @@ -297,6 +311,17 @@ bloodPrimeResumeState = BLOOD_PRIME_RUN_STATE; result = BLOOD_PRIME_RUN_STATE; } + // When UI requests fluid bolus + else if ( TRUE == fluidBolusRequested ) + { + fluidBolusRequested = FALSE; + bloodPrimeResumeState = bloodPrimeState; + bolusCallingState = bloodPrimeState; + lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); + // Start bolus and transition to bolus state + signalStartFluidBolus( lastBloodPrimeFlowRate_mL_min ); + result = BLOOD_PRIME_FLUID_BOLUS_STATE; + } else { // Continue ramping @@ -352,6 +377,21 @@ pendingFlowChangeRequest = FALSE; setBloodPumpTargetFlowRate( requestedBloodFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } + // When UI requests fluid bolus + else if ( TRUE == fluidBolusRequested ) + { + fluidBolusRequested = FALSE; + bloodPrimeResumeState = bloodPrimeState; + bolusCallingState = bloodPrimeState; + lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); + // Start bolus and transition to bolus state + signalStartFluidBolus( lastBloodPrimeFlowRate_mL_min ); + result = BLOOD_PRIME_FLUID_BOLUS_STATE; + } + else + { + // No action required. + } return result; } @@ -372,19 +412,73 @@ if ( TRUE == pendingResumeRequest ) { pendingResumeRequest = FALSE; + bolusCallingState = bloodPrimeResumeState; setBloodPumpTargetFlowRate( (U32)lastBloodPrimeFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); // Open art/ven pinch valves setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); // Return to state prior to pause result = bloodPrimeResumeState; } + // When UI requests fluid bolus + else if ( TRUE == fluidBolusRequested ) + { + fluidBolusRequested = FALSE; + bolusCallingState = bloodPrimeState; + // Save elapsed time + pausedElapsedMS = calcTimeSince( bloodPrimeStartMS ); + // Start bolus and transition to bolus state + signalStartFluidBolus( lastBloodPrimeFlowRate_mL_min ); + result = BLOOD_PRIME_FLUID_BOLUS_STATE; + } + else + { + // No action required. + } return result; } /*********************************************************************//** * @brief + * The handleBloodPrimeFluidBolusState function handles the fluid bolus + * state of the blood prime sub-mode. + * @details \b Inputs: bolusCallingState, lastBloodPrimeFlowRate_mL_min, + * bloodPrimeStartMS, pausedElapsedMS + * @details \b Outputs: bolusCallingState + * @return next blood prime state + *************************************************************************/ +static BLOOD_PRIME_STATE_T handleBloodPrimeFluidBolusState( void ) +{ + BLOOD_PRIME_STATE_T result = BLOOD_PRIME_FLUID_BOLUS_STATE; + + // Restore actuators and return to pre-bolus sub-state upon bolus complete or abort + if ( FALSE == isFluidBolusActive() ) + { + if( BLOOD_PRIME_PAUSED_STATE == bolusCallingState ) + { + // Resume from saved elapsed + bloodPrimeStartMS = getMSTimerCount() - pausedElapsedMS; + pausedElapsedMS = 0; + // Arterial valve is open to saline, not required here + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + else + { + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + setBloodPumpTargetFlowRate( lastBloodPrimeFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + + result = bolusCallingState; + } + + return result; +} + +/*********************************************************************//** + * @brief * The getCurrentBloodPrimeState function returns the current state of the * blood prime state. * @details \b Inputs: bloodPrimeState @@ -499,7 +593,7 @@ * @brief * The handleBloodPrimePauseTimer function monitors the Blood Prime * pause timer. -* @details Inputs: bloodPrimeStartMS +* @details Inputs: bloodPrimeStartMS, pausedElapsedMS * @details Outputs: bloodPrimeTimeoutSec, bloodPrimeCountdownSec * @details Alarms: ALARM_ID_TD_BLOOD_PRIME_PAUSE_WARNING * ALARM_ID_TD_BLOOD_PRIME_PAUSE_TIMEOUT @@ -510,9 +604,18 @@ U32 elapsedMS; U32 elapsedSec; - if ( BLOOD_PRIME_PAUSED_STATE == bloodPrimeState ) + if ( ( BLOOD_PRIME_PAUSED_STATE == bloodPrimeState ) || ( BLOOD_PRIME_PAUSED_STATE == bolusCallingState ) ) { - elapsedMS = calcTimeSince( bloodPrimeStartMS ); + if ( BLOOD_PRIME_FLUID_BOLUS_STATE == bloodPrimeState ) + { + // Time frozen during bolus + elapsedMS = pausedElapsedMS; + } + else + { + elapsedMS = calcTimeSince( bloodPrimeStartMS ); + } + elapsedSec = elapsedMS / MS_PER_SECOND; bloodPrimeTimeoutSec = BLOOD_PRIME_PAUSE_TIMEOUT_SEC; if ( elapsedSec < BLOOD_PRIME_PAUSE_TIMEOUT_SEC ) @@ -543,6 +646,25 @@ /*********************************************************************//** * @brief + * The bloodPrimeSetPendingFluidBolusRequest function handles a fluid bolus + * request while in blood prime sub-mode. + * @details \b Inputs: none + * @details \b Outputs: fluidBolusRequested + * @return TRUE if request is accepted, FALSE if rejected. + *************************************************************************/ +BOOL signalBloodPrimeFluidBolusRequest( void ) +{ + BOOL result = FALSE; + + // Allow from all the states + fluidBolusRequested = TRUE; + result = TRUE; + + return result; +} + +/*********************************************************************//** + * @brief * The publishBloodPrimeData function publishes blood prime data * at interval. * @details \b Message \b Sent: MSG_ID_TD_BLOOD_PRIME_PROGRESS_DATA