Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rba15d3e6250e8cd3cd3ef39cb64a93f91c3caba2 -rb3724006e900d548c758aee54cd35386f19a7f1a --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision ba15d3e6250e8cd3cd3ef39cb64a93f91c3caba2) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision b3724006e900d548c758aee54cd35386f19a7f1a) @@ -1,21 +1,21 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 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 Dialysis.c +* @file Dialysis.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Darren Cox +* @date (last) 13-May-2022 * -* @author (original) Sean -* @date (original) 15-Jan-2020 +* @author (original) Sean +* @date (original) 15-Jan-2020 * ***************************************************************************/ -#include +#include // Using fabs() function #include "AirTrap.h" #include "BloodFlow.h" @@ -26,6 +26,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "Reservoirs.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -46,9 +47,8 @@ static const U32 UF_ACCURACY_CHECK_INTERVAL = ((1 * MIN_PER_HOUR * SEC_PER_MIN * 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 150 ///< Fixed rate for saline bolus delivery. -#define MIN_SALINE_BOLUS_VOLUME_PCT 0.8 ///< Minimum saline bolus volume measured by independent means (as % of target). -#define MAX_SALINE_BOLUS_VOLUME_PCT 1.2 ///< Maximum saline bolus volume measured by independent means (as % of target). +#define SALINE_BOLUS_RATE_ML_MIN 300 ///< Fixed rate for saline bolus delivery. +#define MAX_BOLUS_ERROR_PCT 0.2 ///< Maximum error in saline bolus volume delivered (as a percentage of target). #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0 ///< Maximum delta between new and previous measured UF volume. @@ -62,6 +62,8 @@ 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). static F32 resFinalVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir final volume for ultrafiltration (i.e. where did we end after switch with each reservoir). +static F32 resCurrVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir current volume. +static F32 resLastVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir previous volume. static F32 measUFVolumeFromPriorReservoirs; ///< Current total ultrafiltration volume from previous reservoirs in current treatment. static U32 uFTimeMS; ///< Current elapsed ultrafiltration time (in ms). Used for calculating UF reference volume. @@ -75,12 +77,10 @@ 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 salineBolusAutoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. -static F32 totalSalineVolumeDelivered; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). -static F32 bolusSalineVolumeDelivered; ///< Volume (mL) of current bolus delivered so far. -static F32 bolusSalineVolumeDelivered_Safety; ///< Volume (mL) of current bolus delivered so far according to safety monitor. -static S32 bolusSalineMotorCount; ///< Blood pump motor rev count during saline bolus to calculate saline bolus volume independently for safety. -static U32 bolusSalineLastMotorCount; ///< Last blood pump count from last saline bolus volume update. +static BOOL salineBolusAutoResumeUF = FALSE; ///< 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 F32 expectedSalineBolusVolume_mL; ///< Volume (mL) of current bolus delivered so far (calculated from target blood flow rate). static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. static U32 uFAccuracyCheckTimerCtr; ///< Timer counter to determine when next to check ultrafiltration accuracy. @@ -125,6 +125,8 @@ refUFVolume = 0.0; measUFVolume = 0.0; measUFVolumeFromPriorReservoirs = 0.0; + // Send reset UF volumes to dialysate outlet pump + setDialOutUFVolumes( refUFVolume, measUFVolume ); uFTimeMS = 0; lastUFTimeStamp = 0; @@ -135,7 +137,7 @@ setUFRate = 0.0; salineBolusBroadcastTimerCtr = 0; - totalSalineVolumeDelivered = 0.0; + totalSalineVolumeDelivered_mL = 0.0; uFAccuracyCheckTimerCtr = 0; lastUFVolumeChecked = 0.0; @@ -156,14 +158,17 @@ { salineBolusStartRequested = FALSE; salineBolusAbortRequested = FALSE; - salineBolusAutoResumeUF = FALSE; - bolusSalineVolumeDelivered = 0.0; - bolusSalineVolumeDelivered_Safety = 0.0; - bolusSalineMotorCount = 0; + bolusSalineVolumeDelivered_mL = 0.0; + expectedSalineBolusVolume_mL = 0.0; if ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) { currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; } + if ( TRUE == salineBolusAutoResumeUF ) + { + salineBolusAutoResumeUF = FALSE; + currentUFState = UF_RUNNING_STATE; + } } /*********************************************************************//** @@ -179,6 +184,8 @@ *************************************************************************/ void transitionToDialysis( void ) { + PUMP_CONTROL_MODE_T mode = PUMP_CONTROL_MODE_CLOSED_LOOP; + // Set last UF timestamp so UF ref is resumed from this time lastUFTimeStamp = getMSTimerCount(); // Send dialysate outlet pump latest UF volumes @@ -187,19 +194,33 @@ // Inform DG interface that dialysis has started/resumed dialysisResumed(); + resetReservoirsVariables(); + // Set valves for dialysis setValvePosition( VDI, VALVE_POSITION_B_OPEN ); setValvePosition( VDO, VALVE_POSITION_B_OPEN ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Restart pumps -#ifndef RUN_PUMPS_OPEN_LOOP - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); -#else - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_BLOOD_PUMP_OPEN_LOOP ) ) + { + mode = PUMP_CONTROL_MODE_OPEN_LOOP; + } #endif + + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, mode ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DIALYSATE_INLET_PUMP_OPEN_LOOP ) ) + { + mode = PUMP_CONTROL_MODE_OPEN_LOOP; + } +#endif + + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, mode ); + setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); // Start Heparin pump as appropriate startHeparinPump(); @@ -226,22 +247,20 @@ { HEPARIN_STATE_T currentHeparinState = getHeparinState(); U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); - U32 minRem = getTreatmentTimeRemainingSecs() / SEC_PER_MIN; + F32 minRem = (F32)getTreatmentTimeRemainingSecs() / (F32)SEC_PER_MIN; F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); // Do not run syringe pump if no Heparin included in prescription or it was paused or if Heparin should be stopped at this stage of treatment - if ( ( minRem > preStop ) && ( HEPARIN_STATE_STOPPED == currentHeparinState ) ) + if ( ( minRem > (F32)preStop ) && ( HEPARIN_STATE_STOPPED == currentHeparinState ) ) { - // If not done with bolus, start/resume bolus - if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) + if ( hepRate > 0.0 ) { - startHeparinBolus(); // TODO - check return status + startHeparinContinuous(); // TODO - check return status } - // Otherwise, start/resume continuous delivery else { - startHeparinContinuous(); // TODO - check return status + setHeparinCompleted(); } } else @@ -270,15 +289,27 @@ maxUFVolumeML = maxUFVol; setUFRate = uFRate; - if ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) + // Make rate changes in real time if currently performing dialysis. + if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) { -#ifndef RUN_PUMPS_OPEN_LOOP - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); -#else - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + PUMP_CONTROL_MODE_T mode = PUMP_CONTROL_MODE_CLOSED_LOOP; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_BLOOD_PUMP_OPEN_LOOP ) ) + { + mode = PUMP_CONTROL_MODE_OPEN_LOOP; + } #endif + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, mode ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DIALYSATE_INLET_PUMP_OPEN_LOOP ) ) + { + mode = PUMP_CONTROL_MODE_OPEN_LOOP; + } +#endif + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, mode ); + setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } } @@ -307,8 +338,8 @@ * @brief * The signalStartSalineBolus function handles user request to initiate a * saline bolus. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusStartRequested, response sent * @return none *************************************************************************/ void signalStartSalineBolus( void ) @@ -329,14 +360,14 @@ { 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 ( currSalineBolusState != SALINE_BOLUS_STATE_IDLE ) { rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; } - else if ( totalSalineVolumeDelivered >= (F32)MAX_SALINE_VOLUME_DELIVERED ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; - } else { accept = TRUE; @@ -351,8 +382,8 @@ * @brief * The signalAbortSalineBolus function handles user request to abort a * saline bolus. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusAbortRequested, response sent * @return none *************************************************************************/ void signalAbortSalineBolus( void ) @@ -427,22 +458,20 @@ * @brief * The getUltrafiltrationVolumeCollected function gets the current ultrafiltration * volume collected so far for current treatment. - * @details Inputs: measUFVolume, measUFVolumeFromPriorReservoirs + * @details Inputs: measUFVolume * @details Outputs: none * @return measUFVolume *************************************************************************/ F32 getUltrafiltrationVolumeCollected( void ) { - F32 result = measUFVolume; - - return result; + return measUFVolume; } /*********************************************************************//** * @brief * The getUltrafiltrationReferenceVolume function gets the current ultrafiltration * reference volume. - * @details Inputs: measUFVolume, measUFVolumeFromPriorReservoirs + * @details Inputs: refUFVolume * @details Outputs: none * @return refUFVolume *************************************************************************/ @@ -453,6 +482,19 @@ /*********************************************************************//** * @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 * @details Outputs: currentUFState, outlet pump set point @@ -473,6 +515,7 @@ setDialOutPumpTargetRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); // Go to UF paused state currentUFState = UF_PAUSED_STATE; + sendTreatmentLogEventData( UF_START_RESUME_EVENT, UF_RUNNING_STATE, UF_PAUSED_STATE ); } else { @@ -519,11 +562,12 @@ { result = TRUE; // Set outlet pump to dialysate rate + set UF rate - setDialOutPumpTargetRate( setDialysateFlowRate + FLOAT_TO_INT_WITH_ROUND( setUFRate ), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); // Restart UF time accumulation for reference volume calculation lastUFTimeStamp = getMSTimerCount(); // Go to UF running state currentUFState = UF_RUNNING_STATE; + sendTreatmentLogEventData( UF_START_RESUME_EVENT, UF_PAUSED_STATE, UF_RUNNING_STATE ); } else { @@ -601,10 +645,10 @@ { DIALYSIS_STATE_T result = DIALYSIS_UF_STATE; U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); - U32 minRem = getTreatmentTimeRemainingSecs() / SEC_PER_MIN; + F32 minRem = (F32)getTreatmentTimeRemainingSecs() / (F32)SEC_PER_MIN; // Stop Heparin delivery if we have reached Heparin pre-stop point - if ( getTreatmentTimeRemainingSecs() < preStop ) + if ( minRem <= (F32)preStop ) { stopSyringePump(); setHeparinCompleted(); @@ -690,13 +734,10 @@ *************************************************************************/ static UF_STATE_T handleUFStartState( DIALYSIS_STATE_T *dialysisState ) { - UF_STATE_T result; - lastUFTimeStamp = getMSTimerCount(); uFTimeMS = 0; - result = UF_RUNNING_STATE; - return result; + return UF_RUNNING_STATE; } /*********************************************************************//** @@ -831,10 +872,7 @@ if ( ( FALSE == isBloodPumpRunning() ) && ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) { // Reset bolus data before we start - bolusSalineVolumeDelivered = 0.0; - bolusSalineVolumeDelivered_Safety = 0.0; - bolusSalineMotorCount = 0; - bolusSalineLastMotorCount = getBloodPumpMotorCount(); + bolusSalineVolumeDelivered_mL = 0.0; bolusSalineLastVolumeTimeStamp = getMSTimerCount(); // Bypass dialyzer @@ -876,15 +914,16 @@ 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 maxBolusErrorMl = bolusTargetVolume * MAX_BOLUS_ERROR_PCT; F32 bldFlowRate = getMeasuredBloodFlowRate(); // TODO - should I use raw flow instead of filtered here??? F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; + F32 expVolSinceLastUpdateMl = (F32)getTargetBloodFlowRate() * timeSinceLastVolumeUpdateMin; // Update saline bolus volumes bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - bolusSalineVolumeDelivered += volSinceLastUpdateMl; - totalSalineVolumeDelivered += volSinceLastUpdateMl; - bolusSalineMotorCount = u32BiDiffWithWrap( bolusSalineLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - bolusSalineVolumeDelivered_Safety = ( (F32)bolusSalineMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc (from PBA). + bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; + totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; + expectedSalineBolusVolume_mL += expVolSinceLastUpdateMl; // Check for empty saline bag per arterial line pressure if ( TRUE == isSalineBagEmpty() ) @@ -895,23 +934,15 @@ } // Determine if we have reached maximum saline delivery volume - if ( ( totalSalineVolumeDelivered >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) + if ( ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) { result = SALINE_BOLUS_STATE_MAX_DELIVERED; } else { // Determine if bolus is complete - if ( bolusSalineVolumeDelivered >= bolusTargetVolume ) + if ( bolusSalineVolumeDelivered_mL >= bolusTargetVolume ) { - // If safety thinks we have under-delivered the bolus, throw a fault - if ( bolusSalineVolumeDelivered_Safety < ( bolusTargetVolume * MIN_SALINE_BOLUS_VOLUME_PCT ) ) - { -#ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); - errorFound = TRUE; -#endif - } result = SALINE_BOLUS_STATE_IDLE; } // User is aborting saline bolus @@ -920,14 +951,13 @@ salineBolusAbortRequested = FALSE; result = SALINE_BOLUS_STATE_IDLE; } - // Determine if safety thinks we have over-delivered the bolus - else if ( bolusSalineVolumeDelivered_Safety > ( bolusTargetVolume * MAX_SALINE_BOLUS_VOLUME_PCT ) ) + // Determine if saline bolus is under/over delivering + else if ( ( fabs( expectedSalineBolusVolume_mL - bolusSalineVolumeDelivered_mL ) > maxBolusErrorMl ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_FLOW_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); + activateAlarmNoData( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE ); errorFound = TRUE; result = SALINE_BOLUS_STATE_IDLE; -#endif } } @@ -938,9 +968,10 @@ signalBloodPumpHardStop(); signalDialInPumpHardStop(); // Send last saline bolus data - bolusSalineVolumeDelivered = 0.0; 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 @@ -996,9 +1027,9 @@ SALINE_BOLUS_DATA_PAYLOAD_T data; data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - data.cumSalineVolumeMl = totalSalineVolumeDelivered; - data.bolSalineVolumeMl = bolusSalineVolumeDelivered; - broadcastSalineBolusData( data ); + data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; + data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; + broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); salineBolusBroadcastTimerCtr = 0; } } @@ -1018,9 +1049,12 @@ // Check UF rate over last hour if ( uFMeasRate > MAX_UF_RATE_ML_PER_HOUR ) { -#ifndef DISABLE_UF_ALARMS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_UF_RATE_TOO_HIGH_ERROR, uFMeasRate ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ULTRAFILTRATION_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_UF_RATE_TOO_HIGH_ERROR, uFMeasRate ); + } } // Increment timer and see if time to start another 1 hour check period if ( ++uFAccuracyCheckTimerCtr >= UF_ACCURACY_CHECK_INTERVAL ) @@ -1033,9 +1067,12 @@ // Check total UF volume error if ( ( fabs( refUFVolume - measUFVolume ) ) >= (F32)MAX_UF_ACCURACY_ERROR_ML ) { -#ifndef DISABLE_UF_ALARMS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_UF_VOLUME_ACCURACY_ERROR, refUFVolume, measUFVolume ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ULTRAFILTRATION_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_UF_VOLUME_ACCURACY_ERROR, refUFVolume, measUFVolume ); + } } } @@ -1054,17 +1091,21 @@ DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); LOAD_CELL_ID_T loadCell = ( activeRes == DG_RESERVOIR_1 ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); F32 latestResVolume = getLoadCellWeight( loadCell ); -#ifndef DISABLE_UF_ALARMS - F32 deltaVolume = latestResVolume - resFinalVolume[ activeRes ]; + F32 deltaVolume = latestResVolume - resLastVolume[ activeRes ]; // ensure volume change is not too excessive - indication that load cell was impacted by some kind of shock if ( fabs(deltaVolume) > MAX_ACTIVE_LOAD_CELL_CHANGE_G ) { - ALARM_ID_T deltaAlarm = ( getDGActiveReservoir() == DG_RESERVOIR_1 ? ALARM_ID_HD_LOAD_CELL_ACCELERATION_RES_1_ALARM : ALARM_ID_HD_LOAD_CELL_ACCELERATION_RES_2_ALARM ); - SET_ALARM_WITH_1_F32_DATA( deltaAlarm, deltaVolume ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ULTRAFILTRATION_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + ALARM_ID_T deltaAlarm = ( getDGActiveReservoir() == DG_RESERVOIR_1 ? ALARM_ID_HD_LOAD_CELL_ACCELERATION_RES_1_ALARM : + ALARM_ID_HD_LOAD_CELL_ACCELERATION_RES_2_ALARM ); + SET_ALARM_WITH_1_F32_DATA( deltaAlarm, deltaVolume ); + } } else -#endif { // Calculate UF volumes and provide to dialysate outlet pump controller measUFVolume = measUFVolumeFromPriorReservoirs + ( latestResVolume - resStartVolume[ activeRes ] ); @@ -1129,4 +1170,36 @@ measUFVolumeFromPriorReservoirs += ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); } +/*********************************************************************//** + * @brief + * The updateReservoirVolumes function updates the reservoir volumes based + * on new load cell readings. + * @details Inputs: none + * @details Outputs: resCurrVolume[], resLastVolume[] + * @param res1Vol new volume for reservoir 1 + * @param res2Vol new volume for reservoir 2 + * @return none + *************************************************************************/ +void updateReservoirVolumes( F32 res1Vol, F32 res2Vol ) +{ + resLastVolume[ DG_RESERVOIR_1 ] = resCurrVolume[ DG_RESERVOIR_1 ]; + resLastVolume[ DG_RESERVOIR_2 ] = resCurrVolume[ DG_RESERVOIR_2 ]; + resCurrVolume[ DG_RESERVOIR_1 ] = res1Vol; + resCurrVolume[ DG_RESERVOIR_2 ] = res2Vol; +} + +/*********************************************************************//** + * @brief + * The getReservoirUltrafiltrationVol function returns the ultrafiltration + * volume of a reservoir. + * @details Inputs: none + * @details Outputs: resStartVolume[], resFinalVolume[] + * @param reservoirID reservoir ID to calculate the ultrafiltration volume + * @return ultrafiltration volume of the reservoir + *************************************************************************/ +F32 getReservoirUltrafiltrationVol( DG_RESERVOIR_ID_T reservoirID ) +{ + return ( resFinalVolume[ reservoirID ] - resStartVolume[ reservoirID ] ); +} + /**@}*/