Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r944c891f790440233f0950e335f33f477a01fe02 -r6cdabf7f2032e8adbec0763f24fb9e26ffe668ff --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 944c891f790440233f0950e335f33f477a01fe02) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 6cdabf7f2032e8adbec0763f24fb9e26ffe668ff) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeTreatment.c * -* @author (last) Vinayakam Mani -* @date (last) 12-Oct-2023 +* @author (last) Sean Nash +* @date (last) 22-Apr-2024 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -27,6 +27,8 @@ #include "ModeTreatmentParams.h" #include "NVDataMgmt.h" #include "OperationModes.h" +#include "PersistentAlarm.h" +#include "PresOccl.h" #include "Reservoirs.h" #include "Rinseback.h" #include "RTC.h" @@ -195,6 +197,11 @@ treatmentStartTimeStamp = getRTCTimestamp(); treatmentEndTimeStamp = 0; + + // reset dialysate temperature alarm persistences prior to starting a treatment. + resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ); + resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ); + resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ); } /*********************************************************************//** @@ -746,6 +753,8 @@ sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0, presUFRate ); } transitionToDialysis(); + // To update partial blood pump occlusion baseline - start of treatment + signalBloodPumpPressureOcclBaseline(); result = TREATMENT_DIALYSIS_STATE; } } @@ -1014,23 +1023,28 @@ *************************************************************************/ BOOL verifyTreatmentDurationSettingChange( U32 treatmentTime ) { - BOOL result = FALSE; + BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; - HD_OP_MODE_T currMode = getCurrentOperationMode(); + HD_OP_MODE_T currMode = getCurrentOperationMode(); // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_END_STATE ) && ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= getMinTreatmentTimeInMinutes() ) ) { - F32 uFVolume; - U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL - // Always adjust UF volume to accommodate treatment time change (not UF rate) - uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); - if ( ( treatmentTime <= MAX_TREATMENT_TIME_MINUTES ) && - ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && - ( uFVolume <= MAX_UF_VOLUME_ML ) ) + F32 uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); + F32 uFVolumeL = uFVolume / ML_PER_LITER; + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL + // The minimum treatment time is either in the range of the institutional record or the 1-minute treatment config has been requested which is an exception + BOOL isMinTxTimeValid = ( ( treatmentTime >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) || + ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ) ? TRUE : FALSE ); + BOOL isTxTimeValid = ( ( TRUE == isMinTxTimeValid ) && + ( treatmentTime <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) ? TRUE : FALSE ); + BOOL isMinUFVolValid = ( ( uFVolumeL >= getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) || ( uFVolumeL <= 0.0F ) ? TRUE : FALSE ); + BOOL isUFVolValid = ( ( TRUE == isMinUFVolValid ) && ( uFVolumeL <= getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) ? TRUE : FALSE ); + + if ( ( TRUE == isTxTimeValid ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && ( TRUE == isUFVolValid ) ) { result = TRUE; sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), treatmentTime ); @@ -1043,11 +1057,11 @@ } else { - if ( treatmentTime > MAX_TREATMENT_TIME_MINUTES ) + if ( FALSE == isTxTimeValid ) { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } - else if ( uFVolume > MAX_UF_VOLUME_ML ) + else if ( FALSE == isUFVolValid ) { rejectReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; } @@ -1117,7 +1131,9 @@ // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_END_STATE ) && - ( uFVolume <= MAX_UF_VOLUME_ML ) && ( uFVolume > colUFVol ) && + ( uFVolume >= ( getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) && + ( uFVolume <= ( getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) && + ( uFVolume > colUFVol ) && ( CALC_TREAT_TIME_REMAINING_IN_SECS() >= PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ) ) { DIALYSIS_STATE_T currDialysisState = getDialysisState(); @@ -1170,7 +1186,8 @@ rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } // UF volume cannot be set lower than the UF volume that has already been collected - else if ( ( uFVolume > MAX_UF_VOLUME_ML ) || + else if ( ( uFVolume > ( getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) || + ( uFVolume < ( getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) || ( uFVolume <= colUFVol ) ) { rejectReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; @@ -1211,9 +1228,8 @@ UF_STATE_T currUFState = getUltrafiltrationState(); sendTreatmentLogEventData( UF_VOLUME_CHANGE_EVENT, presMaxUFVolumeML, pendingUFVolumeChange ); - result = TRUE; presMaxUFVolumeML = pendingUFVolumeChange; - setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); + result = setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); // User should only allow UF rate adjustment to achieve UF volume change if ( UF_ADJ_UF_RATE == adjustment ) @@ -1273,12 +1289,16 @@ // Check if we are in treatment mode for settings change if ( MODE_TREA == currMode ) { - U32 dialVolume = dialRate * ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); // In mL + F32 dialVolumeSoFar = (F32)( getTreatmentAvgDialysateFlowRate() * ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) ) / (F32)( SEC_PER_MIN ); + F32 dialVolumeNowToEnd = (F32)( dialRate * CALC_TREAT_TIME_REMAINING_IN_SECS() ) / (F32)( SEC_PER_MIN ); + F32 dialVolume = dialVolumeSoFar + dialVolumeNowToEnd; // mL // Validate new rates - if ( ( bloodRate >= MIN_SET_BLOOD_FLOW_RATE ) && ( bloodRate <= MAX_SET_BLOOD_FLOW_RATE ) && - ( dialRate >= MIN_DIAL_IN_FLOW_RATE ) && ( dialRate <= MAX_DIAL_IN_FLOW_RATE ) && - ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) + if ( ( bloodRate >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) && + ( bloodRate <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) && + ( dialRate >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) && + ( dialRate <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) && + ( dialVolume <= (F32)MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; // handle blood pump flow rate change @@ -1287,7 +1307,7 @@ sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Set to new rate - setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); + result &= setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); } @@ -1297,17 +1317,19 @@ sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Set to new rate - setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); + result &= setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); } } else { - if ( ( bloodRate < MIN_SET_BLOOD_FLOW_RATE ) || ( bloodRate > MAX_SET_BLOOD_FLOW_RATE ) ) + if ( ( bloodRate < getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) || + ( bloodRate > getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) ) { rejectReason = REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE; } - else if ( ( dialRate < MIN_DIAL_IN_FLOW_RATE ) || ( dialRate > MAX_DIAL_IN_FLOW_RATE ) ) + else if ( ( dialRate < getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) || + ( dialRate > getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) ) { rejectReason = REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE; } @@ -1346,7 +1368,7 @@ CRITICAL_DATAS_T proposedNewArtLimitWindow; CRITICAL_DATAS_T proposedNewVenLimitWindow; CRITICAL_DATAS_T proposedNewVenLimitAsymmetric; - PRESSURE_LIMIT_CHANGE_RESPONSE_T respRecord = { FALSE, 0, 0, 0 }; + PRESSURE_LIMIT_CHANGE_RESPONSE_T respRecord = { FALSE, 0, 0, 0, 0 }; proposedNewArtLimitWindow.sInt = data->artPresLimitWindowmmHg; proposedNewVenLimitWindow.sInt = data->venPresLimitWindowmmHg; @@ -1528,17 +1550,20 @@ F32 const arterialPres = getFilteredArterialPressure(); F32 const venousPres = getFilteredVenousPressure(); + if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) + { + treatmentBloodFlowRateTotal_mL_min += getMeasuredBloodFlowRate(); + treatmentDialysateFlowRateTotal_mL_min += getMeasuredDialInFlowRate(); + treatmentDialysateTempTotal_degree_C += getDialysateTemperature(); + treatmentArterialPressureTotal_mmHg += arterialPres; + treatmentVenousPressureTotal_mmHg += venousPres; + } + lastTreatmentPeriodicDataCollectTimeStamp = treatmentTimeMS; bloodFlowRateSum_mL_min += getMeasuredBloodFlowRate(); dialysateFlowRateSum_mL_min += getMeasuredDialInFlowRate(); arterialPressureSum_mmHg += arterialPres; venousPressureSum_mmHg += venousPres; - - treatmentBloodFlowRateTotal_mL_min += getMeasuredBloodFlowRate(); - treatmentDialysateFlowRateTotal_mL_min += getMeasuredDialInFlowRate(); - treatmentDialysateTempTotal_degree_C += getDialysateTemperature(); - treatmentArterialPressureTotal_mmHg += arterialPres; - treatmentVenousPressureTotal_mmHg += venousPres; } if ( ( timeElapsedSinceLastPublish_ms >= TREATMENT_PERIODIC_DATA_PUB_INTERVAL ) || ( TRUE == sendLastTreatmentPeriodicData ) )