Index: firmware/App/Modes/StatePreTxDrySelfTests.c =================================================================== diff -u --- firmware/App/Modes/StatePreTxDrySelfTests.c (revision 0) +++ firmware/App/Modes/StatePreTxDrySelfTests.c (revision efdbfe0a1ee81f4a71cadd5bae98ef4543b6572d) @@ -0,0 +1,1496 @@ +/************************************************************************** +* +* Copyright (c) 2026-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file SelfTests.h +* +* @author (last) Varshini Nagabooshanam +* @date (last) 01-Apr-2026 +* +* @author (original) Varshini Nagabooshanam +* @date (original) 01-Apr-2026 +* +***************************************************************************/ + +#include "AirPump.h" +#include "AirTrap.h" +#include "BloodFlow.h" +#include "BloodFlow.h" +#include "Bubbles.h" +#include "DDInterface.h" +#include "FPGA.h" +#include "TxParams.h" +#include "Pressures.h" +#include "StatePreTxDrySelfTests.h" +#include "Switches.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup SelfTests + * @{ + */ + +// ********** private definitions ********** + +// Syringe pump +#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay before checking syringe pump occlusion after prime. + +// Pressure self-test timing +#define PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ( 5 * MS_PER_SECOND ) ///< Delay before capturing baseline arterial and venous pressures. +#define STABILTY_PRESSURE_SELF_TEST_TIME ( 5 * MS_PER_SECOND ) ///< Time allowed for pressure stabilization. +#define VENOUS_PRESSURE_LEAK_CHECK_TIME ( 4 * MS_PER_SECOND ) ///< Time to monitor venous pressure decay (leak check). +#define ARTERIAL_PRESSURE_LEAK_CHECK_TIME ( 4 * MS_PER_SECOND ) ///< Time to monitor arterial pressure decay (leak check). +#define CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Time required for pressure settling after cartridge insertion. + +//Pressure self-test pump flow +#define BLOOD_PUMP_PRESSURE_SELF_TEST_FLOW 100 ///< Blood pump flow rate during arterial pressure self-test (mL/min). + +// Pressure thresholds +#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -200.0F ///< Target arterial pressure threshold during pressure build. +#define VENOUS_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed venous pressure variation during stabilization. +#define ARTERIAL_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed arterial pressure variation during stabilization. +#define VENOUS_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed venous pressure difference during leak check. +#define ARTERIAL_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Max allowed arterial pressure difference during leak check. +#define VENOUS_RELIEF_PRESSURE_THRESHOLD_MMHG 20.0F ///< Venous pressure must return within this threshold after relief. +#define ARTERIAL_RELIEF_PRESSURE_THRESHOLD_MMHG 20.0F ///< Arterial pressure must return within this threshold after relief. + +// Pressure self-test timeout values +#define ARTERIAL_PRESSURE_SELF_TEST_MAX_TIME ( 30 * MS_PER_SECOND ) ///< Max time allowed to reach arterial pressure target. + +// General dry self-test timing +#define MAX_DRY_SELF_TEST_TIME ( 12 * SEC_PER_MIN ) ///< Maximum total dry self-test duration. +#define SELF_TEST_TIME_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND ) ///< Interval for publishing self-test progress data. + +/// Payload structure for response to validate from cloud +typedef struct +{ + U32 accepted; + U32 reason; +} TUBE_SET_AUTH_RESULT_PAYLOAD_T; + +// ********** private data ********** + +static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of Dry Self-Test state machine +static U32 pressureSelfTestPreNormalStartTime; ///< Pressure dry self-test pre-normal start time. +static U32 selfTestStartTime; ///< Timestamp when self-tests started +static U32 selfTestPreviousPublishDataTime; ///< Last time progress data was published +static U32 selfTestCartridgeSettleTime; ///< Delay timer after cartridge insertion +static U32 syringeOcclusionDelayStartTime; ///< Delay before checking syringe occlusion +static BOOL selfTestsResumeRequested; ///< Indicates resume request from STOPPED state +static BOOL doorStateAfterCartridgeInstall; ///< Tracks door transition post cartridge insertion +static BOOL dryPressureTestsCompleted; ///< Indicates pressure tests completion +static BOOL cartridgeUsedTestRun; ///< Indicates cartridge-used check executed +static BOOL occlusionBaselineWasSet; ///< Indicates baseline pressure established +static BOOL heparinOcclusionTestRun; ///< Indicates heparin occlusion test executed +static BOOL authResponseReceived; ///< Authentication response received from external subsystem +static BOOL authResponseValidTubeSet; ///< Indicates whether tube set is valid +static BOOL authResponseModalityAccepted; ///< Indicates whether tube set matches selected treatment modality +static BOOL requestInstallMode; ///< Triggers transition to INSTALL mode when authentication fails +static BOOL useHeparin; ///< Indicates whether heparin functionality is enabled for current treatment +static F32 previousNormalArterialPressure; ///< Arterial pressure at baseline +static F32 previousNormalVenousPressure; // Venous pressure at baseline +static F32 peakVenousPressure; // Peak venous pressure during stabilization +static F32 venousPressureP1; // First stable venous pressure sample +static F32 venousPressureP2; // Second venous pressure sample for leak check +static F32 peakArterialPressure; // Peak arterial pressure during stabilization +static F32 arterialPressureP1; // First stable arterial pressure sample +static F32 arterialPressureP2; // Second arterial pressure sample for leak check +static BOOL arterialPressureTargetReached; // Indicates whether arterial pressure target has been reached +static U32 venousPressureStabilizationStartTime; // Start time for venous stabilization phase +static U32 venousPressureLeakCheckStartTime; // Start time for venous leak check +static U32 venousPressureReliefStartTime; // Start time for venous pressure relief +static U32 pressureSelfTestBloodPumpRunStartTime; // Blood pump run start for pressure test +static U32 pressureSelfTestNormalizedStartTime; // Time when pressures normalized +static U32 pressureSelfTestArterialStartTime; // Start time for arterial pressure build-up +static U32 arterialPressureStabilizationStartTime; // Start time for arterial stabilization +static U32 arterialPressureLeakCheckStartTime; // Start time for arterial leak check +static U32 arterialPressureReliefStartTime; // Start time for arterial pressure relief + +// ********** private function prototypes ********** + +static void resetSelfTestsFlags( void ); +static void setupForSelfTestsStop( void ); +static void setAlarmResumePerDoorAndLatch( 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 handleDrySelfTestCartridgeLoadedCheckState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpSeekState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsVenousState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialSetupState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsArterialState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsDecayState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsStabilityState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ) +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); + +static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ); + +/*********************************************************************//** + * @brief + * The initSelfTests function initializes the SelfTests module. + * @details Inputs: none + * @details Outputs: SelfTests module initialized. + * @return none + *************************************************************************/ +void initSelfTests( void ) +{ + selfTestStartTime = 0; + selfTestPreviousPublishDataTime = 0; + syringeOcclusionDelayStartTime = 0; + doorStateAfterCartridgeInstall = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalResumeSelfTests function signals the self-tests to resume + * previous operation. + * @details Inputs: none + * @details Outputs: primeResumeRequested + * @return none + *************************************************************************/ +void signalResumeSelfTests( void ) +{ + selfTestsResumeRequested = TRUE; +} + +/*********************************************************************//** + * @brief + * The resetSelfTestsFlags function resets all self-tests signal flags. + * @details Inputs: none + * @details Outputs: signal flags set to FALSE + * @return none + *************************************************************************/ +static void resetSelfTestsFlags( void ) +{ + selfTestsResumeRequested = FALSE; +} + +/*********************************************************************//** + * @brief + * The setupForSelfTestsStop function sets actuators appropriately for self-tests + * states. + * @details Inputs: dryPressureTestsCompleted, PreTreatmentSubState + * @details Outputs: All pumps stopped + * @return none + *************************************************************************/ +static void setupForSelfTestsStop( void ) +{ + signalBloodPumpHardStop(); + +// if ( TRUE == isAlarmActive( ALARM_ID_TD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM ) ) +// { +// retractSyringePump(); +// } +// else +// { + // stopSyringePump(); +// } + + setValvePosition( H13_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H20_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + + // If the TD has finished no cart s.t. but not dry pressure tests, Open to vent pressure + // to prevent air going to the Saline bag. + if ( ( TD_PRE_TREATMENT_SELF_TEST_DRY_STATE == getPreTreatmentSubState() ) && ( FALSE == dryPressureTestsCompleted ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValveAirTrap( STATE_OPEN ); + } + + else + { + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValveAirTrap( STATE_CLOSED ); + } +} + +/*********************************************************************//** +* @brief +* The setAlarmResumePerDoorAndLatch function enables resume only when +* required conditions are satisfied. +* @details \b Inputs: Front door switch state +* @details \b Outputs: resume alarm enabled/disabled +* @return none +*************************************************************************/ +static void setAlarmResumePerDoorAndLatch( void ) +{ + BOOL doorClosed = FALSE; + doorClosed = ( STATE_CLOSED == getSwitchState( H9_SWCH ) ); + + if ( TRUE == doorClosed ) + { + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + } + else + { + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The transitionToDrySelfTests function resets anything required before + * the start of dry self-tests. + * @details Inputs: front door state + * @details Outputs: Dry self-tests re-initialized, changed depending + * on front door state + * @return none + *************************************************************************/ +void transitionToDrySelfTests( void ) +{ + // State Reset + currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; + pressureSelfTestBloodPumpRunStartTime = 0; + pressureSelfTestNormalizedStartTime = 0; + previousNormalArterialPressure = 0.0F; + previousNormalVenousPressure = 0.0F; + dryPressureTestsCompleted = FALSE; + cartridgeUsedTestRun = FALSE; + occlusionBaselineWasSet = FALSE; + heparinOcclusionTestRun = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); + selfTestCartridgeSettleTime = getMSTimerCount(); + doorClosedRequired( TRUE ); + setCurrentSubState( (U32)currentDrySelfTestsState ); + + signalBloodPumpHardStop(); +// stopSyringePump(); + + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + + if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + } + else + { + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + } + + resetSelfTestsFlags(); +} + +/*********************************************************************//** + * @brief + * The execDrySelfTests function executes the dry self-tests state machine. + * @details Inputs: currentDrySelfTestsState + * @details Outputs: currentDrySelfTestsState, pressureSelfTestPreNormalStartTime + * @return none + *************************************************************************/ +void execDrySelfTests( void ) +{ + DRY_SELF_TESTS_STATE_T priorSubState = currentDrySelfTestsState; + + switch ( currentDrySelfTestsState ) + { + case DRY_SELF_TESTS_START_STATE: + currentDrySelfTestsState = handleDrySelfTestStartState(); + break; + + case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: + currentDrySelfTestsState = handleDrySelfTestWaitForDoorCloseState(); + break; + + case DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestUsedCartridgeCheckState(); + break; + + case DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestCartridgeLoadedCheckState(); + break; + + case DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE: + currentDrySelfTestsState = handleDrySelfTestTubeSetAuthenticationState(); + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpSeekState(); + break; + + case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureSensorNormalSetupState(); + break; + + case DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureVenousSetupState(); + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE: + currentDrySelfTestsState = handleDrySelfTestVenousPressureStabilizationState(); + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestVenousPressureLeakCheckState(); + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE: + currentDrySelfTestsState = handleDrySelfTestVenousPressureReliefState(); + break; + + case DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE: + currentDrySelfTestsState = handleDrySelfTestPressureArterialSetupState(); + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE: + currentDrySelfTestsState = handleDrySelfTestArterialPressureStabilizationState(); + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestArterialPressureLeakCheckState(); + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE: + currentDrySelfTestsState = handleDrySelfTestArterialPressureReliefState(); + break; + + case DRY_SELF_TESTS_SYRINGE_PRIME_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpOcclusionCheckState(); + break; + + case DRY_SELF_TESTS_COMPLETE_STATE: + currentDrySelfTestsState = handleDrySelfTestCompleteState(); + break; + + case DRY_SELF_TESTS_STOPPED_STATE: + currentDrySelfTestsState = handleDrySelfTestStoppedState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_NO_CARTRIDGE_SELF_TEST_STATE, currentDrySelfTestsState ); + break; + } + + // Self-tests flags should be handled by now, reset if flags not handled with current state + resetSelfTestsFlags(); + + if ( priorSubState != currentDrySelfTestsState ) + { + setCurrentSubState( (U32)currentDrySelfTestsState ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDrySelfTestsState ); + } + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) + { + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + SELF_TEST_DRY_PAYLOAD_T data; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + + data.timeout = MAX_DRY_SELF_TEST_TIME; + data.countdown = ( elapsedSelfTestTimeInSecs <= MAX_DRY_SELF_TEST_TIME ? ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) : 0 ); + broadcastData( MSG_ID_TD_NO_CART_SELF_TEST_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_DRY_PAYLOAD_T ) ); + } +} + +/*********************************************************************//** + * @brief + * The getDrySelfTestsState function returns the current state of dry self-tests sub-mode. + * @details Inputs: currentDrySelfTestsState + * @details Outputs: none + * @return current dry self-tests state + *************************************************************************/ +U32 getDrySelfTestsState( void ) +{ + return (U32)currentDrySelfTestsState; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestStartState function makes sure door is + * closed before starting self-tests. + * @details \b Inputs: none + * @details \b 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 frontDoorSwitch = getSwitchState( H9_SWCH ); + + // Want to pinch off saline once door closed after cartridge install + handleDoorCloseAfterCartridgeInsertion(); + + if ( STATE_CLOSED == frontDoorSwitch ) + { + // 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 ) ) + { + doorClosedRequired( TRUE ); + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } + } + + 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 \b Inputs: none +* @details \b Outputs: selfTestStartTime +* @return the next state of dry self-tests state machine +*************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + OPN_CLS_STATE_T frontDoorSwitch = getSwitchState( H9_SWCH ); + + // Restart self-test start time + selfTestStartTime = getMSTimerCount(); + + if ( STATE_CLOSED == frontDoorSwitch ) + { + state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** +* @brief +* Verifies that the installed cartridge is unused (dry) by checking +* bubble detectors and air trap levels. +* @details \b Inputs: none +* @details \b Outputs: cartridgeUsedTestRun +* @return the next state of dry self-tests state machine +*************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + BUBBLE_STATE_T bubbleStatus = getBubbleDetectedState( H18_BBLD ); + AIR_TRAP_LEVELS_T lowerAirTrap = getLevelSensorState( H17_LEVL ); + AIR_TRAP_LEVELS_T upperAirTrap = getLevelSensorState( H16_LEVL ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_DRY_SELF_TEST_CARTRIDGE_RESULT, (U32)bubbleStatus, (U32)BUBBLE_DETECTED ); + + // Check if cartridge is dry + if ( ( BUBBLE_DETECTED == bubbleStatus ) && + ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && + ( AIR_TRAP_LEVEL_AIR == upperAirTrap ) ) + { + // If catridge is valid it proceed + resetArtVenPressureOffsets(); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_REQUEST_BARCODE_SCAN ); + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else + { + // Allow wet cartridge only for test configuration + if ( TRUE == getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) ) + { + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_REQUEST_BARCODE_SCAN ); + cartridgeUsedTestRun = TRUE; + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else + { + // If cartridge is invalid it triggers an alarm + activateAlarmNoData( ALARM_ID_TD_INSTALL_NEW_BLOOD_TUBING_SET ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** +* @brief +* Verifies that a cartridge is installed and barcode scan is successful. +* @details \b Inputs: barcode scan status +* @details \b Outputs: none +* @return the next state of dry self-tests state machine +*************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestCartridgeLoadedCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + BOOL barcodeScanComplete = isBarcodeScanComplete(); + BOOL barcodeScanSuccess = didBarcodeScanSucceed(); + + if ( TRUE == barcodeScanComplete ) + { + if ( TRUE == barcodeScanSuccess ) + { + // If Barcode is valid proceed to authentication + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_BARCODE_SCAN_SUCCESS ); + state = DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE; + } + else + { + // If barcode is valid it trigger an alarm + activateAlarmNoData( ALARM_ID_TD_INSTALL_NEW_CARTRIDGE ); + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + if ( TRUE == isAlarmActive( ALARM_ID_TD_NO_CARTRIDGE_LOADED ) ) + { + // Reset baseline after reinstall + occlusionBaselineWasSet = FALSE; + } + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** +* @brief +* The handleDrySelfTestTubeSetAuthenticationState function handles tube set +* authentication and processes the authentication response. +* +* @details \b Message \b Sent: MSG_ID_TD_TUBE_SET_AUTH_RESULT +* @details Inputs: authResponseReceived, authResponseValidTubeSet, +* authResponseModalityAccepted +* @details Outputs: none +* @return the next state of dry self-tests state machine +*************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestTubeSetAuthenticationState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE; + BOOL authInvalid = TRUE; + BOOL tubeSetIsValid = FALSE; + BOOL modalityIsValid = FALSE; + TUBE_SET_AUTH_RESULT_PAYLOAD_T payload; + + //Initialize Payload + memset( (U08*)&payload, 0, sizeof( TUBE_SET_AUTH_RESULT_PAYLOAD_T ) ); + + // Check Response + if ( TRUE == authResponseReceived ) + { + authResponseReceived = FALSE; + tubeSetIsValid = authResponseValidTubeSet; + modalityIsValid = authResponseModalityAccepted; +/ if ( TRUE == tubeSetIsValid ) + { + if ( TRUE == modalityIsValid ) + { + authInvalid = FALSE; + } + } + // Result Handling + if ( FALSE == authInvalid ) + { + // Valid + modality match + payload.accepted = (U32)TRUE; + payload.reason = (U32)AUTH_REASON_NONE; +// requestSyringeSeek(); + state = DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE; + } + else + { + payload.accepted = (U32)FALSE; + if ( FALSE == tubeSetIsValid ) + { + // Invalid tube set + activateAlarmNoData( ALARM_ID_TD_INVALID_TUBE_SET ); + payload.reason = (U32)AUTH_REASON_INVALID; + } + else + { + // Modality mismatch + payload.reason = (U32)AUTH_REASON_MODALITY_MISMATCH; + } + requestInstallMode = TRUE; + } + + sendMessage( MSG_ID_TD_TUBE_SET_AUTHENTICATION_RESPONSE, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&payload, sizeof( TUBE_SET_AUTH_RESULT_PAYLOAD_T ) ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpSeekState function handles the syringe + * pump seek dry self-test state. + * @details Inputs: useHeparin + * @details Outputs: pressureSelfTestPreNormalStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpSeekState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE; + BOOL done = FALSE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { // using Heparin? + if ( TRUE == useHeparin ) +// { // syringe pump is not busy? +// if ( FALSE == isSyringePumpRunning() ) +// { // seek completed? +// if ( TRUE == isSyringePlungerFound() ) +// { // move on when seek completed +// done = TRUE; +// } +// else +// { // pre-load completed? +// if ( TRUE == isSyringePumpPreLoaded() ) +// { // initiate seek plunger operation +// seekSyringePlunger(); +// } +// else +// { // pre-load syringe +// preloadSyringePlunger(); +// } +// } +// } +// } +// else +// { // not using Heparin, so move on +// done = TRUE; +// } +// } +// } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureSensorsSetupState function handles the setup + * for pressure sensors dry self-test. + * @details Inputs: pressureSelfTestPreNormalStartTime + * @details Outputs: previousNormalArterialPressure, previousNormalVenousPressure + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorNormalSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + // wait for pressure to equalize w/ atmosphere and tare arterial and venous pressures + if ( TRUE == didTimeout( pressureSelfTestPreNormalStartTime, PRE_NORMAL_PRESSURE_SELF_TEST_DELAY_MS ) ) + { + setArtVenPressureOffsets(); + state = DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE; + } + } + + return state; +} + +/*********************************************************************//** +* @brief +* The handleDrySelfTestPressureVenousSetupState function handles the setup +* for the venous pressure sensor dry self-test. +* @details Inputs: none +* @details Outputs: pressureSelfTestVenousTestStartTime +* @return the next state of dry self-tests state machine +*************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureVenousSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + venousPressureStabilizationStartTime = getMSTimerCount(); + peakVenousPressure = getFilteredVenousPressure(); + state = DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestVenousPressureStabilizationState function handles + * venous pressure stabilization check. + * @details Inputs: venousPressureStabilizationStartTime, peakVenousPressure + * @details Outputs: venousPressureP1 + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureStabilizationState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else if ( TRUE == didTimeout( venousPressureStabilizationStartTime, STABILTY_PRESSURE_SELF_TEST_TIME ) ) + { + F32 current = getFilteredVenousPressure(); + F32 diff = fabs( peakVenousPressure - current ); + + if ( diff < VENOUS_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ) + { + venousPressureP1 = current; + venousPressureLeakCheckStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, diff, VENOUS_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestVenousPressureLeakCheckState function handles + * venous pressure leak check. + * @details Inputs: venousPressureLeakCheckStartTime, venousPressureP1 + * @details Outputs: venousPressureP2 + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureLeakCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else if ( TRUE == didTimeout( venousPressureLeakCheckStartTime, VENOUS_PRESSURE_LEAK_CHECK_TIME ) ) + { + venousPressureP2 = getFilteredVenousPressure(); + F32 diff = fabs( venousPressureP1 - venousPressureP2 ); + + if ( diff <= VENOUS_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG ) + { + venousPressureReliefStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, diff, VENOUS_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestVenousPressureReliefState function handles + * venous pressure relief state. + * @details Inputs: venousPressureReliefStartTime + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestVenousPressureReliefState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else if ( TRUE == didTimeout( venousPressureReliefStartTime, STABILTY_PRESSURE_SELF_TEST_TIME ) ) + { + F32 current = getFilteredVenousPressure(); + + if ( current <= VENOUS_RELIEF_PRESSURE_THRESHOLD_MMHG ) + { + state = DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE; + } + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, current ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestPressureArterialSetupState function handles the setup + * for the arterial pressure sensor dry self-test. + * @details Inputs: none + * @details Outputs: pressureSelfTestArterialStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureArterialSetupState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + pressureSelfTestArterialStartTime = getMSTimerCount(); + arterialPressureTargetReached = FALSE; + state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestArterialPressureStabilizationState function monitors + * arterial pressure, verifies target pressure is reached, and records P1 + * after stabilization. + * @details Inputs: pressureSelfTestArterialStartTime, + * arterialPressureStabilizationStartTime + * @details Outputs: peakArterialPressure, arterialPressureP1, + * arterialPressureLeakCheckStartTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureStabilizationState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE; + F32 arterialPressure = getFilteredArterialPressure(); + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + arterialPressureTargetReached = FALSE; + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else + { + // Once reached to target + if ( FALSE == arterialPressureTargetReached ) + { + if ( arterialPressure <= ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG ) + { + peakArterialPressure = arterialPressure; + arterialPressureStabilizationStartTime = getMSTimerCount(); + arterialPressureTargetReached = TRUE; + } + if ( TRUE == didTimeout( pressureSelfTestArterialStartTime, ARTERIAL_PRESSURE_SELF_TEST_MAX_TIME ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, arterialPressure, ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + // Stability Check P1 + else + { + if ( TRUE == didTimeout( arterialPressureStabilizationStartTime, STABILTY_PRESSURE_SELF_TEST_TIME ) ) + { + F32 diff = fabs( peakArterialPressure - arterialPressure ); + if ( diff < ARTERIAL_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ) + { + arterialPressureP1 = arterialPressure; + arterialPressureLeakCheckStartTime = getMSTimerCount(); + arterialPressureTargetReached = FALSE; + state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, diff, ARTERIAL_STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG ); + arterialPressureTargetReached = FALSE; + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestArterialPressureLeakCheckState function verifies + * arterial pressure leak by comparing P1 and P2. + * @details Inputs: arterialPressureLeakCheckStartTime, arterialPressureP1 + * @details Outputs: arterialPressureP2 + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureLeakCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else if ( TRUE == didTimeout( arterialPressureLeakCheckStartTime, ARTERIAL_PRESSURE_LEAK_CHECK_TIME ) ) + { + arterialPressureP2 = getFilteredArterialPressure(); + F32 diff = fabs( arterialPressureP1 - arterialPressureP2 ); + + if ( diff <= ARTERIAL_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG ) + { + arterialPressureReliefStartTime = getMSTimerCount(); + state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, diff, ARTERIAL_LEAK_PRESSURE_DIFF_TOLERANCE_MMHG ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestArterialPressureReliefState function relieves + * arterial pressure and verifies return to baseline. + * @details Inputs: arterialPressureReliefStartTime + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestArterialPressureReliefState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + else if ( TRUE == didTimeout( arterialPressureReliefStartTime, STABILTY_PRESSURE_SELF_TEST_TIME ) ) + { + F32 pressure = getFilteredArterialPressure(); + + if ( fabs( pressure ) <= ARTERIAL_RELIEF_PRESSURE_THRESHOLD_MMHG ) + { + state = DRY_SELF_TESTS_SYRINGE_PRIME_STATE; + } + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_PRE_TREATMENT_DRY_PRESSURE_TEST_FAILURE, pressure ); + state = DRY_SELF_TESTS_STOPPED_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpPrimeState function handles the prime + * operation for syringe pump. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PRIME_STATE; + +// if ( TRUE == useHeparin ) +// { +// if ( FALSE == isSyringePumpRunning() ) +// { +// if ( TRUE == isSyringePlungerFound() ) +// { +// if ( TRUE == isSyringePumpPrimed() ) +// { +// state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; +// syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 3 seconds has elapsed +// } +// else +// { +// primeSyringePump(); +// } +// } +// else +// { +// if ( TRUE == isSyringePumpPreLoaded() ) +// { +// seekSyringePlunger(); +// } +// else +// { +// preloadSyringePlunger(); +// } +// } +// } +// } +// else +// { +// state = DRY_SELF_TESTS_COMPLETE_STATE; +// } +// +// if ( TRUE == doesAlarmStatusIndicateStop() ) +// { +// state = DRY_SELF_TESTS_STOPPED_STATE; +// setupForSelfTestsStop(); +// } + + return state; +//} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpOcclusionDetectionState function handles + * occlusion detection after prime has completed. + * @details Inputs: syringeOcclusionDelayStartTime + * @details Outputs: heparinOcclusionTestRun + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_CHECK_STATE; + + if ( TRUE == didTimeout( syringeOcclusionDelayStartTime, SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ) ) + { + if ( FALSE == checkForSyringeOcclusion( FALSE ) ) // transition to complete state only when occlusion is removed + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + heparinOcclusionTestRun = TRUE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = DRY_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestStoppedState function handles the stopped dry self-tests + * operation. + * @details Inputs: selfTestsResumeRequested, occlusionBaselineWasSet, + * dryPressureTestsCompleted, cartridgeUsedTestRun, heparinOcclusionTestRun + * @details Outputs: selfTestsResumeRequested, selfTestStartTime, selfTestCartridgeSettleTime + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_STOPPED_STATE; + + + if ( TRUE == isAlarmActive( ALARM_ID_TD_SYRINGE_PUMP_OCCLUSION ) ) + { + checkForSyringeOcclusion( FALSE ); + } + + if ( TRUE == selfTestsResumeRequested ) + { + selfTestsResumeRequested = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestCartridgeSettleTime = getMSTimerCount(); + + if ( TRUE == heparinOcclusionTestRun ) + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + else if ( TRUE == dryPressureTestsCompleted ) + { + state = DRY_SELF_TESTS_SYRINGE_PRIME_STATE; + } + else if ( TRUE == cartridgeUsedTestRun ) + { + state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; + } + else if ( FALSE == occlusionBaselineWasSet ) + { + state = DRY_SELF_TESTS_START_STATE; + } + else + { + state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + } + } + + return state; +} + +/*********************************************************************//** +* @brief +* The transitionToDrySelfTestsState function handles the transition to +* dry self-test states by setting actuators. +* +* @details Inputs: none +* @details Outputs: none +* @param newState the targeted dry self-test state +* @return none +*************************************************************************/ +static void transitionToDrySelfTestsState( DRY_SELF_TESTS_STATE_T newState ) +{ + switch ( newState ) + { + case DRY_SELF_TESTS_START_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_TUBE_SET_AUTHENTICATION_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_SEEK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_PRESSURE_SENSOR_NORMAL_SETUP_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_PRESSURE_VENOUS_SETUP_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + startAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_STABILIZATION_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_LEAK_CHECK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_VENOUS_PRESSURE_RELIEF_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_PRESSURE_ARTERIAL_SETUP_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + setBloodPumpTargetFlowRate( BLOOD_PUMP_PRESSURE_SELF_TEST_FLOW, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_STABILIZATION_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_LEAK_CHECK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_ARTERIAL_PRESSURE_RELIEF_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_SYRINGE_PRIME_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_CHECK_STATE: + { + U32 targetDialysateFlowMLPM = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + endAirTrapControl(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + retractEjector(); + cmdBypassDialyzer( TRUE ); + cmdChangeQd( targetDialysateFlowMLPM ); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_COMPLETE_STATE: + { + signalBloodPumpHardStop(); + endAirTrapControl(); + cmdChangeQuf( 0.0F ); + } + break; + + case DRY_SELF_TESTS_STOPPED_STATE: + { + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setAlarmResumePerDoorAndLatch(); + doorClosedRequired( FALSE ); + } + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_STATE, (U32)newState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handleDoorCloseAfterCartridgeInsertion function handles the check + * for door close after cartridge install so that saline line can be pinched. + * @details Inputs: door states + * @details Outputs: doorStateAfterCartridgeInstall + * @return none + *************************************************************************/ +void handleDoorCloseAfterCartridgeInsertion( void ) +{ + OPN_CLS_STATE_T frontDoorSwitch = getSwitchState( H9_SWCH ); + + if ( STATE_OPEN == frontDoorSwitch ) + { + doorStateAfterCartridgeInstall = FALSE; + } + if ( ( STATE_CLOSED == frontDoorSwitch ) && ( FALSE == doorStateAfterCartridgeInstall ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + doorStateAfterCartridgeInstall = TRUE; + } +} + +/**@}*/ Index: firmware/App/Modes/StatePreTxDrySelfTests.h =================================================================== diff -u --- firmware/App/Modes/StatePreTxDrySelfTests.h (revision 0) +++ firmware/App/Modes/StatePreTxDrySelfTests.h (revision efdbfe0a1ee81f4a71cadd5bae98ef4543b6572d) @@ -0,0 +1,64 @@ +/************************************************************************** +* +* Copyright (c) 2026-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file SelfTests.h +* +* @author (last) Varshini Nagabooshanam +* @date (last) 01-Apr-2026 +* +* @author (original) Varshini Nagabooshanam +* @date (original) 01-Apr-2026 +* +***************************************************************************/ + +#ifndef __SELF_TESTS_H__ +#define __SELF_TESTS_H__ + +#include "TDCommon.h" +#include "TDDefs.h" + +/** + * @defgroup SelfTests + * @brief SelfTests module. This module handles self-tests execution for pre-treatment mode. + * + * @addtogroup SelfTests + * @{ + */ + +// ********** public definitions ********** + +/// Payload record structure for no cartridge self-test data broadcast message +typedef struct +{ + U32 timeout; ///< No cartridge self-test timeout (in seconds) + U32 countdown; ///< No cartridge self-test timeout countdown (in seconds) +} SELF_TEST_NO_CARTRIDGE_PAYLOAD_T; + +/// Payload record structure for dry self-test data broadcast message +typedef struct +{ + U32 timeout; ///< Dry self-test timeout (in seconds) + U32 countdown; ///< Dry self-test timeout countdown (in seconds) +} SELF_TEST_DRY_PAYLOAD_T; + +/// Payload record structure for no cartridge self-test data broadcast message +typedef enum AuthRejectReasons +{ + AUTH_REASON_NONE = 0, ///< No rejection reason + AUTH_REASON_INVALID, ///< Invalid tube set + AUTH_REASON_MODALITY_MISMATCH, ///< Modality mismatch + NUM_OF_AUTH_REJECT_REASONS ///< Number of auth reject reasons +} AUTH_REJECT_REASON_T; + +// ********** public function prototypes ********** +void initSelfTests( void ); +void execDrySelfTests( void ); +void transitionToDrySelfTests( void ); + +/**@}*/ + +#endif