Index: firmware/App/Services/StateServices/Prime.c =================================================================== diff -u -ree84e20f729b0aace2b1728c16de9a89e06eee38 -r25aeff9e9994d2e7aab3b4e6171c56fdac6a01fe --- firmware/App/Services/StateServices/Prime.c (.../Prime.c) (revision ee84e20f729b0aace2b1728c16de9a89e06eee38) +++ firmware/App/Services/StateServices/Prime.c (.../Prime.c) (revision 25aeff9e9994d2e7aab3b4e6171c56fdac6a01fe) @@ -22,6 +22,7 @@ #include "BloodFlow.h" #include "DDInterface.h" #include "LevelSensors.h" +#include "MessagePayloads.h" #include "Pressures.h" #include "Prime.h" #include "Switches.h" @@ -102,7 +103,7 @@ #define CARTRIDGE_VOLUME 123.8F /// Maximum ultrafiltration pump (D76) speed used during priming fluid discard and reverse prime. -#define MAX_UF_RATE 200U +#define MAX_UF_RATE 150U /// Duration of each forward pass in the blood pump reversal sequence. #define BC2_FWD_RECIRC_INTERVAL ( 25U * MS_PER_SECOND ) @@ -111,7 +112,7 @@ #define BC2_PINCH_CYCLE_INTERVAL ( 15U * MS_PER_SECOND ) /// Duration of the reverse pass in the blood pump reversal sequence. -#define BC2_REV_RECIRC_INTERVAL ( 10U * MS_PER_SECOND ) +#define BC2_REV_RECIRC_INTERVAL ( 20U * MS_PER_SECOND ) /// Blood pump stop duration between forward and reverse passes. #define BC2_PAUSE_INTERVAL ( 1U * MS_PER_SECOND ) @@ -122,8 +123,19 @@ /// Venous pressure limit below which the venous pinch valve reopens during forward pass pinch cycling. #define BC2_STABLE_VEN_PRES_LIMIT_MMHG 100U +/// Blood flow rate to replunish while discarding priming fluid +#define REPLUNISH_BLOOD_FLOW_RATE 240U + +/// Estimate for Blood Circuit Prime sequence (states 0 to 7) +#define BC_PRIME_ESTIMATE_INTERVAL ( 3U * 60U * MS_PER_SECOND ) + +/// Estimate for BC2 prime sequence (states 11-14) -- 25+1+20+1+25s. +#define BC2_PRIME_ESTIMATE_INTERVAL ( 72U * MS_PER_SECOND ) + // ********** private data ********** +static OVERRIDE_U32_T primePublishInterval; + static TD_PRIME_STATE_T currentPrimeState; ///< Current state of the Prime state machine. static TD_PRIME_STATE_T prevPrimeState; ///< Previous state of the Prime state machine. static TD_PRIME_STATE_T nextStateAfterAirTrapLower; ///< Next state to transition to once air trap lowers. @@ -136,18 +148,22 @@ static U32 bcRevPrimePauseTimerCtr; ///< Timer counter for bc initial rev prime pause. static U32 bcRevPrimeRetryCtr; ///< Counter for bc rev prime retry. static U32 pinchStartTime; ///< Timer counter for pinch valve cycle. +static U32 dcInitialPrimeTimerCtr; ///< Timer counter for dc initial prime. static U32 dialyzerDialysateVolume; ///< Selected dialyzer jacket (dialysate) volume (mL). static U32 dilayzerBloodVolume; ///< Selected dialyzer core (blood) volume (mL). -static U32 dcDepressurizeElapsedMs; ///< Timer counter for dc depressurize venous pressure stabilization. static U32 dcInitialPrimeInterval; ///< Calculated dc initial dialyzer prime duration (ms). static U32 dcDiscardDuration; ///< Calculated priming fluid discard duration (ms). static U32 dcReversePrimeDuration; ///< Calculated dialyzer reverse prime duration (ms). static U32 dcDiscardAndRevPrimeInterval; ///< Greater of dcDiscardDuration and dcReversePrimeDuration (ms). static BOOL revRecircVisited; ///< Flag indicates bc2 reverse recirc pass has been completed. static BOOL primeResumeRequested; ///< Flag indicates user requested resume from pause. +static U32 seqStartTime; ///< Start time (ms) of the currently active progress sequence. +static U32 seqEstimateTime; ///< Estimated budget (ms) for the currently active progress sequence. +static U32 primeTimeCreditMs; ///< Accumulated time (ms) saved from sequences that finished early. // ********** private function prototypes ********** +static void setPrimeStateTransition( TD_PRIME_STATE_T state ); static TD_PRIME_STATE_T handlePrimeBCInitialReverseState( void ); static TD_PRIME_STATE_T handlePrimeBCWaitForAirTrapLowerState( void ); static TD_PRIME_STATE_T handlePrimeBCInitialDialyzerState( void ); @@ -157,7 +173,6 @@ static TD_PRIME_STATE_T handlePrimeBCClearState3( void ); static TD_PRIME_STATE_T handlePrimeWaitForDialysateReadyState( void ); static TD_PRIME_STATE_T handlePrimeDCInitialDialyzerState( void ); -static TD_PRIME_STATE_T handlePrimeDCDepressurizeState( void ); static TD_PRIME_STATE_T handleWaitForAirTrapFillState( void ); static TD_PRIME_STATE_T handleBC2ForwardRecircState( void ); static TD_PRIME_STATE_T handleBC2PauseToRotateOppDirState( void ); @@ -166,7 +181,9 @@ static TD_PRIME_STATE_T handlePrimePauseState( void ); static void resetPrimeFlags( void ); +static void startProgressSequence( U32 estimateMs ); static void publishPrimeData( void ); +static void setBloodAndDialysateVolume( void ); /*********************************************************************//** * @brief @@ -178,24 +195,34 @@ *************************************************************************/ void initPrime( void ) { - currentPrimeState = PRIME_START_STATE; - prevPrimeState = PRIME_START_STATE; - nextStateAfterAirTrapLower = PRIME_BC_INITIAL_DIALYZER_STATE; - primeStartTime = 0; - primePauseStartTime = 0; - primePublishTimerCtr = PRIME_DATA_PUB_INTERVAL - 8; - stateEntryTimerCtr = 0; - bcRevPrimePauseTimerCtr = 0; - bcRevPrimeRetryCtr = 0; - dcDepressurizeElapsedMs = 0; - revRecircVisited = FALSE; - primeResumeRequested = FALSE; - dialyzerDialysateVolume = getDialyzerDialysateVolume( getTreatmentParameterF32( TREATMENT_PARAM_DIALYZER_TYPE ) ); - dilayzerBloodVolume = getDialyzerBloodVolume( getTreatmentParameterF32( TREATMENT_PARAM_DIALYZER_TYPE ) ); - dcInitialPrimeInterval = (U32)( ( ( dialyzerDialysateVolume * 60.0F ) / (F32)TARGET_DIALYSATE_FLOW_RATE + 30.0F ) * (F32)MS_PER_SECOND ); - dcDiscardDuration = (U32)( ( ( dilayzerBloodVolume + CARTRIDGE_VOLUME ) * 1.5F ) / MAX_UF_RATE ) * (F32)( SEC_PER_MIN * MS_PER_SECOND ) ; - dcReversePrimeDuration = (U32)( ( ( dialyzerDialysateVolume * 0.5F * (F32)SEC_PER_MIN ) / (F32)MAX_UF_RATE ) + 30.0F ) * (F32)MS_PER_SECOND; - dcDiscardAndRevPrimeInterval = ( dcDiscardDuration > dcReversePrimeDuration ) ? dcDiscardDuration : dcReversePrimeDuration; + currentPrimeState = PRIME_START_STATE; + prevPrimeState = PRIME_START_STATE; + nextStateAfterAirTrapLower = PRIME_BC_INITIAL_DIALYZER_STATE; + primeStartTime = 0; + primePauseStartTime = 0; + primePublishTimerCtr = PRIME_DATA_PUB_INTERVAL - 8; + stateEntryTimerCtr = 0; + bcRevPrimePauseTimerCtr = 0; + bcRevPrimeRetryCtr = 0; + revRecircVisited = FALSE; + primeResumeRequested = FALSE; + dcInitialPrimeTimerCtr = 0; + dialyzerDialysateVolume = 0; + dilayzerBloodVolume = 0; + dcInitialPrimeInterval = 0; + dcDiscardDuration = 0; + dcReversePrimeDuration = 0; + dcDiscardAndRevPrimeInterval = 0; + seqStartTime = 0; + seqEstimateTime = 0; + primeTimeCreditMs = 0; + dilayzerBloodVolume = 142; + dialyzerDialysateVolume = 348; + + primePublishInterval.data = PRIME_DATA_PUB_INTERVAL; + primePublishInterval.ovData = PRIME_DATA_PUB_INTERVAL; + primePublishInterval.ovInitData = 0; + primePublishInterval.override = OVERRIDE_RESET; } /*********************************************************************//** @@ -204,6 +231,7 @@ * (valves, blood pump, air pump/trap) required upon entry into the given * Prime state. Called both during normal forward state progression and * during pause/resume to deterministically re-establish actuator state. + * @details \b Alarms: ALARM_ID_TD_SOFTWARE_FAULT if exec state is invalid * @details \b Inputs: nextStateAfterAirTrapLower, revRecircVisited * @details \b Outputs: stateEntryTimerCtr, pinchStartTime, actuator commands * @param state target Prime state being transitioned into @@ -214,6 +242,7 @@ switch ( state ) { case PRIME_BC_INITIAL_REVERSE_STATE: + startProgressSequence( BC_PRIME_ESTIMATE_INTERVAL ); signalBloodPumpHardStop(); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); @@ -225,54 +254,56 @@ break; case PRIME_BC_AIR_TRAP_LOWER_STATE: - if ( PRIME_BC_INITIAL_DIALYZER_STATE == nextStateAfterAirTrapLower ) - { - // Leaving Venous Line state -- stop the H12/H20 reverse-prime drive. - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - } - else - { - // Leaving Dialyzer Purge state -- stop the forward BP purge. - signalBloodPumpHardStop(); - setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); - } + signalBloodPumpHardStop(); + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_DUTY_CYCLE_PRIME_PCT ); break; case PRIME_BC_INITIAL_DIALYZER_STATE: + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); - setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); break; case PRIME_BC_FILL_STATE: + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); - setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); break; case PRIME_BC_CLEAR_STATE1: signalBloodPumpHardStop(); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); pinchStartTime = getMSTimerCount(); break; case PRIME_BC_CLEAR_STATE2: setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); break; case PRIME_BC_CLEAR_STATE3: setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); pinchStartTime = getMSTimerCount(); break; @@ -284,25 +315,25 @@ break; case PRIME_DC_INITIAL_DIALYSATE_STATE: + dcInitialPrimeInterval = (U32)( ( ( dialyzerDialysateVolume * 60.0F ) / (F32)TARGET_DIALYSATE_FLOW_RATE + 30.0F ) * (F32)MS_PER_SECOND ); + startProgressSequence( dcInitialPrimeInterval ); cmdBypassDialyzer( FALSE ); stateEntryTimerCtr = getMSTimerCount(); - dcDepressurizeElapsedMs = getMSTimerCount(); break; - case PRIME_DC_DEPRESSURIZE_STATE: - // TODO: Remove if not required in future. - //cmdDDChamberHValveOpen( TRUE ); - break; - case PRIME_WAIT_FOR_AIR_TRAP_FILL_STATE: cmdBypassDialyzer( TRUE ); + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); startAirTrapControl(); break; case PRIME_BC2_FORWARD_RECIRC_STATE: - setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); break; @@ -313,18 +344,24 @@ case PRIME_BC2_REVERSE_RECIRC_STATE: revRecircVisited = TRUE; + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, MOTOR_DIR_REVERSE, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); break; case PRIME_DC_DISCARD_AND_REVERSE_PRIME_STATE: + dcDiscardDuration = (U32)( ( ( ( dilayzerBloodVolume + CARTRIDGE_VOLUME ) * 1.5F ) / MAX_UF_RATE ) * (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); + dcReversePrimeDuration = (U32)( ( ( dialyzerDialysateVolume * 0.5F * (F32)SEC_PER_MIN ) / (F32)MAX_UF_RATE ) + 30.0F ) * (F32)MS_PER_SECOND; + dcDiscardAndRevPrimeInterval = ( dcDiscardDuration > dcReversePrimeDuration ) ? dcDiscardDuration : dcReversePrimeDuration; + startProgressSequence( dcDiscardAndRevPrimeInterval ); signalBloodPumpHardStop(); cmdDDprimeFluidDiscard( TRUE ); - //cmdChangeQuf( MAX_UF_RATE ); setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( REPLUNISH_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, + PUMP_CONTROL_MODE_OPEN_LOOP ); stateEntryTimerCtr = getMSTimerCount(); break; @@ -350,14 +387,17 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TX_PRIME_INVALID_STATE, (U32)state ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, + SW_FAULT_ID_MODE_PRE_TX_PRIME_INVALID_STATE, + (U32)state ); break; } } /*********************************************************************//** * @brief * The execPrime function executes the prime service state machine. + * @details \b Alarms: ALARM_ID_TD_SOFTWARE_FAULT if exec state is invalid * @details \b Inputs: currentPrimeState * @details \b Outputs: currentPrimeState * @return none @@ -377,6 +417,7 @@ switch ( currentPrimeState ) { case PRIME_START_STATE: + primeStartTime = getMSTimerCount(); setPrimeStateTransition ( PRIME_BC_INITIAL_REVERSE_STATE ); currentPrimeState = PRIME_BC_INITIAL_REVERSE_STATE; break; @@ -417,10 +458,6 @@ currentPrimeState = handlePrimeDCInitialDialyzerState(); break; - case PRIME_DC_DEPRESSURIZE_STATE: - currentPrimeState = handlePrimeDCDepressurizeState(); - break; - case PRIME_WAIT_FOR_AIR_TRAP_FILL_STATE: currentPrimeState = handleWaitForAirTrapFillState(); break; @@ -450,7 +487,9 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TX_PRIME_INVALID_STATE, currentPrimeState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, + SW_FAULT_ID_MODE_PRE_TX_PRIME_INVALID_STATE, + currentPrimeState ); break; } @@ -462,6 +501,8 @@ SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorPrimeState, currentPrimeState ); } + setBloodAndDialysateVolume(); + // Broadcast priming data publishPrimeData(); } @@ -538,7 +579,8 @@ // Max retries exceeded? if ( bcRevPrimeRetryCtr >= BC_INITIAL_REV_MAX_RETRIES ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_INITIAL_BC_REV_PRIME_LIMIT_REACHED, bcRevPrimeRetryCtr ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_INITIAL_BC_REV_PRIME_LIMIT_REACHED, + bcRevPrimeRetryCtr ); } } else @@ -563,7 +605,8 @@ // Max time exceeded for this state? if ( TRUE == didTimeout( stateEntryTimerCtr, BC_INITIAL_REV_PRIME_INTERVAL ) ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_INITIAL_BC_REV_PRIME_TIMEOUT, BC_INITIAL_REV_PRIME_INTERVAL ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_INITIAL_BC_REV_PRIME_TIMEOUT, + BC_INITIAL_REV_PRIME_INTERVAL ); } return state; @@ -655,48 +698,57 @@ { TD_PRIME_STATE_T state = PRIME_BC_CLEAR_STATE1; - // Max time for this state - 20 secs - if ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) + //Check if airtrap is filling + if ( ( TRUE == isAirTrapControlling() ) && + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) { - setPrimeStateTransition ( PRIME_BC_CLEAR_STATE2 ); - state = PRIME_BC_CLEAR_STATE2; + endAirTrapControl(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stateEntryTimerCtr = getMSTimerCount(); + pinchStartTime = getMSTimerCount(); } + // Air trap refill + else if ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + startAirTrapControl(); + stateEntryTimerCtr = getMSTimerCount(); + pinchStartTime = getMSTimerCount(); + } // Check pressure on each pinch else if ( VALVE_POSITION_C_CLOSE == getValvePosition( H1_VALV ) ) { - if ( getFilteredVenousPressure() >= TARGET_VEN_PRES_LIMIT_MMHG ) + if ( ( getFilteredVenousPressure() >= TARGET_VEN_PRES_LIMIT_MMHG ) || + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H16_LEVL ) ) ) { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); pinchStartTime = getMSTimerCount(); } } - //Check if airtrap is filling - else if ( TRUE == isAirTrapControlling() ) - { - if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) - { - endAirTrapControl(); - stateEntryTimerCtr = getMSTimerCount(); - pinchStartTime = getMSTimerCount(); - } - } - // Air trap refill - else if ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) - { - startAirTrapControl(); - } // 5 secs pinch time check else if ( TRUE == didTimeout( pinchStartTime, PINCH_INTERVAL_MS ) ) { setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); - setBloodPumpTargetFlowRate( INITIAL_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } else { // No action required, continue for 5 secs } + // Max time for this state - 20 secs + if ( ( FALSE == isAirTrapControlling() ) && + ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) ) + { + setPrimeStateTransition ( PRIME_BC_CLEAR_STATE2 ); + state = PRIME_BC_CLEAR_STATE2; + } + return state; } @@ -713,32 +765,38 @@ { TD_PRIME_STATE_T state = PRIME_BC_CLEAR_STATE2; - // Max time for this state - 20 secs - if ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) - { - setPrimeStateTransition( PRIME_BC_CLEAR_STATE3 ); - state = PRIME_BC_CLEAR_STATE3; - } //Check if airtrap is filling - else if ( TRUE == isAirTrapControlling() ) + if ( ( TRUE == isAirTrapControlling() ) && + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) { - if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) - { - endAirTrapControl(); - stateEntryTimerCtr = getMSTimerCount(); - pinchStartTime = getMSTimerCount(); - } + endAirTrapControl(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setBloodPumpTargetFlowRate( MAX_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stateEntryTimerCtr = getMSTimerCount(); } // Air trap refill else if ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) { + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); startAirTrapControl(); + stateEntryTimerCtr = getMSTimerCount(); } else { // No action required, continue. } + // Max time for this state - 20 secs + if ( ( FALSE == isAirTrapControlling() ) && + ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) ) + { + setPrimeStateTransition( PRIME_BC_CLEAR_STATE3 ); + state = PRIME_BC_CLEAR_STATE3; + } + return state; } @@ -755,48 +813,59 @@ { TD_PRIME_STATE_T state = PRIME_BC_CLEAR_STATE3; - // Max time for this state - 20 secs - if ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) + //Check if airtrap is filling + if ( ( TRUE == isAirTrapControlling() ) && + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) { - setPrimeStateTransition( PRIME_WAIT_FOR_DIALYSATE_READY_STATE ); - state = PRIME_WAIT_FOR_DIALYSATE_READY_STATE; + endAirTrapControl(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stateEntryTimerCtr = getMSTimerCount(); + pinchStartTime = getMSTimerCount(); } + // Air trap refill + else if ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setBloodPumpTargetFlowRate( RECIRC_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + startAirTrapControl(); + stateEntryTimerCtr = getMSTimerCount(); + pinchStartTime = getMSTimerCount(); + } // Check pressure on each pinch else if ( VALVE_POSITION_C_CLOSE == getValvePosition( H1_VALV ) ) { - if ( getFilteredVenousPressure() >= TARGET_VEN_PRES_LIMIT_MMHG ) + if ( ( getFilteredVenousPressure() >= TARGET_VEN_PRES_LIMIT_MMHG ) || + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H16_LEVL ) ) ) { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); - setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); pinchStartTime = getMSTimerCount(); } } - //Check if airtrap is filling - else if ( TRUE == isAirTrapControlling() ) - { - if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) - { - endAirTrapControl(); - stateEntryTimerCtr = getMSTimerCount(); - pinchStartTime = getMSTimerCount(); - } - } - // Air trap refill - else if ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) - { - startAirTrapControl(); - } // 5 secs pinch time check else if ( TRUE == didTimeout( pinchStartTime, PINCH_INTERVAL_MS ) ) { setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); - setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( SALINE_PURGE_SET_BLOOD_FLOW_RATE, + MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } else { // No action required, continue for 5 secs } + // Max time for this state - 20 secs + if ( ( FALSE == isAirTrapControlling() ) && + ( TRUE == didTimeout( stateEntryTimerCtr, SLOW_PURGE_INTERVAL ) ) ) + { + setPrimeStateTransition( PRIME_WAIT_FOR_DIALYSATE_READY_STATE ); + state = PRIME_WAIT_FOR_DIALYSATE_READY_STATE; + } + return state; } @@ -827,7 +896,8 @@ * The handlePrimeDCInitialDialyzerState function handles dialysate circuit * initial dialyzer state of prime prime service. Passes dialysate through * dialyzer. - * @details \b Inputs: stateEntryTimerCtr, dcInitialPrimeInterval + * @details \b Inputs: stateEntryTimerCtr, dcInitialPrimeInterval, + * dcInitialPrimeActiveElapsedMs * @details \b Outputs: none * @return next Prime state *************************************************************************/ @@ -836,73 +906,20 @@ TD_PRIME_STATE_T state = PRIME_DC_INITIAL_DIALYSATE_STATE; F32 venPres = getFilteredVenousPressure(); - if ( fabs( venPres ) > DC_PRIME_VEN_PRES_LIMIT_MMHG ) + if ( DD_GEND_DIALYSATE_DELIVERY_STATE == getCurrentGenDState() ) { - setPrimeStateTransition( PRIME_DC_DEPRESSURIZE_STATE ); - state = PRIME_DC_DEPRESSURIZE_STATE; - } - else if ( DD_GEND_DIALYSATE_DELIVERY_STATE == getCurrentGenDState() ) - { - if ( TRUE == didTimeout( stateEntryTimerCtr, dcInitialPrimeInterval ) ) + if ( ++dcInitialPrimeTimerCtr >= dcInitialPrimeInterval ) { - cmdBypassDialyzer( TRUE ); - startAirTrapControl(); + setPrimeStateTransition( PRIME_WAIT_FOR_AIR_TRAP_FILL_STATE ); state = PRIME_WAIT_FOR_AIR_TRAP_FILL_STATE; } } - else - { - // No action required. - } return state; } /*********************************************************************//** * @brief - * The handlePrimeDCDepressurizeState function handles dialysate circuit - * depressurize state of prime service. Waits for pressure to return - * within the resume limit, alarming if stabilization does not occur - * within 5s. - * @details \b Alarm: ALARM_ID_TD_VENOUS_PRESSURE_HIGH if venous pressure does - * not stabilize within 5s. - * @details \b Inputs: dcDepressurizeElapsedMs - * @details \b Outputs: dcDepressurizeElapsedMs - * @return next Prime state - *************************************************************************/ -static TD_PRIME_STATE_T handlePrimeDCDepressurizeState( void ) -{ - TD_PRIME_STATE_T state = PRIME_DC_DEPRESSURIZE_STATE; - F32 venPres = getFilteredVenousPressure(); - - if ( fabs( venPres ) <= DC_PRIME_RESUME_VEN_PRES_LIMIT_MMHG ) - { - //cmdDDChamberHValveOpen( FALSE ); - setPrimeStateTransition ( PRIME_DC_INITIAL_DIALYSATE_STATE ); - state = PRIME_DC_INITIAL_DIALYSATE_STATE; - } - else if ( ++dcDepressurizeElapsedMs >= VEN_PRES_STABILIZATION_TIMEOUT_INTERVAL_MS ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_HIGH, (U32)venPres ); - } -// else if ( DD_GEND_SPENT_CHAMBER_VENT_OPEN_STATE == getCurrentGenDState() ) -// { -// -// if ( ++dcDepressurizeElapsedMs >= VEN_PRES_STABILIZATION_TIMEOUT_INTERVAL_MS ) -// { -// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_VENOUS_PRESSURE_HIGH, (U32)venPres ); -// } -// } - else - { - // No action required. - } - - return state; -} - -/*********************************************************************//** - * @brief * The handleWaitForAirTrapFillState function waits for the air trap to * fill to the upper level sensor (H16) before starting the blood pump * reversal sequence. @@ -916,7 +933,9 @@ if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H16_LEVL ) ) { + endAirTrapControl(); setPrimeStateTransition( PRIME_BC2_FORWARD_RECIRC_STATE ); + startProgressSequence( BC2_PRIME_ESTIMATE_INTERVAL ); state = PRIME_BC2_FORWARD_RECIRC_STATE; } return state; @@ -946,8 +965,13 @@ } else { - setPrimeStateTransition( PRIME_DC_DISCARD_AND_REVERSE_PRIME_STATE ); - state = PRIME_DC_DISCARD_AND_REVERSE_PRIME_STATE; + cmdDDprimeFluidDiscard( TRUE ); + signalBloodPumpHardStop(); + if ( FALSE == getBalChamberSwitchingStatus() ) + { + setPrimeStateTransition( PRIME_DC_DISCARD_AND_REVERSE_PRIME_STATE ); + state = PRIME_DC_DISCARD_AND_REVERSE_PRIME_STATE; + } } } //First 15 sec @@ -1045,7 +1069,6 @@ { if ( TRUE == didTimeout( stateEntryTimerCtr, dcInitialPrimeInterval ) ) { - //cmdChangeQuf( 0.0F ); setPrimeStateTransition( PRIME_COMPLETE_STATE ); state = PRIME_COMPLETE_STATE; } @@ -1077,6 +1100,48 @@ /*********************************************************************//** * @brief + * The setBloodAndDialysateVolume function updates the dialyzer blood and + * dialysate volumes used for prime duration calculations. Uses the actual + * selected dialyzer's volumes once Rx is confirmed, or the largest + * available volumes is used. + * @details \b Inputs: none + * @details \b Outputs: dilayzerBloodVolume, dialyzerDialysateVolume + * @return none + *************************************************************************/ +static void setBloodAndDialysateVolume( void ) +{ + if ( TRUE == getValidTreatParamsReceived() ) + { + // Rx confirmed -- use the actual selected dialyzer's volumes. + dilayzerBloodVolume = getDialyzerBloodVolume( (DIALYZER_TYPE_T)getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ); + dialyzerDialysateVolume = getDialyzerDialysateVolume( (DIALYZER_TYPE_T)getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ); + } +} + +/*********************************************************************//** + * @brief + * The startProgressSequence function marks the start of a new progress + * sequence, closing out the previous sequence and subracts any unused time + * if it completed early than its estimate. + * @details \b Inputs: seqStartTime, seqEstimateMs + * @details \b Outputs: seqStartTime, seqEstimateMs, primeTimeCreditMs + * @param estimateMs estimated time (ms) for the sequence being entered + * @return none + *************************************************************************/ +static void startProgressSequence( U32 estimateMs ) +{ + if ( ( 0 != seqStartTime ) && ( calcTimeSince( seqStartTime ) < seqEstimateTime ) ) + { + // Previous sequence finished early -- bank the unused time. + primeTimeCreditMs += ( seqEstimateTime - calcTimeSince( seqStartTime ) ); + } + + seqEstimateTime = estimateMs; + seqStartTime = getMSTimerCount(); +} + +/*********************************************************************//** + * @brief * The publishPrimeData function broadcasts prime data during priming. * @details \b Message \b Sent: MSG_ID_TD_PRIME_PROGRESS_DATA * @details \b Inputs: primePublishTimerCtr, currentPrimeState, primeStartTime, @@ -1086,7 +1151,7 @@ *************************************************************************/ static void publishPrimeData( void ) { - if ( ++primePublishTimerCtr >= PRIME_DATA_PUB_INTERVAL ) + if ( ++primePublishTimerCtr >= getU32OverrideValue( &primePublishInterval ) ) { PRIMING_DATA_PAYLOAD_T data; U32 elapsedMs; @@ -1106,6 +1171,8 @@ elapsedMs = calcTimeSince( primeStartTime ); } + elapsedMs = ( elapsedMs > primeTimeCreditMs ) ? ( elapsedMs - primeTimeCreditMs ) : 0; + remainingMs = ( elapsedMs < PRIME_TOTAL_DURATION_INTERVAL ) ? ( PRIME_TOTAL_DURATION_INTERVAL - elapsedMs ) : 0; @@ -1119,4 +1186,26 @@ } } + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + +/*********************************************************************//** + * @brief + * The testPrimePublishIntervalOverride function overrides the interval + * at which the TD prime data is published. + * @details \b Inputs: none + * @details \b Outputs: primePublishInterval + * @param message Override message from Dialin which includes the interval + * to override the prime broadcast interval. + * @return TRUE if override request is successful, FALSE if not + *************************************************************************/ +BOOL testPrimePublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &primePublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + /**@}*/