Index: firmware/App/Controllers/AirTrap.c =================================================================== diff -u -r20fe5dc6869557f96c86fbd9d7f2f634ce23696a -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 20fe5dc6869557f96c86fbd9d7f2f634ce23696a) +++ firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -18,6 +18,7 @@ #include "AirPump.h" #include "AirTrap.h" #include "AlarmMgmt.h" +#include "BloodFlow.h" #include "FPGA.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" @@ -27,6 +28,7 @@ #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" +#include "Valves.h" /** * @addtogroup AirTrap @@ -35,17 +37,16 @@ // ********** private definitions ********** - #define AIR_TRAP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the air trap data is published on the CAN bus. #define AIR_TRAP_FILL_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Air trap fill timeout period (in ms). #define AIR_PUMP_ON_DELAY_TIME_MS ( 10 * MS_PER_SECOND ) ///< Delay between air pump On (in ms). #define AIR_PUMP_ON_STOP_TIME_MIN_MS 200 ///< Stop air Pump time. -#define AIR_PUMP_ON_ERROR_MAX_CNT 6 ///< Maximum number of air pump on events within time window before alarm triggered. Do not exceed MAX_TIME_WINDOWED_COUNT. -#define AIR_PUMP_ON_ERROR_TIME_WIN_MS ( 60 * MS_PER_SECOND ) ///< Time window for Air Pump on count error. +#define AIR_TRAP_ACTIVITY_MAX_COUNT 5 ///< Maximum number of air trap events (fills and air pump activations) within time window before alarm triggered. +#define AIR_TRAP_ACTIVITY_TIME_WIN_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time window to monitor for too many air trap events. #define AIR_TRAP_LEVEL_DEBOUNCE_TIME_MS ( 400 ) ///< Air trap level sensor debounce time -/// Persistence period for illegal level sensors fault. +// Persistence period for illegal level sensors fault. #define AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Air trap illegal values timeout (in ms) -#define AIR_TRAP_UPPER_LEVEL_FLUID_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Air trap upper level fluid timeout in milliseconds. +#define AIR_TRAP_UPPER_LEVEL_FLUID_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Air trap upper level fluid timeout in milliseconds. /// Volume (in mL) of venous portion of blood circuit line. TODO - get actual volume from Systems. #define VENOUS_LINE_VOLUME_ML ( 200.0F ) @@ -122,6 +123,7 @@ initPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_AIR_TRAP_UPPER_LEVEL_FLUID_TIME_OUT, 0, AIR_TRAP_UPPER_LEVEL_FLUID_TIMEOUT_MS ); + initTimeWindowedCount( TIME_WINDOWED_COUNT_AIRTRAP_TOO_FREQ_ALARM, AIR_TRAP_ACTIVITY_MAX_COUNT, AIR_TRAP_ACTIVITY_TIME_WIN_MS ); } /*********************************************************************//** @@ -195,6 +197,26 @@ /*********************************************************************//** * @brief + * The isAirTrapFillInProgress function determines whether the air trap is + * currently filling. + * @details Inputs: airTrapControllerState + * @details Outputs: none + * @return TRUE if air trap is currently filling, FALSE if not. + *************************************************************************/ +BOOL isAirTrapFillInProgress( void ) +{ + BOOL result = FALSE; + + if ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The execAirTrapMonitor function executes the air trap monitor. * @details Inputs: FPGA air trap levels GPIO pin levels, airTrapIllegalLevelSensorsCtr * @details Outputs: airTrapLevels[], airTrapIllegalLevelSensorsCtr @@ -390,7 +412,7 @@ } } - //Open valve once at start of treatment ( blood priming) + //Open valve once at start of treatment (blood priming) else if ( TRUE == airTrapValveOpenAtStartOfTreatement ) { airTrapValveOpenAtStartOfTreatement = FALSE; @@ -400,10 +422,12 @@ } setValveAirTrap( STATE_OPEN ); + signalBloodPumpHardStop(); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); fillStartTime = getMSTimerCount(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)AIR_TRAP_VALVE_CLOSED_STATE, (U32)result ) + result = AIR_TRAP_VALVE_OPEN_STATE; } // Turn air pump off after defined time or air detected at upper level @@ -422,9 +446,19 @@ if ( ( AIR_PUMP_STATE_OFF == getAirPumpState() ) && ( TRUE == didTimeout( airPumpOnDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) { - setAirPumpState( AIR_PUMP_STATE_ON ); - stopAirPumpStartTime = getMSTimerCount(); - signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); + // Check air trap activity (fills/air pump activations) too frequent + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_AIRTRAP_TOO_FREQ_ALARM ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AIR_TRAP_ACTIVITY_TOO_FREQUENT, TIME_WINDOWED_COUNT_AIRTRAP_TOO_FREQ_ALARM ); + // reset alarm count after alarm so that time window does not interfere with alarm recovery + initTimeWindowedCount( TIME_WINDOWED_COUNT_AIRTRAP_TOO_FREQ_ALARM, AIR_TRAP_ACTIVITY_MAX_COUNT, AIR_TRAP_ACTIVITY_TIME_WIN_MS ); + } + else + { + setAirPumpState( AIR_PUMP_STATE_ON ); + stopAirPumpStartTime = getMSTimerCount(); + signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); + } } } @@ -438,10 +472,12 @@ } setValveAirTrap( STATE_OPEN ); + signalBloodPumpHardStop(); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); fillStartTime = getMSTimerCount(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)AIR_TRAP_VALVE_CLOSED_STATE, (U32)result ) + result = AIR_TRAP_VALVE_OPEN_STATE; } return result; @@ -478,6 +514,7 @@ result = AIR_TRAP_VALVE_CLOSED_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)AIR_TRAP_VALVE_OPEN_STATE, (U32)result ) } + return result; } Index: firmware/App/Controllers/AirTrap.h =================================================================== diff -u -r7092920786ccf9d52c00b84c6f47ccebc4d28118 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Controllers/AirTrap.h (.../AirTrap.h) (revision 7092920786ccf9d52c00b84c6f47ccebc4d28118) +++ firmware/App/Controllers/AirTrap.h (.../AirTrap.h) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -14,40 +14,42 @@ * @date (original) 16-Sep-2020 * ***************************************************************************/ - -#ifndef __AIR_TRAP_H__ -#define __AIR_TRAP_H__ - -#include "HDCommon.h" - -/** - * @defgroup AirTrap AirTrap - * @brief Air Trap valve controller / level sensor monitor module. Monitors the + +#ifndef __AIR_TRAP_H__ +#define __AIR_TRAP_H__ + +#include "HDCommon.h" + +/** + * @defgroup AirTrap AirTrap + * @brief Air Trap valve controller / level sensor monitor module. Monitors the * air trap level sensors. Controls the air trap valve when level controlling is - * turned on. - * - * @addtogroup AirTrap - * @{ - */ - -// ********** public definitions ********** - -/// Enumeration of air trap level sensors monitored by this module. -typedef enum AirTrapLevelSensors -{ - AIR_TRAP_LEVEL_SENSOR_LOWER = 0, ///< Lower air trap sensor - AIR_TRAP_LEVEL_SENSOR_UPPER, ///< Upper air trap sensor - NUM_OF_AIR_TRAP_LEVEL_SENSORS ///< Number of air trap sensors -} AIR_TRAP_LEVEL_SENSORS_T; - -/// Enumeration of air trap level sensor levels. -typedef enum AirTrapLevelSensorLevels -{ - AIR_TRAP_LEVEL_AIR = 0, ///< Air trap level sensor detects air - AIR_TRAP_LEVEL_FLUID, ///< Air trap level sensor detects fluid - NUM_OF_AIR_TRAP_LEVELS ///< Number of air trap level sensor levels -} AIR_TRAP_LEVELS_T; - + * turned on. + * + * @addtogroup AirTrap + * @{ + */ + +// ********** public definitions ********** + +#define AIR_TRAP_FILL_BLOOD_FLOW_RATE 150 ///< Blood flow rate (mL/min) at which an air trap fill is done. + +/// Enumeration of air trap level sensors monitored by this module. +typedef enum AirTrapLevelSensors +{ + AIR_TRAP_LEVEL_SENSOR_LOWER = 0, ///< Lower air trap sensor + AIR_TRAP_LEVEL_SENSOR_UPPER, ///< Upper air trap sensor + NUM_OF_AIR_TRAP_LEVEL_SENSORS ///< Number of air trap sensors +} AIR_TRAP_LEVEL_SENSORS_T; + +/// Enumeration of air trap level sensor levels. +typedef enum AirTrapLevelSensorLevels +{ + AIR_TRAP_LEVEL_AIR = 0, ///< Air trap level sensor detects air + AIR_TRAP_LEVEL_FLUID, ///< Air trap level sensor detects fluid + NUM_OF_AIR_TRAP_LEVELS ///< Number of air trap level sensor levels +} AIR_TRAP_LEVELS_T; + /// Payload record structure for air trap data broadcast message typedef struct { @@ -57,28 +59,29 @@ U32 rawUpperLevel; ///< Raw Upper air trap level sensor state } AIR_TRAP_PAYLOAD_T; -// ********** public function prototypes ********** - +// ********** public function prototypes ********** + void initAirTrap( void ); -void resetAirTrap( void ); +void resetAirTrap( void ); void execAirTrapController( void ); void execAirTrapMonitor( void ); -void execAirTrapMonitorTreatment( void ); - -void startAirTrapControl( void ); +void execAirTrapMonitorTreatment( void ); + +void startAirTrapControl( void ); void endAirTrapControl( void ); BOOL isAirTrapControlling( void ); - +BOOL isAirTrapFillInProgress( void ); + AIR_TRAP_LEVELS_T getAirTrapLevel( AIR_TRAP_LEVEL_SENSORS_T sensor ); AIR_TRAP_LEVELS_T getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSORS_T sensor ); -BOOL testSetAirTrapDataPublishIntervalOverride( U32 value ); -BOOL testResetAirTrapDataPublishIntervalOverride( void ); -BOOL testSetAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor, AIR_TRAP_LEVELS_T level ); +BOOL testSetAirTrapDataPublishIntervalOverride( U32 value ); +BOOL testResetAirTrapDataPublishIntervalOverride( void ); +BOOL testSetAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor, AIR_TRAP_LEVELS_T level ); BOOL testResetAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor ); BOOL testSetRawAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor, AIR_TRAP_LEVELS_T level ); -BOOL testResetRawAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor ); - -/**@}*/ - -#endif +BOOL testResetRawAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor ); + +/**@}*/ + +#endif Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r20fe5dc6869557f96c86fbd9d7f2f634ce23696a -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 20fe5dc6869557f96c86fbd9d7f2f634ce23696a) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -364,7 +364,7 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED1, (U32)valve ); } return result; @@ -393,19 +393,20 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED2, (U32)valve ); } return result; } /*********************************************************************//** * @brief - * The getValvePosition function returns the current position of a valve. + * The getValvePosition function returns the current position of a + * given valve. * @details Inputs: none * @details Outputs: valvesStatus - * @param valve that the position is requested - * @return returns the current position of the valve in enum + * @param valve Valve to get the position of + * @return returns the current position of the given valve *************************************************************************/ VALVE_POSITION_T getValvePosition( VALVE_T valve ) { @@ -417,7 +418,7 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED3, (U32)valve ); } return position; @@ -1122,7 +1123,7 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED5, (U32)valve ); break; } } @@ -1443,7 +1444,7 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED6, (U32)valve ); break; } } Index: firmware/App/Modes/BloodPrime.c =================================================================== diff -u -rd963f2a611b2d5ed18172c390b0f593045abced7 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision d963f2a611b2d5ed18172c390b0f593045abced7) +++ firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -61,6 +61,8 @@ static U32 bloodPrimeRampControlTimerCtr; ///< Timer counter for determining interval for controlling BP ramp. static U32 bloodPrimePublishTimerCtr; ///< Timer counter for determining interval for blood prime status to be published. +static BOOL airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. + /// 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 }; @@ -126,21 +128,35 @@ setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Ensure dialysate outlet and Heparin pumps are stopped signalDialOutPumpHardStop(); stopSyringePump(); // start blood and dialysate inlet pumps - setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); cmdStartDGTrimmerHeater(); setCurrentSubState( (U32)bloodPrimeState ); // Start air trap control startAirTrapControl(); + // make sure air trap fill is handled right + if ( TRUE == isAirTrapFillInProgress() ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + else + { + // Start blood pump at prescribed flow rate + setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + // re-open VBV for blood recirculation + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + } + // Set user alarm recovery actions allowed in this sub-mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); @@ -151,12 +167,12 @@ * @brief * The resetBloodPrimeFlags function resets the blood prime request flags. * @details Inputs: none - * @details Outputs: Blood prime request flags reset to FALSE. + * @details Outputs: airTrapFillInProgress * @return none *************************************************************************/ static void resetBloodPrimeFlags( void ) { - // No flags for now + airTrapFillInProgress = isAirTrapFillInProgress(); } /*********************************************************************//** @@ -210,8 +226,9 @@ * @brief * The handleBloodPrimeRampState function handles the blood prime ramp * state operations. - * @details Inputs: flags - * @details Outputs: flags handled + * @details Inputs: bloodPrimeTargetVolume_mL, airTrapFillInProgress, + * bloodPrimeRampControlTimerCtr + * @details Outputs: cumulativeBloodPrimeVolume_mL, bloodPrimeRampControlTimerCtr * @return next blood prime state *************************************************************************/ static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ) @@ -227,6 +244,22 @@ cumulativeBloodPrimeVolume_mL.data = bloodPrimeTargetVolume_mL; } + // if an air trap fill has started, set BP rate and VBV state accordingly + if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // if an air trap fill has completed, restore BP and VBV to blood prime ramp settings + else if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // re-open VBV after fill + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // Blood pump rate will be set to ramp rate below + } + // Has blood prime completed? if ( getBloodPrimeVolume() >= bloodPrimeTargetVolume_mL ) { @@ -236,13 +269,11 @@ signalBloodPrimeToDialysis(); // Signal treatment mode that it's time to start dialysis cmdStopDGTrimmerHeater(); // Stop trimmer heater - dialysis sub-mode will restart as appropriate } - else + else if ( isAirTrapFillInProgress() != TRUE ) { // ramp blood pump on ramp interval if ( ++bloodPrimeRampControlTimerCtr >= BLOOD_PRIME_RAMPING_INTERVAL ) { - U32 setBPRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); - bloodPrimeRampControlTimerCtr = 0; bloodPrimeRampFlowRate_mL_min += bloodPrimeRampStep_mL; setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r2f9807457197c347c20a24c64492edcf063f3daa -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 2f9807457197c347c20a24c64492edcf063f3daa) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -103,6 +103,7 @@ static F32 setUFRate; ///< Currently set ultrafiltration rate (from prescription). static BOOL autoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. +static BOOL airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. static BLOOD_LEAK_ZEROING_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // ********** private function prototypes ********** @@ -160,6 +161,7 @@ resetDialOutRateOffset(); autoResumeUF = FALSE; + airTrapFillInProgress = FALSE; for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { @@ -204,7 +206,7 @@ * may be stopped and resumed multiple times due to alarms or user intervention * and we don't want to start the treatment all over again. * @details Inputs: none - * @details Outputs: none + * @details Outputs: airTrapFillInProgress, lastUFTimeStamp * @return none *************************************************************************/ void transitionToDialysis( void ) @@ -217,17 +219,36 @@ lastUFTimeStamp = getMSTimerCount(); // Send dialysate outlet pump latest UF volumes setDialOutUFVolumes( refUFVolume, measUFVolume ); + // initialize air trap fill flag + airTrapFillInProgress = FALSE; + // Reset saline bolus state machine + resetSalineBolus(); resetReservoirsVariables(); // Reset the blood leak zeroing variables resetBloodLeakZeroingVariables(); + // make sure air trap fill is handled right + if ( TRUE == isAirTrapFillInProgress() ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, mode ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + else + { + // Start blood pump at prescribed flow rate + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, mode ); + // re-open VBV for blood recirculation + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + } + // 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 _RELEASE_ @@ -236,7 +257,6 @@ 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 ) ) { @@ -557,7 +577,7 @@ * @brief * The execDialysis function executes the Dialysis sub-mode state machine. * @details Inputs: currentDialysisState - * @details Outputs: currentDialysisState + * @details Outputs: currentDialysisState, airTrapFillInProgress * @return none *************************************************************************/ void execDialysis( void ) @@ -572,6 +592,7 @@ bloodLeakZeroingStatus.zeroingRequestState = BLOOD_LEAK_ZEROING_RQST_REQUESTED; } + // Check for blood leak zeroing request if ( ( BLOOD_LEAK_ZEROING_RQST_REQUESTED == bloodLeakZeroingStatus.zeroingRequestState ) && ( DIALYSIS_UF_STATE == currentDialysisState ) ) { if ( TRUE == checkHasReservoirBeenSwitched() ) @@ -607,6 +628,8 @@ // Calculate UF measured volume and provide to dialysate outlet pump controller (watch UF regardless of dialysis state) updateUFVolumes(); + airTrapFillInProgress = isAirTrapFillInProgress(); + if ( priorSubState != currentDialysisState ) { setCurrentSubState( (U32)currentDialysisState ); @@ -621,7 +644,7 @@ * @brief * The handleDialysisUltrafiltrationState function handles the ultrafiltration * state of the Dialysis state machine. - * @details Inputs: currentUFState + * @details Inputs: currentUFState, airTrapFillInProgress * @details Outputs: currentUFState * @return next Dialysis state. *************************************************************************/ @@ -639,6 +662,23 @@ setHeparinCompleted(); } + // if an air trap fill has started, set BP rate and VBV state accordingly + if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // if an air trap fill has completed, restore BP and VBV to blood prime ramp settings + if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // restore BP to set blood flow rate + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // re-open VBV for blood recirculation + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + } + // Handle current ultrafiltration state switch ( currentUFState ) { @@ -707,14 +747,31 @@ * @brief * The handleDialysisBloodLeakZeroingState function handles the blood leak * zeroing sub state of the state machine. - * @details Inputs: none + * @details Inputs: airTrapFillInProgress * @details Outputs: none * @return next Dialysis state. *************************************************************************/ static DIALYSIS_STATE_T handleDialysisBloodLeakZeroingState( void ) { DIALYSIS_STATE_T result = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + // if an air trap fill has started, set BP rate and VBV state accordingly + if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // if an air trap fill has completed, restore BP and VBV to blood prime ramp settings + if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // restore BP to set blood flow rate + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // re-open VBV for blood recirculation + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + } + result = execBloodLeakZeroing(); return result; @@ -724,7 +781,7 @@ * @brief * The handleUFPausedState function handles the Paused state of the * ultrafiltration state machine. - * @details Inputs: salineBolusStartRequested + * @details Inputs: none * @details Outputs: if ultrafiltration resumption requested, UF time is set to resume. * @param dialysisState next dialysis state * @return next ultrafiltration state. Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -raddd69fc864448c17a4a68b2bfa466af5483f987 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision addd69fc864448c17a4a68b2bfa466af5483f987) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -47,6 +47,7 @@ #define INSTIT_MAX_INLET_WATER_COND_ALARM_USPCM 300.0F ///< Institutional record max inlet water conductivity alarm in uS/cm. #define INSTIT_MAX_MIN_VEN_PRES_WIDE_LIMIT_MMHG 400 ///< Institutional record max min venous pressure wide limit in mmHg. #define INSTIT_MIN_MIN_VEN_PRES_WIDE_LIMIT_MMHG 0 ///< Institutional record min min venous pressure wide limit in mmHg. +#define RINSEBACK_MIN_VEN_PRESSURE_MMHG -100 ///< Minimum venous pressure (in mmHg) while in rinseback state. /// Record for range and default of treatment parameters. typedef struct @@ -959,9 +960,19 @@ * @details Outputs: none * @return the min venous pressure wide limit window in mmHg. *************************************************************************/ -S32 getMinVenousPressureWideValueMMHG( void ) +S32 getMinVenousPressureWideValueMMHG( void ) { - return hdInstitutionalRecord.minVenPressWideLimitWindowMMHG; + S32 minVenPressureLimit = hdInstitutionalRecord.minVenPressWideLimitWindowMMHG; + HD_OP_MODE_T opMode = getCurrentOperationMode(); + TREATMENT_STATE_T curTxState = getTreatmentState(); + + // while in rinseback state of treatment mode, the minimum venous pressure limit is reduced + if ( ( MODE_TREA == opMode ) && ( TREATMENT_RINSEBACK_STATE == curTxState ) ) + { + minVenPressureLimit = RINSEBACK_MIN_VEN_PRESSURE_MMHG; + } + + return minVenPressureLimit; } /*********************************************************************//** @@ -1047,8 +1058,12 @@ result &= ( ( nvInstRcrd->minRORejectionRatioPCT <= INSTIT_MIN_RO_REJECTION_RATIO_MAX_PCT ) ? TRUE : FALSE ); result &= ( ( nvInstRcrd->minInletWaterCondAlarmLimitUSPCM >= 0.0F ) && ( nvInstRcrd->minInletWaterCondAlarmLimitUSPCM <= INSTIT_MAX_INLET_WATER_COND_ALARM_USPCM ) ? TRUE : FALSE ); - result &= ( ( nvInstRcrd->minVenPressWideLimitWindowMMHG <= INSTIT_MAX_MIN_VEN_PRES_WIDE_LIMIT_MMHG ) && - ( nvInstRcrd->minVenPressWideLimitWindowMMHG >= INSTIT_MIN_MIN_VEN_PRES_WIDE_LIMIT_MMHG ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minVenPressWideLimitWindowMMHG <= INSTIT_MAX_MIN_VEN_PRES_WIDE_LIMIT_MMHG ) && + ( nvInstRcrd->minVenPressWideLimitWindowMMHG >= INSTIT_MIN_MIN_VEN_PRES_WIDE_LIMIT_MMHG ) ? TRUE : FALSE ); + // NOTE: the treatment end blood flow rate in mL/min can be either 0 or 100 <= blood flow mL/min <= 500. + result &= ( ( nvInstRcrd->txEndBloodFlowMLPM == 0 ) || + ( ( nvInstRcrd->txEndBloodFlowMLPM >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].min.uInt ) && + ( nvInstRcrd->txEndBloodFlowMLPM <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].max.uInt ) ) ? TRUE : FALSE ); return result; } @@ -1060,17 +1075,28 @@ * treatment parameters. * @details Inputs: none * @details Outputs: hdInstitutionalRecord - * @param nvInstitutionalRecord pointer to the newly received institutional record - * in the non-volatile data management. - * @return none + * @return Institutional record treatment end blood flow in mL/min *************************************************************************/ void setNVInstitutionalRecordToTxParamsRecord( HD_INSTITUTIONAL_RECORD_T* nvInstitutionalRecord ) { - memcpy( &hdInstitutionalRecord, nvInstitutionalRecord, sizeof(HD_INSTITUTIONAL_RECORD_T) ); + memcpy( &hdInstitutionalRecord, nvInstitutionalRecord, sizeof( HD_INSTITUTIONAL_RECORD_T ) ); } /*********************************************************************//** * @brief + * The getNVInstitutionalRecordTxEndBloodFlowMLPM function returns the institutional + * record's treatment end blood flow in mL/min. + * @details Inputs: hdInstitutionalRecord + * @details Outputs: none + * @return none + *************************************************************************/ +U32 getNVInstitutionalRecordTxEndBloodFlowMLPM( void ) +{ + return hdInstitutionalRecord.txEndBloodFlowMLPM; +} + +/*********************************************************************//** + * @brief * The extractTreatmentParamsFromPayload function extracts the individual * treatment parameters received from the UI into a staging array where * they will be validated and stay until user confirms them. Index: firmware/App/Modes/ModeTreatmentParams.h =================================================================== diff -u -raddd69fc864448c17a4a68b2bfa466af5483f987 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/ModeTreatmentParams.h (.../ModeTreatmentParams.h) (revision addd69fc864448c17a4a68b2bfa466af5483f987) +++ firmware/App/Modes/ModeTreatmentParams.h (.../ModeTreatmentParams.h) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -79,7 +79,6 @@ U32 accepted; ///< Accepted or rejected based on if critical data has been set. TREATMENT_PARAMS_DATA_PAYLOAD_T treatment_parameters; ///< Record structure of treatment parameters F32 uFVolume_L; ///< Current ultrafiltration volume (in L). - } CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T; @@ -118,6 +117,7 @@ BOOL isNVInstitutionalRecordInRange( HD_INSTITUTIONAL_RECORD_T* nvInstRcrd ); // Is non-volatile memory institutional record in range void setNVInstitutionalRecordToTxParamsRecord( HD_INSTITUTIONAL_RECORD_T* nvInstitutionalRecord ); // Set the recently received institution record from NV to local tx parameters +U32 getNVInstitutionalRecordTxEndBloodFlowMLPM( void ); F32 getUltrafiltrationVolumeOriginal( void ); // Get the original ultrafiltration volume, set in pre-treatment mode by user. F32 getUltrafiltrationRateOriginal( void ); // Get/calculate the original ultrafiltration rate, by ultrafiltration volume and treatment duration set in pre-treatment mode by user. Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r2f9807457197c347c20a24c64492edcf063f3daa -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 2f9807457197c347c20a24c64492edcf063f3daa) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -82,6 +82,7 @@ static BOOL recircRequested; ///< Flag indicates user requesting to begin re-circulation (confirming disconnection and shunt). static BOOL backToTreatmentRequested; ///< Flag indicates user requesting to go back to treatment (confirming still connected). static BOOL endTreatmentRequested; ///< Flag indicates user requesting to end treatment. +static BOOL airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. // ********** private function prototypes ********** @@ -133,6 +134,7 @@ rinsebackAdditionalTimerCtr = 0; rinsebackPublishTimerCtr = 0; resetRinsebackFlags(); + airTrapFillInProgress = FALSE; // set to false initially - so keep after call to reset function } /*********************************************************************//** @@ -154,6 +156,7 @@ recircRequested = FALSE; backToTreatmentRequested = FALSE; endTreatmentRequested = FALSE; + airTrapFillInProgress = isAirTrapFillInProgress(); } /*********************************************************************//** @@ -405,8 +408,13 @@ * @brief * The handleRinsebackRunState function handles the rinseback run state * operations. - * @details Inputs: flags - * @details Outputs: cumulativeRinsebackVolume_mL, flags handled + * @details Inputs: endRinsebackRequested, pauseRinsebackRequested, + * airTrapFillInProgress, rinsebackRate_mL_min, incrRinsebackFlowRateRequested, + * decrRinsebackFlowRateRequested + * @details Outputs: cumulativeRinsebackVolume_mL, rinsebackTimerCtr, + * targetRinsebackVolumePlusAdditional_mL, rinsebackRate_mL_min, + * incrRinsebackFlowRateRequested, decrRinsebackFlowRateRequested, + * targetRinsebackVolumePlusAdditional_mL, rinsebackRate_mL_min * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackRunState( void ) @@ -453,9 +461,25 @@ setupForRinsebackStopOrPause(); result = RINSEBACK_PAUSED_STATE; } + // if an air trap fill has started, set BP rate and VBV state accordingly + else if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } // Otherwise, continue rinseback else - { // Has user requested rate change? + { + if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // re-open VBV after fill + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // restore BP to rinseback blood flow rate + setBloodPumpTargetFlowRate( rinsebackRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + } + // Has user requested rate change? if ( ( TRUE == incrRinsebackFlowRateRequested ) || ( TRUE == decrRinsebackFlowRateRequested ) ) { U32 rbRate = rinsebackRate_mL_min; @@ -576,8 +600,10 @@ * @brief * The handleRinsebackRunAdditionalState function handles the rinseback additional * state operations. - * @details Inputs: flags - * @details Outputs: flags handled + * @details Inputs: additionalRinsebackVolume_mL, rinsebackAdditionalTimerCtr + * @details Outputs: rinsebackTimerCtr, additionalRinsebackVolume_mL, + * totalAdditionalRinsebackVolume_mL, cumulativeRinsebackVolume_mL, + * rinsebackAdditionalTimerCtr * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackRunAdditionalState( void ) @@ -629,6 +655,22 @@ setRinsebackIsCompleted( TRUE ); } } + // if an air trap fill has started, set BP rate and VBV state accordingly + else if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // re-open VBV and restore BP rate after air trap fill + else if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // re-open VBV after fill + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // restore BP to rinseback blood flow rate + setBloodPumpTargetFlowRate( rinsebackRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + } return result; } Index: firmware/App/Modes/SalineBolus.c =================================================================== diff -u -r2f9807457197c347c20a24c64492edcf063f3daa -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/SalineBolus.c (.../SalineBolus.c) (revision 2f9807457197c347c20a24c64492edcf063f3daa) +++ firmware/App/Modes/SalineBolus.c (.../SalineBolus.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -15,7 +15,6 @@ * ***************************************************************************/ - #include "BloodFlow.h" #include "Dialysis.h" #include "ModeTreatment.h" @@ -44,6 +43,7 @@ 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 airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. 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). @@ -63,7 +63,7 @@ * @details Inputs: none * @details Outputs: currentSalineBolusState, salineBolusBroadcastTimerCtr, * totalSalineVolumeDelivered_mL, bolusSalineVolumeDelivered_mL, - * salineBolusStartRequested, salineBolusAbortRequested + * salineBolusStartRequested, salineBolusAbortRequested, airTrapFillInProgress * @return none *************************************************************************/ void initSalineBolus( void ) @@ -74,6 +74,7 @@ bolusSalineVolumeDelivered_mL = 0.0; salineBolusStartRequested = FALSE; salineBolusAbortRequested = FALSE; + airTrapFillInProgress = FALSE; bolusSalineLastVolumeTimeStamp = getMSTimerCount(); } @@ -82,14 +83,15 @@ * The resetSalineBolus function resets the saline bolus variables. * @details Inputs: currentSalineBolusState * @details Outputs: bolusSalineVolumeDelivered_mL, salineBolusStartRequested, - * salineBolusAbortRequested, currentSalineBolusState + * salineBolusAbortRequested, currentSalineBolusState, airTrapFillInProgress * @return none *************************************************************************/ void resetSalineBolus( void ) { bolusSalineVolumeDelivered_mL = 0.0; salineBolusStartRequested = FALSE; salineBolusAbortRequested = FALSE; + airTrapFillInProgress = FALSE; currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; resetUF(); } @@ -98,7 +100,7 @@ * @brief * The execSalineBolus function executes the saline bolus state machine. * @details Inputs: currentSalineBolusState - * @details Outputs: currentSalineBolusState + * @details Outputs: currentSalineBolusState, airTrapFillInProgress * @return Current saline bolus state machine. *************************************************************************/ SALINE_BOLUS_STATE_T execSalineBolus( void ) @@ -125,6 +127,8 @@ break; } + airTrapFillInProgress = isAirTrapFillInProgress(); + if ( priorSubState != currentSalineBolusState ) { setCurrent4thLevelState( (U32)currentSalineBolusState ); @@ -217,7 +221,7 @@ } else if ( ( TRUE == isAnyAlarmActive() ) && ( ( TRUE == isBloodRecircBlocked() ) || ( TRUE == isRinseBackBlocked() ) ) ) { - // Any alarm can be active but blood recirculation and dialysate recirculation cannot be blocked in their properties in order + // Any alarm can be active but blood recirculation and rinseback cannot be blocked in their properties in order // to do saline bolus rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_NOT_ALLOWED; } @@ -377,8 +381,11 @@ * @brief * The handleSalineBolusInProgressState function handles the in-progress state of the * saline bolus state machine. - * @details Inputs: none - * @details Outputs: + * @details Inputs: bolusSalineLastVolumeTimeStamp, bolusSalineVolumeDelivered_mL, + * totalSalineVolumeDelivered_mL, salineBolusAbortRequested + * @details Outputs: bolusSalineLastVolumeTimeStamp, bolusSalineVolumeDelivered_mL, + * totalSalineVolumeDelivered_mL, airTrapFillInProgress, salineBolusAbortRequested, + * salineBolusBroadcastTimerCtr * @return next saline bolus state *************************************************************************/ static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( void ) @@ -395,6 +402,23 @@ bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; + // if an air trap fill has started, set BP rate and VBV state accordingly + if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // if an air trap fill has completed, restore BP and VBV to saline bolus + else if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // Set to patient in case VBV is closed in treatment stop + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // Start blood pump at saline bolus rate + setBloodPumpTargetFlowRate( SALINE_BOLUS_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + } + // Check for empty saline bag per arterial line pressure if ( TRUE == isSalineBagEmpty() ) { Index: firmware/App/Modes/TreatmentEnd.c =================================================================== diff -u -redd44135869db32d23a0c809f6107b153c34d3bd -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision edd44135869db32d23a0c809f6107b153c34d3bd) +++ firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -20,6 +20,7 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "ModeTreatment.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -36,8 +37,6 @@ /// Interval at which treatment end progress is to be published to UI. #define TREATMENT_END_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) -/// Target flow rate for blood while waiting for user to initiate final rinseback. -#define TX_END_BP_FLOW_RATE_ML_MIN 150 /// Max time to wait for user to initiate final rinseback. static const U32 TX_END_TIMEOUT_MS = ( ( 10 * 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); @@ -54,6 +53,8 @@ static BOOL txEndRinsebackRequested; ///< Flag indicates user requesting final rinseback. static BOOL txEndDrainCmdSent; ///< Flag indicates DG Drain command has been sent. static U32 treatmentEndPublishTimerCtr; ///< Timer counter for determining interval for treatment end status to be published. +static BOOL airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. +static U32 txEndTargetBloodFlowMLPM; ///< Treatment end target blood flow in mL/min. // ********** private function prototypes ********** @@ -84,20 +85,31 @@ treatmentEndPublishTimerCtr = 0; txEndDrainCmdSent = FALSE; resetTreatmentEndFlags(); + airTrapFillInProgress = FALSE; // set to false initially - so keep after call to reset function + txEndTargetBloodFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); + + // The default for the blood flow is from the treatment parameters target flow but if the institutional + // record for the target flow is not 0 it takes the precedence + if ( getNVInstitutionalRecordTxEndBloodFlowMLPM() != 0 ) + { + txEndTargetBloodFlowMLPM = getNVInstitutionalRecordTxEndBloodFlowMLPM(); + } } /*********************************************************************//** * @brief * The resetTreatmentEndFlags function resets the treatment end request flags. * @details Inputs: none - * @details Outputs: Treatment end request flags reset to FALSE. + * @details Outputs: txEndAlarmRinsebackRequested, txEndAlarmEndTreatmentRequested, + * txEndRinsebackRequested, airTrapFillInProgress * @return none *************************************************************************/ static void resetTreatmentEndFlags( void ) { txEndAlarmRinsebackRequested = FALSE; txEndAlarmEndTreatmentRequested = FALSE; txEndRinsebackRequested = FALSE; + airTrapFillInProgress = isAirTrapFillInProgress(); } /*********************************************************************//** @@ -137,9 +149,8 @@ * @brief * The setupForTxEndWait4RinsebackState function sets actuators appropriately * for treatment end wait for rinseback state. - * @details Inputs: none - * @details Outputs: arterial and venous lines opened, blood pump started, - * and air trap leveling control is started. + * @details Inputs: txEndTargetBloodFlowMLPM + * @details Outputs: bloodSittingTimerCtr * @return none *************************************************************************/ static void setupForTxEndWait4RinsebackState( void ) @@ -149,7 +160,7 @@ setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Start blood pump at Tx End slow flow rate - setBloodPumpTargetFlowRate( TX_END_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setBloodPumpTargetFlowRate( txEndTargetBloodFlowMLPM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); bloodSittingTimerCtr = 0; // Continue air trap leveling control startAirTrapControl(); @@ -225,7 +236,8 @@ * The handleTxEndWait4RinsebackState function handles the treatment end * wait for rinseback state operations. * @details Inputs: txEndDrainCmdSent, txEndAlarmEndTreatmentRequested, - * txEndRinsebackRequested, txEndAlarmRinsebackRequested, txEndTimerCtr + * txEndRinsebackRequested, txEndAlarmRinsebackRequested, txEndTimerCtr, + * airTrapFillInProgress, txEndTargetBloodFlowMLPM * @details Outputs: txEndDrainCmdSent * @return next treatment end wait for rinseback state *************************************************************************/ @@ -271,6 +283,22 @@ { signalGoToRinseback(); } + // if an air trap fill has started, set BP rate and VBV state accordingly + else if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // re-open VBV and restore BP rate after air trap fill + else if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + // re-open VBV after fill + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // restore BP to Tx End blood flow rate + setBloodPumpTargetFlowRate( txEndTargetBloodFlowMLPM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + } return result; } Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r2f9807457197c347c20a24c64492edcf063f3daa -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 2f9807457197c347c20a24c64492edcf063f3daa) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -45,6 +45,8 @@ static TREATMENT_STOP_STATE_T currentTxStopState; ///< Current treatment stop state. static U32 bloodSittingTimerCtr; ///< Timer counter tracks time in this mode while blood is sitting. static U32 stopPublishTimerCtr; ///< Timer counter (in GP task intervals) counts time to next status broadcast. +static BOOL airTrapFillInProgress; ///< Flag indicates an air trap fill is in progress. + /// Interval (in task intervals) at which to publish treatment stop sub-mode data to CAN bus. static OVERRIDE_U32_T treatmentStopPublishInterval = { TREATMENT_STOP_DATA_PUBLISH_INTERVAL, TREATMENT_STOP_DATA_PUBLISH_INTERVAL, TREATMENT_STOP_DATA_PUBLISH_INTERVAL, 0 }; @@ -76,6 +78,7 @@ { currentTxStopState = TREATMENT_STOP_RECIRC_STATE; // Assume blood and dialysate will recirculate initially - will stop pump(s) as appropriate in state machine bloodSittingTimerCtr = 0; + airTrapFillInProgress = FALSE; stopPublishTimerCtr = TREATMENT_STOP_DATA_PUBLISH_INTERVAL; } @@ -112,7 +115,6 @@ setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setupForBloodRecirculationState(); - setupForDialysateRecirculationState(); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); @@ -182,9 +184,20 @@ doorClosedRequired( TRUE, TRUE ); // Open VBA and VBV valves to patient for blood recirculation setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - // Start blood pump at prescribed flow rate - setBloodPumpTargetFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), MOTOR_DIR_FORWARD, mode ); + if ( TRUE == isAirTrapFillInProgress() ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, mode ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + else + { + // Start blood pump at prescribed flow rate + setBloodPumpTargetFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), MOTOR_DIR_FORWARD, mode ); + // re-open VBV for blood recirculation + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + } // Start Heparin pump as appropriate startHeparinPump(); // Start air trap leveling control @@ -290,6 +303,8 @@ break; } + airTrapFillInProgress = isAirTrapFillInProgress(); + if ( priorSubState != currentTxStopState ) { setCurrentSubState( (U32)currentTxStopState ); @@ -307,6 +322,8 @@ * operations to set new states. * @details Inputs: state, flags * @details Outputs: flags handled + * @param state The Tx stop state that we're in now. An invalid state will + * force a re-evaluation of actuator settings based on current status. * @return next treatment re-circulation state *************************************************************************/ static TREATMENT_STOP_STATE_T handleTreatmentStopAlarmsAndSignals( TREATMENT_STOP_STATE_T state ) @@ -317,6 +334,21 @@ BOOL bldAlarmsStatus = ( ( TRUE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ) ) && ( FALSE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_DETECTED ) ? TRUE : FALSE ) ); + // if an air trap fill has started, set BP rate and VBV state accordingly + if ( ( airTrapFillInProgress != TRUE ) && ( TRUE == isAirTrapFillInProgress() ) ) + { + // set BP to air trap fill rate if air trap fill has been initiated + setBloodPumpTargetFlowRate( AIR_TRAP_FILL_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // close VBV for fill + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + } + // if an air trap fill has completed, force re-evaluation of state to restore BP and VBV appropriately + else if ( ( TRUE == airTrapFillInProgress ) && ( isAirTrapFillInProgress() != TRUE ) ) + { + state = NUM_OF_TREATMENT_STOP_STATES; // make it look like we're changing states to force re-evaluation + } + + // recovering from blood leak alarm? if ( TRUE == bldAlarmsStatus ) { if ( ( TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE != state ) && ( dialysateRecircBlocked != TRUE ) ) @@ -325,6 +357,7 @@ result = TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE; } } + // handling a saline bolus? else if ( ( TRUE == isSalineBolusStartRequested() ) || ( getSalineBolusState() != SALINE_BOLUS_STATE_IDLE ) ) { // No need for setup function since the saline bolus exec function starts from Idle and sets the actuators @@ -333,40 +366,39 @@ if ( SALINE_BOLUS_STATE_IDLE == (U32)getSalineBolusState() ) { // Send the first 4th level state here only when we are in idle - setCurrent4thLevelState( (U32)getSalineBolusState() ); + setCurrent4thLevelState( (U32)SALINE_BOLUS_STATE_IDLE ); } } - else + // Both unblocked and not in recirculate both state + else if ( ( TREATMENT_STOP_RECIRC_STATE != state ) && ( FALSE == dialysateRecircBlocked ) && ( FALSE == bloodRecircBlocked ) ) { - // Both unblocked and not in recirculate both state - if ( ( TREATMENT_STOP_RECIRC_STATE != state ) && ( FALSE == dialysateRecircBlocked ) && ( FALSE == bloodRecircBlocked ) ) - { - setupForBloodRecirculationState(); - setupForDialysateRecirculationState(); - result = TREATMENT_STOP_RECIRC_STATE; - } - // Both blocked and not in stopped state - else if ( ( TREATMENT_STOP_NO_RECIRC_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && ( TRUE == bloodRecircBlocked ) ) - { - setupForBloodRecirculationStopState(); - setupForDialysateRecirculationStopState(); - result = TREATMENT_STOP_NO_RECIRC_STATE; - } - // Dialysate recirculation blocked and not in blood recirc state - else if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && - ( FALSE == bloodRecircBlocked ) ) - { - setupForDialysateRecirculationStopState(); - result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; - } - // Blood recirculation blocked and not in dialysate recirc state - else if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) && ( TRUE == bloodRecircBlocked ) && - ( FALSE == dialysateRecircBlocked ) ) - { - setupForBloodRecirculationStopState(); - result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; - } + setupForBloodRecirculationState(); + setupForDialysateRecirculationState(); + result = TREATMENT_STOP_RECIRC_STATE; } + // Both blocked and not in stopped state + else if ( ( TREATMENT_STOP_NO_RECIRC_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && ( TRUE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_NO_RECIRC_STATE; + } + // Dialysate recirculation blocked and not in blood recirc state + else if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && + ( FALSE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationState(); + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; + } + // Blood recirculation blocked and not in dialysate recirc state + else if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) && ( TRUE == bloodRecircBlocked ) && + ( FALSE == dialysateRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + setupForDialysateRecirculationState(); + result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; + } return result; } Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -rfb714597ad515d3774d69b94808f065788504724 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision fb714597ad515d3774d69b94808f065788504724) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -113,7 +113,7 @@ SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, SW_FAULT_ID_HD_VALVES_INVALID_SELF_TEST_STATE, SW_FAULT_ID_HD_VALVES_INVALID_EXEC_STATE, - SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED, // 85 + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED1, // 85 SW_FAULT_ID_HD_VALVES_INVALID_AIR_TRAP_REQUEST, SW_FAULT_ID_HD_VALVES_INVALID_CONTROL_MODE_SELECTED, SW_FAULT_ID_HD_VAVLES_INVALID_POSITION_SELECTED, @@ -190,6 +190,11 @@ SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MIN_LIMIT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MAX_LIMIT, // 160 SW_FAULT_ID_MODE_TREATMENT_INVALID_BLOOD_LEAK_ZEROING_STATE, + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED2, + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED3, + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED4, + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED5, // 165 + SW_FAULT_ID_HD_VALVES_INVALID_VALVE_SELECTED6, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -raddd69fc864448c17a4a68b2bfa466af5483f987 -r8d3dbd25627fb7e993409eb47b2575e0430afddd --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision addd69fc864448c17a4a68b2bfa466af5483f987) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 8d3dbd25627fb7e993409eb47b2575e0430afddd) @@ -66,6 +66,7 @@ } BLOCKED_MSGS_DATA_T; #pragma pack(pop) +/// Institutional record payload structure typedef struct { U32 minBloodFlowMLPM; ///< Min blood flow in mL/min. @@ -96,8 +97,10 @@ U32 minRORejectionRatioPCT; ///< Min RO rejection ratio in percent. F32 minInletWaterCondAlarmLimitUSPCM; ///< Min inlet water conductivity alarm limit in uS/cm. S32 minVenPressWideLimitWindowMMHG; ///< Min venous pressure wide window limit in mmHg. + U32 txEndBloodFlowMLPM; ///< Treatment end blood flow in mL/min. } HD_INSTITUTIONAL_LOCAL_RECORD_T; +/// Local serial number typedef struct { U08 topLevelSN[ MAX_TOP_LEVEL_SN_CHARS ];