Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r791b25bd20e80fce8c5d7e8a3ac37d8395f2315c -r556668d4ef26ad4afbc438cc28d397a898459084 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 791b25bd20e80fce8c5d7e8a3ac37d8395f2315c) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 556668d4ef26ad4afbc438cc28d397a898459084) @@ -7,8 +7,8 @@ * * @file ModeTreatment.c * -* @author (last) Dara Navaei -* @date (last) 04-Jun-2023 +* @author (last) Sean Nash +* @date (last) 11-Jul-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -834,6 +834,7 @@ transitionToBloodPrime(); result = TREATMENT_BLOOD_PRIME_STATE; } + signalInitiatePressureStabilization(); } // If user requests rinseback, go to rinseback else if ( TRUE == initiateRinsebackAlarmResponseRequest ) @@ -873,16 +874,33 @@ * @brief * The handleTreatmentRinsebackState function executes the rinseback state of the * Treatment Mode state machine. - * @details Inputs: none - * @details Outputs: treatment rinseback sub-mode executed. + * @details Inputs: endTreatmentAlarmResponseRequest, resumeTreatmentAlarmResponseRequest, + * rinsebackToRecircRequest, rinsebackToStoppedRequest, endTreatmentRequest + * @details Outputs: treatment rinseback sub-mode executed, sendLastTreatmentPeriodicData * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentRinsebackState( void ) { TREATMENT_STATE_T result = TREATMENT_RINSEBACK_STATE; - // Execute treatment rinseback sub-mode - execRinseback(); + // If user requests treatment end, end treatment + if ( TRUE == endTreatmentAlarmResponseRequest ) + { + sendLastTreatmentPeriodicData = TRUE; + requestNewOperationMode( MODE_POST ); + } + // Otherwise execute state machine for treatment rinseback sub-mode + else + { + // If user requests resumption of treatment, resume rinseback + if ( TRUE == resumeTreatmentAlarmResponseRequest ) + { + resumeTreatmentAlarmResponseRequest = FALSE; + signalRinsebackAlarmResumeUserAction(); + } + // Execute treatment rinseback sub-mode + execRinseback(); + } // Handle signals from rinseback sub-mode if ( TRUE == rinsebackToRecircRequest ) @@ -1202,6 +1220,7 @@ { sendTreatmentLogEventData( UF_RATE_CHANGE_EVENT, presUFRate, pendingUFRateChange ); presUFRate = pendingUFRateChange; + signalInitiatePressureStabilization(); } setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); @@ -1268,7 +1287,7 @@ if ( ( bloodRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ) || ( dialRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) ) { - signalUserRateChange(); + signalInitiatePressureStabilization(); } // Set to new rates setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r874d279bf969199988c7ab6ca2891eec6a6c1bb0 -r556668d4ef26ad4afbc438cc28d397a898459084 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 874d279bf969199988c7ab6ca2891eec6a6c1bb0) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 556668d4ef26ad4afbc438cc28d397a898459084) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Michael Garthwaite -* @date (last) 14-Jun-2023 +* @author (last) Sean Nash +* @date (last) 10-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 08-Dec-2020 @@ -57,12 +57,12 @@ #define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. #define PURGE_AIR_TIME_OUT_COUNT ( 240 * MS_PER_SECOND ) ///< Time period count for purge air time out. -#define PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for prime saline dialyzer time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 8 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. -#define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 55 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. +#define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 90 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. #define STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ( 62 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during bypass dialysate prime state. +#define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ( 0.3F ) ///< mL of histeresis for the steady state check that determines when bypass line is primed. #define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML ( 0.3F ) ///< mL of histeresis for the steady state check that determines when bypass line is primed. #define VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum venous pressure reading (in mmHg) for bubble clear. @@ -550,7 +550,7 @@ /*********************************************************************//** * @brief - * The handlePrimeSalineSetupState function checks user's request to start + * The handlePrimeWaitForUserStartState function checks user's request to start * priming. * @details Inputs: primeStartReqReceived * @details Outputs: control valves to purge air @@ -562,6 +562,8 @@ // Keep updating start time until the user requested priming primeStartTime = getMSTimerCount(); + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) @@ -605,6 +607,7 @@ purgeAirValvesBloodPumpControl(); purgeAirTimeOutStartTime = getMSTimerCount(); primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + if ( getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) != TRUE ) { primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; @@ -764,8 +767,10 @@ * @brief * The handlePrimeDialysateDialyzerState function handles priming for * dialysate dialyzer fluid path. - * @details Inputs: reservoir 1 filtered weight - * @details Outputs: primed dialysate dialyzer fluid path + * @details Inputs: reservoir 1 filtered weight, minimumReservoirVolume, + * steadyVolumeCount + * @details Outputs: primed dialysate dialyzer fluid path, minimumReservoirVolume, + * steadyVolumeCount * @return current state *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ) @@ -779,7 +784,7 @@ { F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -788,9 +793,12 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; // required 10 seconds continuous steady volume to transition to next state } + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next dVolume/dt check } @@ -866,11 +874,6 @@ { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; } - // TODO: Rework alarm and timeout logic here. PRIME_SALINE_DIALYZER_TIME_OUT_COUNT may not be reached. - if ( TRUE == didTimeout( primeSalineDialyzerStartTime, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_SALINE_DIALYZER_TIME_OUT, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ); // Trigger HD prime saline dialyzer time out alarm. - } if ( TRUE == doesAlarmStatusIndicateStop() ) { Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r791b25bd20e80fce8c5d7e8a3ac37d8395f2315c -r556668d4ef26ad4afbc438cc28d397a898459084 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 791b25bd20e80fce8c5d7e8a3ac37d8395f2315c) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 556668d4ef26ad4afbc438cc28d397a898459084) @@ -7,8 +7,8 @@ * * @file SelfTests.c * -* @author (last) Michael Garthwaite -* @date (last) 01-Jun-2023 +* @author (last) Sean Nash +* @date (last) 12-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 28-Jan-2021 @@ -130,8 +130,9 @@ static U32 bloodLeakDebubbleStartTimeMS; ///< Blood leak detector debubble start time in milliseconds. static BOOL useHeparin; ///< Flag indicates the user of heparin. - static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. +static BOOL cartridgeUsedTestRun; ///< Flag indicates whether the used cartridge test has been run. +static BOOL doorStateAfterCartridgeInstall; ///< Flag indicates state of front door for saline clamp check after cartridge installed. // ********** private function prototypes ********** @@ -188,6 +189,7 @@ selfTestStartTime = 0; selfTestPreviousPublishDataTime = 0; syringeOcclusionDelayStartTime = 0; + doorStateAfterCartridgeInstall = TRUE; } /*********************************************************************//** @@ -382,21 +384,13 @@ if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; selfTestPreviousPublishDataTime = getMSTimerCount(); - if ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ) - { - SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; - - data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; - data.countdown = ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); - broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); - } - else - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CART_SELF_TEST_TIMEOUT, currentNoCartSelfTestsState ); - } + data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; + data.countdown = ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ? MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs : 0 ); + broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); } } @@ -417,8 +411,9 @@ * @brief * The transitionToDrySelfTests function resets anything required before * the start of dry self-tests. - * @details Inputs: none - * @details Outputs: Dry self-tests re-initialized. + * @details Inputs: front door state + * @details Outputs: Dry self-tests re-initialized, VBA state changed depending + * on front door state * @return none *************************************************************************/ void transitionToDrySelfTests() @@ -429,6 +424,7 @@ previousNormalArterialPressure = 0.0; previousNormalVenousPressure = 0.0; dryPressureTestsCompleted = FALSE; + cartridgeUsedTestRun = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); selfTestCartridgeSettleTime = getMSTimerCount(); @@ -444,7 +440,14 @@ setValveAirTrap( STATE_CLOSED ); setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + if ( STATE_CLOSED == getSwitchStatus( FRONT_DOOR ) ) + { + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + } + else + { + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + } setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); resetSelfTestsFlags(); @@ -947,15 +950,15 @@ DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_START_STATE; OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + handleDoorCloseAfterCartridgeInsertion(); // want to pinch off saline once door closed after cartridge install + if ( STATE_CLOSED == pumpTrack ) { // Ensure occlusion sensor has time to settle after cartridge insertion before starting dry self-tests if ( TRUE == didTimeout( selfTestCartridgeSettleTime, CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ) ) { setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed doorClosedRequired( TRUE, TRUE ); - signalAllowDGFillRes1(); - signalAllowDGFillRes2(); state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } } @@ -994,7 +997,7 @@ state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); } @@ -1012,7 +1015,7 @@ * The handleDrySelfTestUsedCartridgeCheckState function verify no fluid is * detected by bubble detectors to ensure the cartridge is new. * @details Inputs: none - * @details Outputs: none + * @details Outputs: cartridgeUsedTestRun * @return the next state of dry self-tests state machine *************************************************************************/ static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) @@ -1034,6 +1037,7 @@ { // If either of the test configurations are set go to loaded check state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + cartridgeUsedTestRun = TRUE; } else { @@ -1467,19 +1471,6 @@ setupForSelfTestsStop(); } -#ifndef _RELEASE_ - if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) || // Allow res 1&2 fills now if air pump not disabled - ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) ) - { - if ( state != DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE ) - { - signalAllowDGFlushFills(); - signalAllowDGFillRes1(); - signalAllowDGFillRes2(); - } - } -#endif - return state; } @@ -1560,7 +1551,15 @@ else { doorClosedRequired( FALSE, TRUE ); - state = DRY_SELF_TESTS_START_STATE; + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + if ( TRUE == cartridgeUsedTestRun ) + { + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else + { + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } } } @@ -2095,4 +2094,29 @@ return state; } +/*********************************************************************//** + * @brief + * The handleDoorCloseAfterCartridgeInsertion function handles the check + * for door close after cartridge install so that saline line can be pinched. + * @details Inputs: door and latch states, doorStateAfterCartridgeInstall + * @details Outputs: doorStateAfterCartridgeInstall + * @return none + *************************************************************************/ +void handleDoorCloseAfterCartridgeInsertion( void ) +{ + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + if ( ( STATE_OPEN == frontDoor ) && ( TRUE == doorStateAfterCartridgeInstall ) ) + { + doorStateAfterCartridgeInstall = FALSE; + } + // when transitioning from door open to door closed, pinch off saline bag to prevent saline from running up the line + if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) && ( FALSE == doorStateAfterCartridgeInstall ) ) + { + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + doorStateAfterCartridgeInstall = TRUE; + } +} + /**@}*/ Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r2c1afe706e509c4e7dd0724bfacaa5517c42ef48 -r556668d4ef26ad4afbc438cc28d397a898459084 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 2c1afe706e509c4e7dd0724bfacaa5517c42ef48) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 556668d4ef26ad4afbc438cc28d397a898459084) @@ -421,25 +421,25 @@ static F32 getReservoirRecirculationMaxPercent( void ) { U32 targetDialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); - F32 maxPercent = 0.0F; + F32 maxPercent = 0.0F; - if (RESERVOIR_FLOW_400_MLP >= targetDialysateFlowMLP) + if ( targetDialysateFlowMLP <= RESERVOIR_FLOW_400_MLP ) { maxPercent = MAX_RESERVOIR_RECIRCULATION_400_MLP; } - else if (RESERVOIR_FLOW_450_MLP >= targetDialysateFlowMLP) + else if ( targetDialysateFlowMLP <= RESERVOIR_FLOW_450_MLP ) { maxPercent = MAX_RESERVOIR_RECIRCULATION_450_MLP; } - else if (RESERVOIR_FLOW_500_MLP >= targetDialysateFlowMLP) + else if ( targetDialysateFlowMLP <= RESERVOIR_FLOW_500_MLP ) { maxPercent = MAX_RESERVOIR_RECIRCULATION_500_MLP; } - else if (RESERVOIR_FLOW_550_MLP >= targetDialysateFlowMLP) + else if ( targetDialysateFlowMLP <= RESERVOIR_FLOW_550_MLP ) { maxPercent = MAX_RESERVOIR_RECIRCULATION_550_MLP; } - else // if (RESERVOIR_FLOW_600_MLP >= targetDialysateFlowMLP) + else { maxPercent = MAX_RESERVOIR_RECIRCULATION_600_MLP; }