Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r5d9c5362b537331248dc592e05b6b016267eb6d3 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -8,7 +8,7 @@ * @file BloodLeak.c * * @author (last) Dara Navaei -* @date (last) 11-Jan-2023 +* @date (last) 22-Jan-2023 * * @author (original) Peman Montazemi * @date (original) 18-Mar-2021 @@ -573,7 +573,7 @@ case Q_EMB_MODE_CMD: case T_EMB_MODE_CMD: // Check to see if any of the command responses failed - hasCurrCmdFailed = ( BLOOD_LEAK_EMB_MODE_FAIL_ASCII == bloodLeakEmbModeCmd[ i ].commandResp ? TRUE : FALSE ); + hasCurrCmdFailed = ( BLOOD_LEAK_EMB_MODE_PASS_ASCII == bloodLeakEmbModeCmd[ i ].commandResp ? FALSE : TRUE ); hasCmdSqncFailed |= hasCurrCmdFailed; failedCmd = ( TRUE == hasCurrCmdFailed ? i : NU_EMB_MODE_CMD ); break; Index: firmware/App/Controllers/Buttons.c =================================================================== diff -u -r7d4fe5b7c29e66be9c09c076eb8c7b295e1d280b -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision 7d4fe5b7c29e66be9c09c076eb8c7b295e1d280b) +++ firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -8,7 +8,7 @@ * @file Buttons.c * * @author (last) Dara Navaei -* @date (last) 13-Jun-2022 +* @date (last) 18-Jan-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -260,6 +260,18 @@ /*********************************************************************//** * @brief + * The resetStuckButtonPOSTState function resets the stuck button POST state. + * @details Inputs: none + * @details Outputs: buttonSelfTestState + * @return none + *************************************************************************/ +void resetStuckButtonPOSTState( void ) +{ + buttonSelfTestState = BUTTON_SELF_TEST_STATE_START; +} + +/*********************************************************************//** + * @brief * The userConfirmOffButton function handles user confirmation of the off * button. The off request will be initiated here if confirmed or cancelled * if rejected by user. Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r6015f14d02e1b0dd73b2bed1d9ac84a83a20172e -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 6015f14d02e1b0dd73b2bed1d9ac84a83a20172e) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -146,15 +146,10 @@ static F32 shortFilteredArterialPressure; ///< Measured arterial pressure after short (1 s) filter. static F32 shortFilteredVenousPressure; ///< Measured venous pressure after short (1 s) filter. -static U32 airPumpOpenToleranceTimer; ///< Timer for increased maximum venous high limit. - static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. -static U08 lastBPOcclReadCtr; ///< Previous BP occlusion sensor read count. -static U08 lastBPErrorCtr; ///< Previous BP error count. - static F32 artPressureReadingsLong[ SIZE_OF_LONG_ART_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. static U32 artPressureReadingsLongIdx = 0; ///< Index for next sample in rolling average array. static F32 artPressureReadingsLongTotal = 0.0; ///< Rolling total - used to calc average. @@ -212,28 +207,13 @@ initFPGAPersistentAlarm( FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, ALARM_ID_HD_VENOUS_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - lastBPOcclReadCtr = 0; - lastBPErrorCtr = 0; - } - longFilteredArterialPressure = 0.0F; shortFilteredArterialPressure = 0.0F; shortFilteredVenousPressure = 0.0F; presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; presOcclState = PRESSURE_WAIT_FOR_POST_STATE; presOcclPostState = PRESSURE_SELF_TEST_STATE_START; - airPumpOpenToleranceTimer = 0; - -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - bloodPumpOcclusionAfterCartridgeInstall = 0; - } + bloodPumpOcclusionAfterCartridgeInstall = 0; } /*********************************************************************//** @@ -459,15 +439,6 @@ // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); - -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - // Record occlusion read and error counters for next time around - lastBPOcclReadCtr = bpReadCtr; - lastBPErrorCtr = bpErrorCtr; - } } /*********************************************************************//** @@ -486,16 +457,20 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ARTERIAL_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - // Check arterial pressure is in range + TREATMENT_STATE_T txState = getTreatmentState(); + + // 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 == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || + ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); @@ -550,15 +525,19 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_VENOUS_PRESSURE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - // Check venous pressure is in range + TREATMENT_STATE_T txState = getTreatmentState(); + + // 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 - if ( MODE_TREA == getCurrentOperationMode() && - TREATMENT_DIALYSIS_STATE == getTreatmentState() && getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) + // 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_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || + ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); @@ -652,7 +631,7 @@ if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl, OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) } } } @@ -666,7 +645,7 @@ if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl, OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) } } } @@ -885,12 +864,12 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SELF_TEST_FAILURE, bpPressure ); } - if ( ( arterialPressure <= ARTERIAL_PRESSURE_SELF_TEST_MIN ) || ( arterialPressure >= ARTERIAL_PRESSURE_SELF_TEST_MAX ) ) + if ( ( arterialPressure < ARTERIAL_PRESSURE_SELF_TEST_MIN ) || ( arterialPressure > ARTERIAL_PRESSURE_SELF_TEST_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_SELF_TEST_FAILURE, arterialPressure ); } - if ( ( venousPressure <= VENOUS_PRESSURE_SELF_TEST_MIN ) || ( venousPressure >= VENOUS_PRESSURE_SELF_TEST_MAX ) ) + if ( ( venousPressure < VENOUS_PRESSURE_SELF_TEST_MIN ) || ( venousPressure > VENOUS_PRESSURE_SELF_TEST_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_SELF_TEST_FAILURE, venousPressure ); } @@ -914,7 +893,7 @@ { U32 const bpPressure = getMeasuredBloodPumpOcclusion(); - if ( ( bpPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( bpPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) + if ( ( bpPressure < CARTRIDGE_LOADED_THRESHOLD ) || ( bpPressure > OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) { activateAlarmNoData( ALARM_ID_NO_CARTRIDGE_LOADED ); result = SELF_TEST_STATUS_FAILED; Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r8da12f877491ce76e60645acfa738458f954293a -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 8da12f877491ce76e60645acfa738458f954293a) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file Valves.c * -* @author (last) Darren Cox -* @date (last) 12-Jan-2023 +* @author (last) Dara Navaei +* @date (last) 22-Jan-2023 * * @author (original) Dara Navaei * @date (original) 07-Aug-2020 @@ -252,6 +252,7 @@ static void publishValvesData( VALVE_T valve ); static void setValveNextStep( VALVE_T valve, U32 stepChange ); static S16 getValvePositionCounts( VALVE_T valve ); +static BOOL isValveCloseToCommandedPosition( VALVE_T valve, VALVE_POSITION_T positionToCheck ); // These functions will be used in debug only mode #ifdef DEBUG_ENABLED @@ -479,6 +480,19 @@ /*********************************************************************//** * @brief + * The resetValvesPOSTState function resets the valves POST state; + * @details Inputs: none + * @details Outputs: valveSelfTestState, valvesSelfTestResult + * @return none + *************************************************************************/ +void resetValvesPOSTState( void ) +{ + valveSelfTestState = VALVE_SELF_TEST_ENABLE_VALVES; + valvesSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; +} + +/*********************************************************************//** + * @brief * The execValves function executes the valves exec state machine. * @details Inputs: valvesStatus * @details Outputs: valvesStatus @@ -809,7 +823,8 @@ } else if ( ( TRUE == valvesStatus[ valve ].hasValveBeenHomed ) && ( TRUE == valvesStatus[ valve ].hasTransitionBeenRequested ) ) { - if ( valvesStatus[ valve ].currentPosition != valvesStatus[ valve ].pendingCommandedPosition ) + if ( ( valvesStatus[ valve ].currentPosition != valvesStatus[ valve ].pendingCommandedPosition ) || + ( FALSE == isValveCloseToCommandedPosition( valve, valvesStatus[ valve ].pendingCommandedPosition ) ) ) { // Just set the valves to transition so it will not be in a known position for a while valvesStatus[ valve ].commandedPosition = valvesStatus[ valve ].pendingCommandedPosition; @@ -945,7 +960,7 @@ { // Get the set and reset bits for the particular valve U16 control = VALVE_CONTROL_MODES_SET_BITS[ valve ][ mode ]; - U16 reset = VALVE_CONTROL_MODES_RESET_BITS[ valve ]; + U16 reset = VALVE_CONTROL_MODES_RESET_BITS[ valve ]; // Reset the control bits of the particular valve valvesControlSetBits &= reset; @@ -1158,9 +1173,9 @@ static void getAndMonitorValvesCurrentFPGAPosition( void ) { VALVE_T valve; - S16 currentPosition = 0; - S16 commandedPosition = 0; VALVE_POSITION_T commandedPositionEnum; + S16 currentPosition = 0; + S16 commandedPosition = 0; // Get the position of the valves and update the structure of each valve valvesStatus[ VDI ].currentPositionInCounts.data = (S32)getFPGAValveDialyzerInletPosition(); @@ -1196,10 +1211,13 @@ if ( valvesStatus[ valve ].positionOutOfRangeCounter > MAX_POS_DEVIATION_TIME_INTERVAL_COUNTER ) { + // If the valve's deviation from target was more than the counts for the define period of time trigger the alarm. + // Also, set the state to Idle so in the fault mode, the valve can transition to Pos C. The exec state is directly set here + // because this is a monitor function that is called in the controller function. + valvesStatus[ valve ].execState = VALVE_STATE_IDLE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_POSITION_OUT_OF_RANGE, (U32)valve, currentPosition ); } - else if ( ( abs( currentPosition - commandedPosition ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS ) && - ( valvesStatus[ valve ].positionOutOfRangeCounter > 0 ) ) + else if ( ( TRUE == isValveCloseToCommandedPosition( valve, commandedPositionEnum ) ) && ( valvesStatus[ valve ].positionOutOfRangeCounter > 0 ) ) { valvesStatus[ valve ].positionOutOfRangeCounter = 0; } @@ -1256,11 +1274,11 @@ *************************************************************************/ static void setValveNextStep( VALVE_T valve, U32 stepChange ) { - S16 nextStep = 0; + S16 nextStep = 0; VALVE_POSITION_T currentPositionEnum = valvesStatus[ valve ].currentPosition; VALVE_POSITION_T commandedPositionEnum = valvesStatus[ valve ].commandedPosition; - S16 currentPosition = getValvePositionCounts( valve ); - S16 commandedPosition = valvesStatus[ valve ].positions[ commandedPositionEnum ]; + S16 currentPosition = getValvePositionCounts( valve ); + S16 commandedPosition = valvesStatus[ valve ].positions[ commandedPositionEnum ]; // If the next step is less than the specified step change, set that if ( abs( currentPosition - commandedPosition ) <= stepChange ) @@ -1334,6 +1352,27 @@ return position; } +/*********************************************************************//** + * @brief + * The isValveCloseToCommandedPosition function checks whether a valve is close + * to its commanded position or not + * @details Inputs: valvesStatus + * @details Outputs: none + * @param valve that its position in counts is requested + * @param positionToCheck the position enum (can be commanded to pending commanded enums + * to check) + * @return TRUE if the valve is within accepted deviation from commanded otherwise, + * FALSE + *************************************************************************/ +static BOOL isValveCloseToCommandedPosition( VALVE_T valve, VALVE_POSITION_T positionToCheck ) +{ + S16 currentPosition = getValvePositionCounts( valve ); + S16 commandedPosition = valvesStatus[ valve ].positions[ positionToCheck ]; + BOOL isInRange = ( abs( currentPosition - commandedPosition ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS ? TRUE : FALSE ); + + return isInRange; +} + #ifdef DEBUG_ENABLED /*********************************************************************//** * @brief Index: firmware/App/Drivers/SafetyShutdown.c =================================================================== diff -u -r7d4fe5b7c29e66be9c09c076eb8c7b295e1d280b -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Drivers/SafetyShutdown.c (.../SafetyShutdown.c) (revision 7d4fe5b7c29e66be9c09c076eb8c7b295e1d280b) +++ firmware/App/Drivers/SafetyShutdown.c (.../SafetyShutdown.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file SafetyShutdown.c * -* @author (last) Sean Nash -* @date (last) 21-Dec-2022 +* @author (last) Dara Navaei +* @date (last) 18-Jan-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -200,6 +200,18 @@ return result; } +/*********************************************************************//** + * @brief + * The resetSafetyShutdownPOSTState function resets safety shutdown POST state. + * @details Inputs: none + * @details Outputs: safetyShutdownSelfTestState + * @return none + *************************************************************************/ +void resetSafetyShutdownPOSTState( void ) +{ + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_START; +} + /*********************************************************************//** * @brief * The testSetSafetyShutdownOverride function overrides the HD safety Index: firmware/App/Modes/ConsumableSelfTest.c =================================================================== diff -u -ra57994f752662abc0aaa8c2cf5c3af47ec2c5a20 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/ConsumableSelfTest.c (.../ConsumableSelfTest.c) (revision a57994f752662abc0aaa8c2cf5c3af47ec2c5a20) +++ firmware/App/Modes/ConsumableSelfTest.c (.../ConsumableSelfTest.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file ConsumableSelfTest.c * -* @author (last) Dara Navaei -* @date (last) 05-Jun-2022 +* @author (last) Michael Garthwaite +* @date (last) 19-Jan-2023 * * @author (original) Quang Nguyen * @date (original) 06-Mar-2021 @@ -25,6 +25,7 @@ #include "Reservoirs.h" #include "SelfTests.h" #include "SyringePump.h" +#include "SystemCommMessages.h" #include "Valves.h" /** @@ -91,6 +92,8 @@ *************************************************************************/ void execConsumableSelfTest( void ) { + CONSUMABLE_SELF_TESTS_STATE_T priorSubState = currentConsumableSelfTestState; + switch( currentConsumableSelfTestState ) { case CONSUMABLE_SELF_TESTS_INSTALL_STATE: @@ -153,6 +156,10 @@ break; } + if ( priorSubState != currentConsumableSelfTestState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentConsumableSelfTestState ); + } // Handle triggered alarm with stop property handleConsumableSelfTestStopRequest(); } Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -109,8 +109,6 @@ static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); -static void startHeparinPump( void ); - static void checkUFAccuracyAndVolume( void ); static void updateUFVolumes( void ); @@ -130,15 +128,17 @@ { U16 i; - currentDialysisState = DIALYSIS_START_STATE; - currentUFState = UF_START_STATE; + currentDialysisState = DIALYSIS_UF_STATE; + currentUFState = UF_RUNNING_STATE; currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; + lastUFTimeStamp = getMSTimerCount(); + uFTimeMS = 0; + refUFVolume = 0.0; measUFVolume = 0.0; measUFVolumeFromPriorReservoirs = 0.0; - // Send reset UF volumes to dialysate outlet pump - setDialOutUFVolumes( refUFVolume, measUFVolume ); + setDialOutUFVolumes( refUFVolume, measUFVolume ); // Send reset UF volumes to dialysate outlet pump driver uFTimeMS = 0; lastUFTimeStamp = 0; @@ -154,11 +154,12 @@ uFAccuracyCheckTimerCtr = 0; lastUFVolumeChecked = 0.0; - for (i=0; i= (F32)MAX_UF_ACCURACY_ERROR_ML ) + if ( ( fabs( refUFVolume - measUFVolume ) ) > (F32)MAX_UF_ACCURACY_ERROR_ML ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ULTRAFILTRATION_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r03bd494bf7b7c96f79cf9b8bd0f99432982b9571 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 03bd494bf7b7c96f79cf9b8bd0f99432982b9571) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -8,7 +8,7 @@ * @file ModeInitPOST.c * * @author (last) Dara Navaei -* @date (last) 11-Jan-2023 +* @date (last) 18-Jan-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -118,11 +118,23 @@ *************************************************************************/ U32 transitionToInitAndPOSTMode( void ) { + initInitAndPOSTMode(); + // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); + resetRTCPOSTState(); + resetNVDataMgmtPOSTState(); + resetAccelPOSTState(); + resetWatchdogPOSTState(); + resetSafetyShutdownPOSTState(); + resetValvesPOSTState(); + resetAlarmAudioPOSTState(); + resetAlarmLampPOSTState(); + resetStuckButtonPOSTState(); + return postState; } @@ -162,14 +174,14 @@ postState = handlePOSTStatus( testStatus ); break; + // NOTE: all the actuators and sensors must execute their POST after NVDataMgmt + // NVDataMgmt must load all the calibration data into RAM so the actuators + // can query their corresponding calibration values successfully case POST_STATE_NVDATAMGMT: testStatus = execNVDataMgmtSelfTest(); postState = handlePOSTStatus( testStatus ); break; - // NOTE: all the actuators and sensors must execute their POST after NVDataMgmt - // NVDataMgmt must load all the calibration data into RAM so the actuators - // can query their corresponding calibration values successfully case POST_STATE_WATCHDOG: testStatus = execWatchdogTest(); postState = handlePOSTStatus( testStatus ); Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -464,8 +464,6 @@ *************************************************************************/ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ) { - // Assuming the cartridge door is removed already. - // This is used when the disable cartridge removal step software configuration is enabled BOOL isCartridgeRemoved = TRUE; #ifndef _RELEASE_ Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -rf65557f45236336204b573c40646937edf01b054 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision f65557f45236336204b573c40646937edf01b054) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file ModeTreatmentParams.c * -* @author (last) Sean Nash -* @date (last) 01-Aug-2022 +* @author (last) Michael Garthwaite +* @date (last) 19-Jan-2023 * * @author (original) Sean Nash * @date (original) 29-May-2020 @@ -276,6 +276,7 @@ *************************************************************************/ U32 execTreatParamsMode( void ) { + HD_TREATMENT_PARAMS_MODE_STATE_T priorSubState = currentTreatmentParamsState; BOOL stop = isStopButtonPressed(); if ( TRUE == stop ) @@ -300,6 +301,11 @@ } + if ( priorSubState != currentTreatmentParamsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentTreatmentParamsState ); + } + return (U32)currentTreatmentParamsState; } Index: firmware/App/Modes/PreTreatmentRecirc.c =================================================================== diff -u -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -22,6 +22,8 @@ #include "DGInterface.h" #include "PreTreatmentRecirc.h" #include "Switches.h" +#include "SystemCommMessages.h" +#include "Timers.h" #include "Valves.h" /** @@ -31,14 +33,19 @@ // ********** 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. -#define DIALYSATE_PUMP_RECIRC_FLOW_RATE 250 ///< Dialysate pump flow rate during recirculation in mL/min. +#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. +#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 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 +65,9 @@ void initPreTreatmentRecirc( void ) { currentPreTreatmentRecircState = PRE_TREATMENT_RECIRC_STATE; + preTxRecircStartTime = getMSTimerCount(); + recircTOWarningGiven = FALSE; + recircTOAlarmGiven = FALSE; resetPreTreatmentRecircFlags(); } @@ -87,6 +97,14 @@ { HD_PRE_TREATMENT_RECIRC_STATE_T priorSubState = currentPreTreatmentRecircState; + // 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 ) { @@ -193,6 +211,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 -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -165,12 +165,11 @@ *************************************************************************/ void initPrime( void ) { - currentPrimeState = HD_PRIME_START_STATE; + currentPrimeState = HD_PRIME_WAIT_FOR_USER_START_STATE; currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_START_STATE; primeStartTime = 0; primePauseStartTime = 0; primeStatusBroadcastTimerCounter = 0; - } /*********************************************************************//** @@ -198,6 +197,12 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); stopSyringePump(); +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) +#endif + { + setAirPumpState( AIR_PUMP_STATE_OFF ); + } // Set valves to default positions setValveAirTrap( STATE_CLOSED ); @@ -223,19 +228,6 @@ // execute prime sub-mode state machine switch ( currentPrimeState ) { - case HD_PRIME_START_STATE: -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) - { - currentPrimeState = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; - } - else -#endif - { - currentPrimeState = HD_PRIME_WAIT_FOR_USER_START_STATE; - } - break; - case HD_PRIME_WAIT_FOR_USER_START_STATE: currentPrimeState = handlePrimeWaitForUserStartState(); break; @@ -280,13 +272,14 @@ currentPrimeState = handlePrimeWetSelfTestsState(); break; - case HD_PRIME_COMPLETE: - break; - case HD_PRIME_PAUSE: currentPrimeState = handlePrimePause(); break; + case HD_PRIME_COMPLETE: + // ok, do nothing here. pre-treatment will move on to recirculate once we get here. + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_PRIME_INVALID_STATE, currentReservoirMgmtState ); break; @@ -404,9 +397,12 @@ *************************************************************************/ static void setupForPrimePause( void ) { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); signalDialOutPumpHardStop(); signalDialInPumpHardStop(); signalBloodPumpHardStop(); + stopSyringePump(); primePauseStartTime = getMSTimerCount(); previousPrimeState = currentPrimeState; @@ -490,6 +486,14 @@ } #endif +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) + { + state = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; + } + else +#endif + if ( TRUE == primeStartRequested ) { primeStartRequested = FALSE; @@ -569,7 +573,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 ); @@ -578,7 +582,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 ); @@ -691,11 +695,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(); @@ -753,9 +752,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 ); @@ -842,6 +841,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; @@ -988,8 +988,7 @@ { state = HD_PRIME_COMPLETE; } - - if ( TRUE == doesAlarmStatusIndicateStop() ) + else if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForPrimePause(); state = HD_PRIME_PAUSE; @@ -1016,6 +1015,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/Rinseback.c =================================================================== diff -u -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -503,19 +503,19 @@ if ( ( rinsebackTimerCtr > MAX_RINSEBACK_DONE_TIME ) && ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { signalGoToTreatmentStopped(); - activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM, rinsebackTimerCtr, MAX_RINSEBACK_DONE_TIME ); clearAlarm( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); } // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? else if ( ( RINSEBACK_DONE_WARNING_TIME == rinsebackTimerCtr ) && ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { - activateAlarmNoData( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING, rinsebackTimerCtr, RINSEBACK_DONE_WARNING_TIME ); } // Have we been in this stopped state for too long w/o having delivered full blood volume back to patient? else if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < rinsebackTargetVolume_mL ) ) { signalGoToTreatmentStopped(); - activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM, rinsebackTimerCtr, MAX_RINSEBACK_TIME ); } else if ( TRUE == recircRequested ) { @@ -524,7 +524,7 @@ else if ( TRUE == additionalRinsebackRequested ) { additionalRinsebackRequested = FALSE; - // deliver additional rinseback volume only if max volume not reached and max time not reached + // deliver additional rinseback volume only if max time not reached or max volume has been reached (i.e. no more blood in line) if ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { rinsebackAdditionalTimerCtr = 0; @@ -910,7 +910,7 @@ { *rejReason = REQUEST_REJECT_REASON_TREATMENT_IS_COMPLETED; } - else if ( RINSEBACK_STOP_STATE != rinsebackState ) + else if ( rinsebackState != RINSEBACK_STOP_STATE ) { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } Index: firmware/App/Modes/SampleWater.c =================================================================== diff -u -ra57994f752662abc0aaa8c2cf5c3af47ec2c5a20 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/SampleWater.c (.../SampleWater.c) (revision a57994f752662abc0aaa8c2cf5c3af47ec2c5a20) +++ firmware/App/Modes/SampleWater.c (.../SampleWater.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file SampleWater.c * -* @author (last) Dara Navaei -* @date (last) 03-Apr-2022 +* @author (last) Michael Garthwaite +* @date (last) 19-Jan-2023 * * @author (original) Quang Nguyen * @date (original) 19-Feb-2021 @@ -91,6 +91,8 @@ *************************************************************************/ void execSampleWater( void ) { + SAMPLE_WATER_STATE_T priorSubState = currentSampleWaterState; + #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SAMPLE_WATER ) ) { @@ -117,6 +119,11 @@ break; } } + + if ( priorSubState != currentSampleWaterState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentSampleWaterState ); + } } /*********************************************************************//** Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r5d9c5362b537331248dc592e05b6b016267eb6d3 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 5d9c5362b537331248dc592e05b6b016267eb6d3) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file SelfTests.c * -* @author (last) Dara Navaei -* @date (last) 11-Jan-2023 +* @author (last) Michael Garthwaite +* @date (last) 30-Jan-2023 * * @author (original) Quang Nguyen * @date (original) 28-Jan-2021 @@ -48,7 +48,7 @@ #define PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ( 1 * MS_PER_SECOND ) ///< Delay 1 second prior to getting initial normal baseline pressures. #define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 30 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. -#define VENOUS_PRESSURE_SELF_TEST_MAX_TEST_TIME ( 30 * MS_PER_SECOND ) ///< Pressure self-test time to run venous self test in ms. +#define VENOUS_PRESSURE_SELF_TEST_MAX_TEST_TIME ( 60 * MS_PER_SECOND ) ///< Pressure self-test time to run venous self test in ms. #define DECAY_PRESSURE_SELF_TEST_TIME ( 4 * MS_PER_SECOND ) ///< time to wait for pressure to decay in ms. #define STABILTY_PRESSURE_SELF_TEST_TIME ( 5 * MS_PER_SECOND ) ///< Time to wait for pressure to stabilize in ms. #define NORMALIZED_PRESSURE_SELF_TEST_TIME ( 20 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize in ms. @@ -117,6 +117,7 @@ static F32 reservoirVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Hold the current volume of all reservoirs. static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been sent to DG. +static U32 selfTestCartridgeSettleTime; ///< Cartridge settle start time. static U32 selfTestStartTime; ///< Starting time of self-test (in ms). static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. @@ -137,6 +138,7 @@ static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeIdleState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStartState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalSetupState( void ); @@ -291,6 +293,8 @@ *************************************************************************/ void execNoCartSelfTests( void ) { + NO_CART_SELF_TESTS_STATE_T priorSubState = currentNoCartSelfTestsState; + // execute no cartridge self-tests state machine switch ( currentNoCartSelfTestsState ) { @@ -334,6 +338,10 @@ // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); + if ( priorSubState != currentNoCartSelfTestsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentNoCartSelfTestsState ); + } // Publish current self-test time data if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { @@ -386,9 +394,9 @@ previousNormalVenousPressure = 0.0; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); + selfTestCartridgeSettleTime = getMSTimerCount(); + doorClosedRequired( FALSE, TRUE ); - doorClosedRequired( TRUE, TRUE ); - // Pumps should be off signalBloodPumpHardStop(); signalDialInPumpHardStop(); @@ -414,25 +422,13 @@ *************************************************************************/ void execDrySelfTests( void ) { + DRY_SELF_TESTS_STATE_T priorSubState = currentDrySelfTestsState; + // execute dry self-tests state machine switch ( currentDrySelfTestsState ) { case DRY_SELF_TESTS_START_STATE: - // Ensure occlusion sensor has time to settle after cartridge insertion before starting dry self-tests - if ( TRUE == didTimeout( selfTestStartTime, CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ) ) - { - setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) - { - currentDrySelfTestsState = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; - } - else -#endif - { - currentDrySelfTestsState = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; - } - } + currentDrySelfTestsState = handleDrySelfTestStartState(); break; case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: @@ -511,6 +507,10 @@ // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); + if ( priorSubState != currentDrySelfTestsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDrySelfTestsState ); + } // Publish current self-test time data if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { @@ -589,6 +589,8 @@ *************************************************************************/ void execWetSelfTests( void ) { + WET_SELF_TESTS_STATE_T priorSubState = currentWetSelfTestsState; + #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WET_SELF_TEST ) == SW_CONFIG_ENABLE_VALUE ) { @@ -658,6 +660,11 @@ // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); + + if ( priorSubState != currentWetSelfTestsState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentWetSelfTestsState ); + } } /*********************************************************************//** @@ -891,6 +898,52 @@ /*********************************************************************//** * @brief + * The handleDrySelfTestStartState function makes sure door is + * closed before starting self-tests. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStartState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_START_STATE; + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + 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 ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) + { + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else +#endif + { + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } + } + } + + else + { + // doorClosedRequired() will trigger alarms if pumpTrack is open + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleDrySelfTestWaitForDoorCloseState function makes sure door is * closed before starting self-tests. * @details Inputs: none @@ -906,8 +959,7 @@ // Restart self-test start time selfTestStartTime = getMSTimerCount(); - // TODO: Use appropriate sensor driver - if (( STATE_CLOSED == frontDoor ) && (STATE_CLOSED == pumpTrack ) ) + if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) ) { state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); @@ -1123,6 +1175,7 @@ if ( TRUE == didTimeout( pressureSelfTestVenousTestStartTime, VENOUS_PRESSURE_SELF_TEST_MAX_TEST_TIME ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, venousPressure, VENOUS_PRESSURE_SELF_TEST_FIRST_PASS_LIMIT_MMHG ); + setAirPumpState( AIR_PUMP_STATE_OFF ); } if ( TRUE == doesAlarmStatusIndicateStop() ) @@ -1472,22 +1525,24 @@ doorClosedRequired( FALSE, FALSE ); - // Restart self-test start time - selfTestStartTime = getMSTimerCount(); - if ( TRUE == selfTestsResumeRequested ) { + // Restart self-test start time + selfTestStartTime = getMSTimerCount(); selfTestsResumeRequested = FALSE; - doorClosedRequired( TRUE, TRUE ); + selfTestCartridgeSettleTime = getMSTimerCount(); + #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRY_SELF_TESTS ) ) { + doorClosedRequired( TRUE, TRUE ); state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; } else #endif { - state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + doorClosedRequired( FALSE, TRUE ); + state = DRY_SELF_TESTS_START_STATE; } } Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r1f91b5a53bda942b0967817bbd5e68a499dbf816 -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 1f91b5a53bda942b0967817bbd5e68a499dbf816) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -37,8 +37,6 @@ /// Treatment stop status broadcast interval. #define TREATMENT_STOP_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) -/// Target flow rate for re-circulation of saline on blood-side circuit. -#define RECIRC_BP_FLOW_RATE_ML_MIN 100 // ********** private data ********** @@ -71,7 +69,7 @@ *************************************************************************/ void initTreatmentStop( void ) { - currentTxStopState = TREATMENT_STOP_RECIRC_STATE; + currentTxStopState = TREATMENT_STOP_RECIRC_STATE; // Assume blood and dialysate will recirculate initially - will stop pump(s) as appropriate in state machine bloodSittingTimerCtr = 0; stopPublishTimerCtr = TREATMENT_STOP_DATA_PUBLISH_INTERVAL; } @@ -102,9 +100,6 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - // Ensure syringe pump is stopped - stopSyringePump(); - // Set Dialysate valves to bypass filter for recirculation setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); @@ -160,12 +155,23 @@ *************************************************************************/ static void setupForBloodRecirculationState( void ) { + PUMP_CONTROL_MODE_T mode = PUMP_CONTROL_MODE_CLOSED_LOOP; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_BLOOD_PUMP_OPEN_LOOP ) ) + { + mode = PUMP_CONTROL_MODE_OPEN_LOOP; + } +#endif + 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 re-circulate flow rate - setBloodPumpTargetFlowRate( RECIRC_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Start blood pump at prescribed flow rate + setBloodPumpTargetFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), MOTOR_DIR_FORWARD, mode ); + // Start Heparin pump as appropriate + startHeparinPump(); // Start air trap leveling control startAirTrapControl(); // Reset blood sitting timer, it is now circulating @@ -201,6 +207,8 @@ { // Stop blood pump signalBloodPumpHardStop(); + // Stop syringe pump + stopSyringePump(); // Close arterial and venous lines setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); @@ -267,36 +275,34 @@ BOOL dialysateRecircBlocked = isDialysateRecircBlocked(); // Both unblocked and not in recirculate both state - if ( (TREATMENT_STOP_RECIRC_STATE != state) && ( FALSE == dialysateRecircBlocked ) - && ( FALSE == bloodRecircBlocked ) ) + if ( ( TREATMENT_STOP_RECIRC_STATE != state ) && ( FALSE == dialysateRecircBlocked ) && ( FALSE == bloodRecircBlocked ) ) { setupForBloodRecirculationState(); setupForDialysateRecirculationState(); result = TREATMENT_STOP_RECIRC_STATE; } // Both blocked and not in stopped state - if ( (TREATMENT_STOP_NO_RECIRC_STATE != state) && ( TRUE == dialysateRecircBlocked ) - && ( TRUE == bloodRecircBlocked ) ) + 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 - if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) - && ( TRUE == dialysateRecircBlocked ) - && ( FALSE == bloodRecircBlocked ) ) + 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 - if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) - && ( TRUE == bloodRecircBlocked ) - && ( FALSE == dialysateRecircBlocked ) ) + if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) && + ( TRUE == bloodRecircBlocked ) && + ( FALSE == dialysateRecircBlocked ) ) { setupForBloodRecirculationStopState(); result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; @@ -408,6 +414,7 @@ bloodSittingTimerCtr = 0; } } + /*********************************************************************//** * @brief * The getCurrentTreatmentStopState function returns the current state of the Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r88868fb5e8f2fcc82f50a952be700863f3cbe19c -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 88868fb5e8f2fcc82f50a952be700863f3cbe19c) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file AlarmMgmt.c * -* @author (last) Sean Nash -* @date (last) 22-Dec-2022 +* @author (last) Dara Navaei +* @date (last) 18-Jan-2023 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -1451,6 +1451,18 @@ return result; } + +/*********************************************************************//** + * @brief + * The resetAlarmAudioPOSTState function resets the alarm audio POST state. + * @details Inputs: none + * @details Outputs: alarmAudioSelfTestState + * @return none + *************************************************************************/ +void resetAlarmAudioPOSTState( void ) +{ + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; +} /************************************************************************* Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -r88868fb5e8f2fcc82f50a952be700863f3cbe19c -r75e1ae332d1446dddf9b8d4ce6e8317449c57d67 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 88868fb5e8f2fcc82f50a952be700863f3cbe19c) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 75e1ae332d1446dddf9b8d4ce6e8317449c57d67) @@ -7,8 +7,8 @@ * * @file AlarmMgmt.h * -* @author (last) Sean Nash -* @date (last) 14-Dec-2022 +* @author (last) Dara Navaei +* @date (last) 18-Jan-2023 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -210,6 +210,7 @@ F32 getAlarmAudioPrimaryLowGainCurrent( void ); F32 getAlarmAudioBackupCurrent( void ); SELF_TEST_STATUS_T execAlarmAudioSelfTest( void ); +void resetAlarmAudioPOSTState( void ); BOOL testSetAlarmStateOverride( U32 alarmID, BOOL value ); BOOL testResetAlarmStateOverride( U32 alarmID );