Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r660876bca7ae34f862ae9cc6feef9a30ec02fe94 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 660876bca7ae34f862ae9cc6feef9a30ec02fe94) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -542,6 +542,7 @@ BLOOD_LEAK_STATE_T state = BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE; BOOL areCommandsReady = TRUE; + // Check to see if all commands in sequence have been responded to for ( i = 0; i < NUM_OF_EMB_CMDS; i++ ) { switch( i ) @@ -556,6 +557,7 @@ } } + // When all commands in sequence have been responded to, determine whether anything went wrong if ( TRUE == areCommandsReady ) { // Enqueue the zero and self test sequence (Z->G->Z->Q->T) @@ -585,6 +587,7 @@ } } + // Pass self-test if entire sequence was successful if ( FALSE == hasCmdSqncFailed ) { // Done with zero sequence, transition to other states @@ -593,6 +596,7 @@ bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; state = BLOOD_LEAK_NORMAL_STATE; } + // If not successful, retry if we've not run out else if ( bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { if ( TRUE == zeroBloodLeak() ) @@ -603,6 +607,7 @@ bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount++; } } + // If out of retries, fault else { #ifndef _RELEASE_ Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -rbf05e93a69198e2bf5870569682dd3aed036be64 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision bf05e93a69198e2bf5870569682dd3aed036be64) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -464,16 +464,17 @@ { TREATMENT_STATE_T txState = getTreatmentState(); - // Check arterial pressure is in range + // Check arterial pressure is in absolute max range if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, ( artPres > ARTERIAL_PRESSURE_MAX_MMHG || artPres < ARTERIAL_PRESSURE_MIN_MMHG ) ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, artPres ); } - // Check arterial pressure during treatment mode + // Check arterial pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); @@ -530,15 +531,16 @@ { TREATMENT_STATE_T txState = getTreatmentState(); - // Check venous pressure is in range + // Check venous pressure is in absolute max range if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, ( venPres > VENOUS_PRESSURE_MAX_MMHG || venPres < VENOUS_PRESSURE_MIN_MMHG ) ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); } - // Check venous pressure during treatment mode + // Check venous pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -ra57994f752662abc0aaa8c2cf5c3af47ec2c5a20 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision a57994f752662abc0aaa8c2cf5c3af47ec2c5a20) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -613,7 +613,7 @@ patientConnectionConfirm = FALSE; treatmentStartRequested = FALSE; - doorClosedRequired( FALSE, FALSE ); + doorClosedRequired( TRUE, TRUE ); for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) { Index: firmware/App/Modes/PreTreatmentRecirc.c =================================================================== diff -u -r0a4dcd288d4347b85baaa0b07da568b6add5eac7 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision 0a4dcd288d4347b85baaa0b07da568b6add5eac7) +++ firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -22,6 +22,7 @@ #include "DGInterface.h" #include "PreTreatmentRecirc.h" #include "Switches.h" +#include "Timers.h" #include "Valves.h" /** @@ -32,13 +33,18 @@ // ********** private definitions ********** #define BLOOD_PUMP_RECIRC_FLOW_RATE 100 ///< Blood pump flow rate during recirculation in mL/min. -/// TODO: Restore to 100 when DPi flow control is fixed. +// TODO: Restore to 100 when DPi flow control is fixed. #define DIALYSATE_PUMP_RECIRC_FLOW_RATE 250 ///< Dialysate pump flow rate during recirculation in mL/min. +#define WARNING_MEDIUM_PRIME_COMPLETED_TIME_MS ( 90 * 60 * MS_PER_SECOND ) ///< Pre-Treatment recirc time before medium priority warning in min. +#define WARNING_HIGH_PRIME_COMPLETED_TIME_MS ( 120 * 60 * MS_PER_SECOND ) ///< Pre-Treatment recirc time before high priority alarm in min. // ********** private data ********** static HD_PRE_TREATMENT_RECIRC_STATE_T currentPreTreatmentRecircState; ///< Current state of the pre-treatment recirculate state machine. static BOOL recircResumeRequested; ///< Flag indicates alarm requesting to resume pre-treatment recirculate. +static U32 preTxRecircStartTime; ///< Time pre-treatment re-circulate state started. +static BOOL recircTOWarningGiven; ///< Flag indicates 90 minute warning given. +static BOOL recircTOAlarmGiven; ///< Flag indicates 2 hour alarm triggered. // ********** private function prototypes ********** @@ -58,6 +64,9 @@ void initPreTreatmentRecirc( void ) { currentPreTreatmentRecircState = PRE_TREATMENT_RECIRC_STATE; + preTxRecircStartTime = getMSTimerCount(); + recircTOWarningGiven = FALSE; + recircTOAlarmGiven = FALSE; resetPreTreatmentRecircFlags(); } @@ -85,6 +94,14 @@ *************************************************************************/ void execPreTreatmentRecirc( void ) { + // Alarm if 2 hours recirculating + if ( ( recircTOAlarmGiven != TRUE ) && ( TRUE == didTimeout( preTxRecircStartTime, WARNING_HIGH_PRIME_COMPLETED_TIME_MS ) ) ) + { + recircTOAlarmGiven = TRUE; + clearAlarm( ALARM_ID_PRIME_COMPLETED_MEDIUM ); + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_HIGH ); + } + // execute pre-treatment recirculate state machine switch ( currentPreTreatmentRecircState ) { @@ -187,6 +204,14 @@ { HD_PRE_TREATMENT_RECIRC_STATE_T state = PRE_TREATMENT_RECIRC_STATE; + // Warn user if 90 minutes recirculating + if ( ( recircTOWarningGiven != TRUE ) && ( TRUE == didTimeout( preTxRecircStartTime, WARNING_MEDIUM_PRIME_COMPLETED_TIME_MS ) ) ) + { + recircTOWarningGiven = TRUE; + clearAlarm( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_MEDIUM ); + } + if ( TRUE == doesAlarmStatusIndicateStop() ) { signalDialOutPumpHardStop(); Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r5113415a09ac8244a8c9504e0ca1a29e0215c3bb -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 5113415a09ac8244a8c9504e0ca1a29e0215c3bb) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -564,7 +564,7 @@ case PRIME_BUBBLE_CLEAR_PRESSURE_STATE: case PRIME_BUBBLE_CLEAR_VENT_STATE: if ( ( getMeasuredVenousPressure() > VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ) || - ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_MAX_TIME_MS ) ) ) + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_MAX_TIME_MS ) ) ) { // Pressure max reached. or timeout, release pressure setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); @@ -573,7 +573,7 @@ primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_VENT_STATE; } else if ( ( TRUE == bubble_clear_ended ) && - ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) { setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValveAirTrap( STATE_OPEN ); @@ -686,11 +686,6 @@ if ( TRUE == getReservoirFillStatus( DG_RESERVOIR_1 ) ) { - DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; - - rsrvrCmd.reservoirID = (U32)DG_RESERVOIR_1; - rsrvrCmd.useLastTrimmerHeaterDC = FALSE; - if ( TRUE == hasDGCompletedReservoirSwitch() ) { U32 dialyzerDialysateVolume = getDialyzerDialysateVolume(); @@ -748,9 +743,9 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_DIALYSATE_DIALYZER_STATE; + // Draw dialysate from reservoir for fixed time (calculated in prior state), then start looking for reservoir volume to steady state (indicating we have primed the line) if ( TRUE == didTimeout( primeDialysateDialyzerStartTime, primeDialysateDialyzerTimeLimit ) ) { - // check for volume steady state every second after the DVi and DVo pumps have been on for primeDialysateDialyzerTimeLimit seconds if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); @@ -837,6 +832,7 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_SALINE_DIALYZER_STATE; + // Wait fixed time (based on calc done in prior state) and then move on to 2nd transfer check if ( TRUE == didTimeout( primeSalineDialyzerStartTime, primeSalineDialyzerTimeLimit ) ) { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; @@ -983,8 +979,7 @@ { state = HD_PRIME_COMPLETE; } - - if ( TRUE == doesAlarmStatusIndicateStop() ) + else if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForPrimePause(); state = HD_PRIME_PAUSE; @@ -1011,6 +1006,10 @@ switch ( previousPrimeState ) { + case HD_PRIME_WAIT_FOR_USER_START_STATE: + state = HD_PRIME_WAIT_FOR_USER_START_STATE; + break; + case HD_PRIME_SALINE_SETUP_STATE: case HD_PRIME_SALINE_PURGE_AIR_STATE: case HD_PRIME_SALINE_CIRC_BLOOD_CIRCUIT_STATE: Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r03bd494bf7b7c96f79cf9b8bd0f99432982b9571 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 03bd494bf7b7c96f79cf9b8bd0f99432982b9571) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -115,7 +115,7 @@ static U32 displacementStartTime; ///< Dialysate displacement starting time. static F32 fmdIntegratedVolume; ///< FMD integrated volume over displacement time. static F32 reservoirVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Hold the current volume of all reservoirs. -static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been send to DG. +static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been sent to DG. static U32 selfTestStartTime; ///< Starting time of self-test (in ms). static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). @@ -603,11 +603,11 @@ currentWetSelfTestsState = handleWetSelfTestStartState(); break; - case WET_SELF_TESTS_SETUP_STATE: + case WET_SELF_TESTS_BUBBLE_CHECK_SETUP_STATE: currentWetSelfTestsState = handleWetSelfTestSetupState(); break; - case WET_SELF_TESTS_BUBBLES_STATE: + case WET_SELF_TESTS_BUBBLE_CHECK_STATE: currentWetSelfTestsState = handleWetSelfTestBubblesState(); break; @@ -1480,14 +1480,14 @@ selfTestsResumeRequested = FALSE; doorClosedRequired( TRUE, TRUE ); #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) != SW_CONFIG_ENABLE_VALUE ) + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) { - state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; } else #endif { - state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } @@ -1498,21 +1498,19 @@ * @brief * The handleWetSelfTestStartState function handles setup state for wet * self-tests sub-mode. - * @details Inputs: reservoir one weight - * @details Outputs: setup valves and dialysate inlet pump + * @details Inputs: heparin bolus volume setting + * @details Outputs: setup valves * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SETUP_STATE; - F32 resOneWeight = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_SETUP_STATE; F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); - isValvesSettingSent = TRUE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - fmdIntegratedVolume = 0.0F; + // if user set a Heparin bolus volume, request bolus to be initiated now if ( ( bolusVol > 0.0F ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) { startHeparinBolus(); // moved here from startHeparinPump() in Dialysis.c @@ -1529,15 +1527,15 @@ /*********************************************************************//** * @brief - * The handleWetSelfTestSetupState function setup reservoir one before - * the start of wet self-tests. - * @details Inputs: dialysate inlet flow rate - * @details Outputs: stop dialysate inlet pump + * The handleWetSelfTestSetupState function setup for bubble self-test + * check. + * @details Inputs: none + * @details Outputs: bubble detector self-test requested * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLES_STATE; + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_STATE; selfTestBubble( ADV ); @@ -1560,7 +1558,7 @@ *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLES_STATE; + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_CHECK_STATE; if ( SELF_TEST_STATUS_PASSED == getBubbleSelfTestStatus( ADV ) ) { @@ -1675,9 +1673,9 @@ if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) { - // Re-send command if DG rejects isValvesSettingSent = FALSE; + // Re-send command if DG rejects if ( DG_CMD_REQUEST_REJECT_REASON_NONE == cmdResp.rejectCode ) { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); @@ -1707,15 +1705,7 @@ { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; - if ( ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) && ( settleStartTime != 0 ) ) - { - reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeight( DG_RESERVOIR_1 ); - reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeight( DG_RESERVOIR_2 ); - displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0.0F; - settleStartTime = 0; - } - + // Once we've settled (5 sec), integrate flow to volume over duration of fluid transfer if ( 0 == settleStartTime ) { // This is not a volume for now and it is a flow rate. @@ -1730,6 +1720,16 @@ } } + // Wait for settle time, then initiate transfer test + if ( ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) && ( settleStartTime != 0 ) ) + { + reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeight( DG_RESERVOIR_1 ); + reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeight( DG_RESERVOIR_2 ); + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0.0F; + settleStartTime = 0; + } + if ( TRUE == doesAlarmStatusIndicateStop() ) { state = WET_SELF_TESTS_STOPPED_STATE; @@ -1818,9 +1818,9 @@ if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) { - // Re-send command if DG rejects isValvesSettingSent = FALSE; + // Re-send command if DG rejects if ( DG_CMD_REQUEST_REJECT_REASON_NONE == cmdResp.rejectCode ) { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); @@ -1954,7 +1954,7 @@ { doorClosedRequired( TRUE, TRUE ); selfTestsResumeRequested = FALSE; - state = WET_SELF_TESTS_START_STATE; + state = WET_SELF_TESTS_START_STATE; // TODO - should start state make sure there is sufficient/appropriate res volumes to restart wet self-tests? and if not, should it signal res mgmt to drain and fill R1 and R2 before resuming wet self-tests? } return state; Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r81c902fb595b9fcde229f8898d14e43312969f26 -r5d9c5362b537331248dc592e05b6b016267eb6d3 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 81c902fb595b9fcde229f8898d14e43312969f26) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) @@ -408,6 +408,7 @@ bloodSittingTimerCtr = 0; } } + /*********************************************************************//** * @brief * The getCurrentTreatmentStopState function returns the current state of the