Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -ra12f3ce494cd2a18aee31659c17d8a619fc70f7d -r87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision a12f3ce494cd2a18aee31659c17d8a619fc70f7d) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e) @@ -22,6 +22,7 @@ #include "Timers.h" #include "TubeSetInstall.h" #include "TxParams.h" +#include "StatePreTxRecirculate.h" /** * @addtogroup TDPreTreatmentMode @@ -124,7 +125,7 @@ break; case TD_PRE_TREATMENT_RECIRCULATE_STATE: - // currentPreTreatmentState = handleRecirculateState(); + currentPreTreatmentState = handleRecirculateState(); break; case TD_PRE_TREATMENT_CONFIRM_RX_STATE: @@ -269,16 +270,15 @@ * @brief * The handleRecirculateState function executes the Recirculate state of * pre-treatment mode. - * @details \b Inputs: TODO fill up if any - * @details \b Outputs: TODO fill up if any + * @details \b Inputs: none. + * @details \b Outputs: none. * @return next Pre-Treatment mode state. *************************************************************************/ static TD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ) { TD_PRE_TREATMENT_MODE_STATE_T state = TD_PRE_TREATMENT_RECIRCULATE_STATE; - // TODO: Transition to Confirm RX state on completion when implemented - // state = TD_PRE_TREATMENT_CONFIRM_RX_STATE; + execPreTxRecirculate(); return state; } @@ -379,6 +379,13 @@ // TODO add logic once we have pre-treatment mode developed break; + case ALARM_ACTION_RESUME: + if ( TD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ) + { + signalResumePreTxRecirculate(); + } + break; + default: // do not handle other actions in pre-treatment mode break; Index: firmware/App/Modes/StatePreTxRecirculate.c =================================================================== diff -u --- firmware/App/Modes/StatePreTxRecirculate.c (revision 0) +++ firmware/App/Modes/StatePreTxRecirculate.c (revision 87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e) @@ -0,0 +1,277 @@ +/************************************************************************** +* +* 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 StatePreTxRecirculate.c +* +* @author (last) Vijay Pamula +* @date (last) 02-June-2026 +* +* @author (original) Vijay Pamula +* @date (original) 06-June-2026 +* +***************************************************************************/ + +#include "TDCommon.h" +#include "DDInterface.h" +#include "AirPump.h" +#include "BloodFlow.h" +#include "Common.h" +#include "Ejector.h" +#include "Messaging.h" +#include "OperationModes.h" +#include "StatePreTxRecirculate.h" +#include "Switches.h" +#include "SyringePump.h" +#include "Timers.h" +#include "Valve3Way.h" +#include "Valves.h" + +/** + * @addtogroup StatePreTxRecirculate + * @{ + */ + +// ********** private definitions ********** + +#define PRE_TX_RECIRC_BLOOD_FLOW_RATE_ML_MIN 100 ///< Blood pump flow rate during recirculation in mL/min. +#define PRE_TX_RECIRC_DIALYSATE_FLOW_RATE_ML_MIN 250 ///< Dialysate flow rate during recirculation in mL/min. +#define RECIRC_MEDIUM_TIME_MS ( 90 * SEC_PER_MIN * MS_PER_SECOND ) ///< Pre-Treatment recirc time before medium priority warning in min. +#define RECIRC_HIGH_TIME_MS ( 120 * SEC_PER_MIN * MS_PER_SECOND ) ///< Pre-Treatment recirc time before high priority alarm in min. + +typedef enum PreTxRecirculate_States +{ + PRE_TX_RECIRCULATE_STATE = 0, + PRE_TX_RECIRCULATE_STOPPED_STATE, + NUM_OF_PRE_TX_RECIRCULATE_STATES +} PRE_TX_RECIRCULATE_STATE_T; + +// ********** private data ********** + +static PRE_TX_RECIRCULATE_STATE_T currentPreTxRecircState; ///< Current pre-treatment recirculation sub-state. +static BOOL recircResumeRequested; ///< Flag indicating resume recirculation was requested. + +static U32 preTxRecircStartTime; ///< Recirculation start time (ms timer count). +static BOOL recircMediumAlarmGiven; ///< Flag indicating medium recirculation alarm has been raised. +static BOOL recircHighAlarmGiven; ///< Flag indicating high recirculation alarm has been raised. + +// ********** private function prototypes ********** + +static void setupPreTxRecirculate( void ); + +static void resetPreTxRecircFlags( void ); +static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateState( void ); +static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateStoppedState( void ); + +/*********************************************************************//** + * @brief + * The initPreTxRecirculate function initializes the Pre-Treatment + * Recirculate state data. + * @details \b Inputs: none. + * @details \b Outputs: currentPreTxRecircState, + * recircResumeRequested, preTxRecircStartTime, + * recircMediumAlarmGiven, recircHighAlarmGiven. + * @return none. + *************************************************************************/ +void initPreTxRecirculate( void ) +{ + currentPreTxRecircState = PRE_TX_RECIRCULATE_STATE; + recircResumeRequested = FALSE; + preTxRecircStartTime = getMSTimerCount(); + recircMediumAlarmGiven = FALSE; + recircHighAlarmGiven = FALSE; +} + +/*********************************************************************//** + * @brief + * The transitionToPreTxRecirculate function transitions the software + * into pre-treatment recirculation. + * @details \b Inputs: none. + * @details \b Outputs: currentPreTxRecircState. + * @return none + *************************************************************************/ +void transitionToPreTxRecirculate( void ) +{ + initPreTxRecirculate(); + setupPreTxRecirculate(); + setCurrentSubState( (U32)currentPreTxRecircState ); +} + +/*********************************************************************//** + * @brief + * The execPreTxRecirculate function executes the Pre-Treatment + * Recirculate state machine. + * @details \b Inputs: currentPreTxRecircState, + * preTxRecircStartTime, recircMediumAlarmGiven, + * recircHighAlarmGiven, recircResumeRequested. + * @details \b Outputs: currentPreTxRecircState, + * recircMediumAlarmGiven, recircHighAlarmGiven, + * recircResumeRequested. + * @return none + *************************************************************************/ +void execPreTxRecirculate( void ) +{ + PRE_TX_RECIRCULATE_STATE_T priorSubState = currentPreTxRecircState; + if ( ( FALSE == recircHighAlarmGiven ) && + ( TRUE == didTimeout( preTxRecircStartTime, RECIRC_HIGH_TIME_MS ) ) ) + { + recircHighAlarmGiven = TRUE; + + clearAlarm( ALARM_ID_TD_PRIME_COMPLETED_MEDIUM ); + activateAlarmNoData( ALARM_ID_TD_PRIME_COMPLETED_HIGH ); + } + + switch ( currentPreTxRecircState ) + { + case PRE_TX_RECIRCULATE_STATE: + currentPreTxRecircState = handlePreTxRecirculateState(); + break; + + case PRE_TX_RECIRCULATE_STOPPED_STATE: + currentPreTxRecircState = handlePreTxRecirculateStoppedState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_PRE_TX_RECIRC_INVALID_STATE, currentPreTxRecircState ); + + break; + } + if ( priorSubState != currentPreTxRecircState ) + { + setCurrentSubState( (U32)currentPreTxRecircState ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, priorSubState, currentPreTxRecircState ); + } + + resetPreTxRecircFlags(); +} + +/*********************************************************************//** + * @brief + * The getPreTxRecirculateState function gets the current pre-treatment + * recirculation sub-state. + * @details \b Inputs: currentPreTxRecircState. + * @details \b Outputs: none. + * @return current pre-treatment recirculation sub-state. + *************************************************************************/ +U32 getPreTxRecirculateState( void ) +{ + return currentPreTxRecircState; +} + +/*********************************************************************//** + * @brief + * The signalResumePreTxRecirculate function signals a request to resume + * pre-treatment recirculation. + * @details \b Inputs: none. + * @details \b Outputs: recircResumeRequested. + * @return none + *************************************************************************/ +void signalResumePreTxRecirculate( void ) +{ + recircResumeRequested = TRUE; +} + +/*********************************************************************//** + * @brief + * The resetPreTxRecircFlags function resets recirculation request flags. + * @details \b Inputs: none. + * @details \b Outputs: recircResumeRequested. + * @return none + *************************************************************************/ +static void resetPreTxRecircFlags( void ) +{ + recircResumeRequested = FALSE; +} + +/*********************************************************************//** + * @brief + * The handlePreTxRecirculateState function handles the + * Recirculate sub-state. + * @details \b Inputs: preTxRecircStartTime, + * recircMediumAlarmGiven + * @details \b Outputs: recircMediumAlarmGiven + * @return next Recirculate sub-state + *************************************************************************/ +static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateState( void ) +{ + PRE_TX_RECIRCULATE_STATE_T state = PRE_TX_RECIRCULATE_STATE; + + if ( ( FALSE == recircMediumAlarmGiven ) && + ( TRUE == didTimeout( preTxRecircStartTime, RECIRC_MEDIUM_TIME_MS ) ) ) + { + recircMediumAlarmGiven = TRUE; + activateAlarmNoData( ALARM_ID_TD_PRIME_COMPLETED_MEDIUM ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + signalBloodPumpHardStop(); + state = PRE_TX_RECIRCULATE_STOPPED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTxRecirculateStoppedState function handles the + * Recirculate Stopped sub-state. + * @details \b Inputs: recircResumeRequested + * @details \b Outputs: recircResumeRequested + * @return next Recirculate sub-state + *************************************************************************/ +static PRE_TX_RECIRCULATE_STATE_T handlePreTxRecirculateStoppedState( void ) +{ + PRE_TX_RECIRCULATE_STATE_T state = PRE_TX_RECIRCULATE_STOPPED_STATE; + + if ( TRUE == recircResumeRequested ) + { + recircResumeRequested = FALSE; + setupPreTxRecirculate(); + state = PRE_TX_RECIRCULATE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The setupPreTxRecirculate function configures the actuators + * required for Pre-Treatment Recirculation. + * @details \b Inputs: none + * @details \b Outputs: none + * @return none + *************************************************************************/ +static void setupPreTxRecirculate( void ) +{ + doorClosedRequired( TRUE ); + + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + retractEjector(); + stopSyringePump(); + + setBloodPumpTargetFlowRate( PRE_TX_RECIRC_BLOOD_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + + // Direct DD to bypass dialyzer and perform no ultrafiltration + cmdBypassDialyzer( TRUE ); + cmdChangeQd( PRE_TX_RECIRC_DIALYSATE_FLOW_RATE_ML_MIN ); + cmdChangeQuf( 0.0F ); +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + +/**@}*/ + + Index: firmware/App/Modes/StatePreTxRecirculate.h =================================================================== diff -u --- firmware/App/Modes/StatePreTxRecirculate.h (revision 0) +++ firmware/App/Modes/StatePreTxRecirculate.h (revision 87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e) @@ -0,0 +1,48 @@ +/************************************************************************** +* +* 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 StatePreTxRecirculate.h +* +* @author (last) Vijay Pamula +* @date (last) 02-June-2026 +* +* @author (original) Vijay Pamula +* @date (original) 02-June-2026 +* +***************************************************************************/ + +#ifndef __STATE_PRE_TX_RECIRCULATE_H__ +#define __STATE_PRE_TX_RECIRCULATE_H__ + +#include "TDCommon.h" +#include "TDDefs.h" + +/** + * @defgroup StatePreTxRecirculate StatePreTxRecirculate + * @brief Pre-treatment recirculation state unit. This state runs the blood + * pump at a fixed recirculation flow rate with the arterial and venous pinch + * valves open, commands dialyzer bypass, and requests fixed dialysate flow + * while waiting to proceed from pre-treatment. + * + * @addtogroup StatePreTxRecirculate + * @{ + */ + +// ********** public definitions ********** + +// ********** public function prototypes ********** + +void initPreTxRecirculate( void ); // Initialize this unit +void transitionToPreTxRecirculate( void ); // Prepares for transition to pre-treatment recirculation state +void execPreTxRecirculate( void ); // Execute the pre-treatment recirculation state machine + +U32 getPreTxRecirculateState( void ); // Gets current pre-treatment recirculation state +void signalResumePreTxRecirculate( void ); // Signal resume request for pre-treatment recirculation + +/**@}*/ + +#endif Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r70f10c77f4f9a48d51030c00504d520fe25d0ba9 -r87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 70f10c77f4f9a48d51030c00504d520fe25d0ba9) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 87d4b0145a1f6a2ccf38e006e30dbf5dd854ed7e) @@ -196,6 +196,7 @@ SW_FAULT_ID_MODE_POST_TREATMENT_INVALID_STATE1 = 165, SW_FAULT_ID_MODE_POST_TX_AUTO_EJECT_INVALID_STATE = 166, SW_FAULT_ID_INVALID_MESSAGE_PAYLOAD_LENGTH = 167, + SW_FAULT_ID_PRE_TX_RECIRC_INVALID_STATE = 168, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T;