Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -re9e339870c5ed01230963f00d400331ab879c91f -r58d4338b0c453ac49d3fdc4ba391b47949406b98 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision e9e339870c5ed01230963f00d400331ab879c91f) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 58d4338b0c453ac49d3fdc4ba391b47949406b98) @@ -7,8 +7,8 @@ * * @file ModeTreatment.c * -* @author (last) Raghu Kallala -* @date (last) 17-Apr-2026 +* @author (last) Vijay Pamula +* @date (last) 27-May-2026 * * @author (original) Sean Nash * @date (original) 21-Apr-2025 @@ -20,6 +20,7 @@ #include "Bubbles.h" #include "Buttons.h" #include "DDInterface.h" +#include "FluidBolus.h" #include "Messaging.h" #include "ModeService.h" #include "ModeTreatment.h" @@ -53,8 +54,6 @@ #define TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) /// Ultrafiltration data broadcast interval (ms/task time) count. #define ULTRAFILTRATION_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) -/// Saline bolus data broadcast interval (ms/task time) count. // TODO - move to StateTxSalineBolus.c when implemented -#define SALINE_BOLUS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Macro to calculate the elapsed treatment time in seconds. #define CALC_ELAPSED_TREAT_TIME_IN_SECS() ( treatmentTimeMS / MS_PER_SECOND ) @@ -72,16 +71,15 @@ static BOOL treatmentCompleted; ///< Flag indicates whether the treatment has completed. static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in seconds). -static F32 presUFVolumeL; ///< Prescribed ultrafiltration volume (in L). -static F32 presUFRateLHr; ///< Prescribed ultrafiltration rate (in L/hr). +static F32 presUFVolumeMl; ///< Prescribed ultrafiltration volume (in Ml). +static F32 presUFRateMlMin; ///< Prescribed ultrafiltration rate (in mL/Min). static U32 treatmentTimeMS; ///< Elapsed treatment time (in ms). static U32 lastTreatmentTimeStamp; ///< Last time elapsed treatment time was recorded (a timestamp in ms). static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment time data broadcast timer counter used to schedule when to transmit data. static U32 treatmentStateBroadcastTimerCtr; ///< Treatment state data broadcast timer counter used to schedule when to transmit data. static U32 treatmentParamsRangesBroadcastTimerCtr; ///< Treatment parameter ranges broadcast timer counter used to schedule when to transmit updated ranges. static U32 ultrafiltrationBroadcastTimerCtr; ///< Ultrafiltration data broadcast timer counter used to schedule when to transmit data. -static U32 salineBolusBroadcastTimerCtr; ///< Saline bolus data broadcast timer counter used to schedule when to transmit data. /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T treatmentTimePublishInterval; @@ -104,15 +102,13 @@ static void broadcastTreatmentSettingsRanges( void ); static void broadcastTreatmentPeriodicData(); -static void publishSalineBolusData( void ); // TODO - move to StateTxSalineBolus.c when implemented static void publishUltrafiltrationData( void ); static U32 getMinTreatmentTimeInMinutes( void ); static TREATMENT_STATE_T handleTreatmentStartState( void ); static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ); static TREATMENT_STATE_T handleTreatmentDialysisState( void ); static TREATMENT_STATE_T handleTreatmentIsoUFState( void ); static TREATMENT_STATE_T handleTreatmentDialysatePausedState( void ); -static TREATMENT_STATE_T handleTreatmentSalineBolusState( void ); static TREATMENT_STATE_T handleTreatmentPausedState( void ); static TREATMENT_STATE_T handleTreatmentRinsebackState( void ); static TREATMENT_STATE_T handleTreatmentRecircState( void ); @@ -155,11 +151,10 @@ treatmentStateBroadcastTimerCtr = TREATMENT_STATE_DATA_PUB_INTERVAL; // So we send state data immediately when we begin treatment mode treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode ultrafiltrationBroadcastTimerCtr = ULTRAFILTRATION_DATA_PUB_INTERVAL; // So we send ultrafiltration immediately when we begin treatment mode - salineBolusBroadcastTimerCtr = SALINE_BOLUS_DATA_PUB_INTERVAL; // So we send saline bolus data immediately when we begin treatment mode presTreatmentTimeSecs = 0; - presUFVolumeL = 0.0F; - presUFRateLHr = 0.0F; + presUFVolumeMl = 0.0F; + presUFRateMlMin = 0.0F; resetSignalFlags(); resetAlarmSignalFlags(); @@ -193,6 +188,7 @@ // initRinseback(); // initTreatmentRecirc(); // initTreatmentEnd(); + initFluidBolus(); // Started the treatment - set the start time in epoch // setTxLastStartTimeEpoch( getRTCTimestamp() ); @@ -207,13 +203,13 @@ // Set treatment parameters presTreatmentTimeSecs = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ) * SEC_PER_MIN; - presUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); - presUFRateLHr = presUFVolumeL / ( (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ) / (F32)MIN_PER_HOUR ); - setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presUFVolumeL, presUFRateLHr ); + presUFVolumeMl = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; + presUFRateMlMin = presUFVolumeMl / (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presUFVolumeMl, presUFRateMlMin ); bicarbConvFactor = BICARBONATE_CONVERSION_FACTOR; // Direct DD to generate dialysate and bypass while priming blood - cmdStartGenerateDialysate( (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presUFRateLHr, + cmdStartGenerateDialysate( (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presUFRateMlMin, getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ), TRUE, getTreatmentParameterF32( TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR ), bicarbConvFactor, @@ -467,10 +463,6 @@ // currentTreatmentState = handleTreatmentIsoUFState(); // break; // -// case TREATMENT_SALINE_BOLUS_STATE: -// currentTreatmentState = handleTreatmentSalineBolusState(); -// break; -// // case TREATMENT_DIALYSATE_PAUSED_STATE: // currentTreatmentState = handleTreatmentDialysatePausedState(); // break; @@ -507,12 +499,13 @@ broadcastTreatmentPeriodicData(); // Publish ultrafiltration data at set interval (whether we are performing UF or not) publishUltrafiltrationData(); - // Publish saline bolus data at set interval (whether we are delivering one or not) - publishSalineBolusData(); // Manage air trap control execAirTrapMonitorTreatment(); + // Call fluid bolus + execFluidBolus(); + return currentTreatmentState; } @@ -627,10 +620,15 @@ U32 msSinceLast = calcTimeBetween( lastTreatmentTimeStamp, newTime ); DIALYSIS_STATE_T dialysisState = getDialysisState(); - // Update treatment time - treatmentTimeMS += msSinceLast; + // Always update timestamp to avoid time jump on bolus exit lastTreatmentTimeStamp = newTime; + // Only update treatment time when fluid bolus is not active + if ( FALSE == isFluidBolusActive() ) + { + treatmentTimeMS += msSinceLast; + } + // End treatment if treatment duration has been reached if ( CALC_ELAPSED_TREAT_TIME_IN_SECS() >= presTreatmentTimeSecs ) { @@ -915,14 +913,32 @@ payload.rinsebackState = 0; // getCurrentRinsebackState(); payload.txRecircState = 0; // getCurrentTreatmentRecircState(); payload.txEndState = 0; // getCurrentTreatmentEndState(); - payload.txSalBolusState = 0; // + payload.txFluidBolusState = getCurrentFluidBolusState(); payload.txHepState = 0; // broadcastData( MSG_ID_TD_TREATMENT_STATE_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)(&payload), sizeof( TREATMENT_STATE_DATA_T ) ); } } /*********************************************************************//** * @brief + * The updateTreatmentBroadcastData function updates treatment broadcast + * data values used for treatment time and ultrafiltration broadcasts. + * @details \b Inputs: none. + * @details \b Outputs: presTreatmentTimeSecs, presUFVolumeMl, presUFRateMlMin. + * @param ufRateLhr ultrafiltration rate in L/hr. + * @return none. + *************************************************************************/ +void updateTreatmentBroadcastData( F32 ufRateLhr ) +{ + presTreatmentTimeSecs = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ) * SEC_PER_MIN; + + presUFVolumeMl = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); + + presUFRateMlMin = ( ufRateLhr * (F32)ML_PER_LITER ) / (F32)MIN_PER_HOUR; +} + +/*********************************************************************//** + * @brief * The broadcastTreatmentSettingsRanges function computes and broadcasts * updated treatment parameter ranges that the user may change during treatment. * It is assumed that prescription settings have already been set prior to calling @@ -949,7 +965,7 @@ F32 minUFVol = 0.0F; // TODO getUltrafiltrationReferenceVolume() + presUFRate; // current UF volume + 1 min at current rate // Compute maximum UF volume (considering from adjustment of UF rate and time perspectives) F32 maxUFVol1 = minUFVol + ( (F32)( presTime - elapseTime ) * MAX_UF_RATE_ML_MIN ); - F32 maxUFVol2 = ( presUFRateLHr > 0.0F ? minUFVol + ( (F32)( MAX_TREATMENT_TIME_MINUTES - elapseTime - 1 ) * presUFRateLHr ) : minUFVol ); + F32 maxUFVol2 = ( presUFRateMlMin > 0.0F ? minUFVol + ( (F32)( MAX_TREATMENT_TIME_MINUTES - elapseTime - 1 ) * presUFRateMlMin ) : minUFVol ); F32 maxUFVol = MAX( maxUFVol1, maxUFVol2 ); // Set minimum dialysate flow rate U32 minDialRate = MIN_DIALYSATE_FLOW_RATE; @@ -991,7 +1007,7 @@ // F32 const arterialPres = getFilteredArterialPressure(); // F32 const venousPres = getFilteredVenousPressure(); // -// if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) +// if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getTreatmentState() != TREATMENT_SALINE_BOLUS_STATE ) ) // { // treatmentBloodFlowRateTotal_mL_min += getMeasuredBloodFlowRate(); // treatmentDialysateFlowRateTotal_mL_min += getMeasuredDialInFlowRate(); @@ -1102,44 +1118,23 @@ /*********************************************************************//** * @brief - * The publishSalineBolusData function publishes the saline bolus data + * The publishUltrafiltrationData function publishes the ultrafiltration data * at the set time interval. * @details \b Inputs: none * @details \b Outputs: none - * @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_FLUID_BOLUS_VOLUME ); - data.cumSalineVolumeMl = 0.0F; // TODO - data.bolSalineVolumeMl = 0.0F; // TODO - - sendMessage( MSG_ID_TD_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)(&data), sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); - salineBolusBroadcastTimerCtr = 0; - } -} - -/*********************************************************************//** - * @brief - * The publishUltrafiltrationData function publishes the ultrafiltration data - * at the set time interval. - * @details \b Inputs: presUFVolumeL, presUFRate - * @details \b Outputs: none * @return none *************************************************************************/ static void publishUltrafiltrationData( void ) { if ( ++ultrafiltrationBroadcastTimerCtr >= ULTRAFILTRATION_DATA_PUB_INTERVAL ) { UF_DATA_PAYLOAD_T data; + F32 presUFRateLHr = 0.0F; + F32 presUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); + presUFRateLHr = presUFVolumeL / ( (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ) / (F32)MIN_PER_HOUR ); data.setUFVolumeL = presUFVolumeL; - data.tgtUFRateLHr = presUFRateLHr; + data.tgtUFRateLHr = ( presUFRateMlMin * (F32)MIN_PER_HOUR ) / (F32)ML_PER_LITER; data.ufVolumeDeliveredL = getUltrafiltrationVolumeDrawn(); data.ufState = (U32)getDialysisState();