Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -rcfa825a18b02440d9be8b0da68980a669ac42682 -rea4df318f602d13eb9494e62331bbc1067a1afe7 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision cfa825a18b02440d9be8b0da68980a669ac42682) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision ea4df318f602d13eb9494e62331bbc1067a1afe7) @@ -8,7 +8,7 @@ * @file ModePreTreat.c * * @author (last) Vijay Pamula -* @date (last) 14-Jul-2026 +* @date (last) 31-Jul-2026 * * @author (original) Dara Navaei * @date (original) 25-Sep-2025 @@ -20,11 +20,13 @@ #include "BloodFlow.h" #include "Buttons.h" #include "DDInterface.h" +#include "Messaging.h" #include "ModePreTreat.h" #include "OperationModes.h" #include "StatePreTxHeparinSetup.h" #include "StatePreTxRecirculate.h" #include "SyringePump.h" +#include "TaskGeneral.h" #include "Timers.h" #include "TubeSetInstall.h" #include "TxParams.h" @@ -36,12 +38,23 @@ * @{ */ +// ********** private definitions ********** + +/// Interval (ms/task time) at which the Pre-Treatment state data is published on the CAN bus. +#define PRE_TREATMENT_STATE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +/// Initial offset used to stagger the Pre-Treatment state data broadcast. +#define PRE_TREATMENT_STATE_DATA_PUB_INITIAL_OFFSET 5U + // ********** private data ********** static TD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current Pre-Treatment sub-state static BOOL goToInstallStateRequested; ///< Flag indicating a request to transition to Install state. static BOOL continueFromRecirculateRequested; ///< Flag indicating a request to transition to Confirm Rx state. static BOOL continueFromHeparinSetupRequested; ///< Flag indicating a request to transition to Patient Connection state. +static BOOL treatmentStartRequested; ///< Flag indicating the UI requested treatment start. +static U32 preTreatmentStateBroadcastTimerCtr; ///< Pre-Treatment state data broadcast timer counter. +static OVERRIDE_U32_T preTreatmentStatePublishInterval; ///< Pre-Treatment state data publication interval override. // ********** private function prototypes ********** @@ -53,6 +66,7 @@ static TD_PRE_TREATMENT_MODE_STATE_T handleRxState( void ); ///< Handle Confirm Rx state during Pre-Treatment static TD_PRE_TREATMENT_MODE_STATE_T handleHeparinSetupState( void ); ///< Handle Heparin Setup state during Pre-Treatment. static TD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); ///< Handle Patient Connection state during Pre-Treatment +static void publishPreTreatmentStates( void ); ///< Publish Pre-Treatment states to the UI. /*********************************************************************//** * @brief @@ -72,6 +86,16 @@ goToInstallStateRequested = FALSE; continueFromRecirculateRequested = FALSE; continueFromHeparinSetupRequested = FALSE; + treatmentStartRequested = FALSE; + preTreatmentStateBroadcastTimerCtr = PRE_TREATMENT_STATE_DATA_PUB_INITIAL_OFFSET; + + preTreatmentStatePublishInterval = (OVERRIDE_U32_T) + { + PRE_TREATMENT_STATE_DATA_PUB_INTERVAL, + PRE_TREATMENT_STATE_DATA_PUB_INTERVAL, + PRE_TREATMENT_STATE_DATA_PUB_INTERVAL, + 0 + }; } /*********************************************************************//** @@ -146,11 +170,13 @@ break; case TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: - // currentPreTreatmentState = handlePatientConnectionState(); + currentPreTreatmentState = handlePatientConnectionState(); break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, + SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, + (U32)currentPreTreatmentState ); break; } @@ -159,6 +185,8 @@ setPreTreatStateTransition(); } + publishPreTreatmentStates(); + return (U32)currentPreTreatmentState; } @@ -205,11 +233,23 @@ break; case TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: - // TODO: actuator configuration + signalBloodPumpHardStop(); + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + stopSyringePump(); + + // TODO: Set H5 ejector Off. + // TODO: Command DD to bypass dialyzer, set QDt to prescribed rate, + // Quf to 0, and Qs to 0. break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, + SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, + (U32)currentPreTreatmentState ); break; } } @@ -232,7 +272,7 @@ if ( TRUE == isTubeSetInstallComplete() ) { - state = TD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + state = TD_PRE_TREATMENT_SELF_TEST_DRY_STATE ; } return state; @@ -298,12 +338,7 @@ if ( TRUE == continueFromRecirculateRequested ) { continueFromRecirculateRequested = FALSE; - - // TODO: Change to TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE - // when Patient Connection state is implemented. - // state = TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; - - requestNewOperationMode( MODE_TREA ); + state = TD_PRE_TREATMENT_CONFIRM_RX_STATE; } return state; @@ -386,19 +421,22 @@ /*********************************************************************//** * @brief * The handlePatientConnectionState function executes the Patient - * Connection state of pre-treatment mode. - * @details \b Inputs: TODO fill up if any - * @details \b Outputs: TODO fill up if any - * @return next Pre-Treatment mode state. + * Connection pre-treatment step. + * @details \b Inputs: treatmentStartRequested. + * @details \b Outputs: Requests transition to Treatment Mode when the + * UI Start Treatment request is received. + * @return current Pre-Treatment mode state. *************************************************************************/ static TD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) { TD_PRE_TREATMENT_MODE_STATE_T state = TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; - // TODO : after implementing this state, place the transition in the right place + if ( TRUE == treatmentStartRequested ) + { + treatmentStartRequested = FALSE; + requestNewOperationMode( MODE_TREA ); + } - //requestNewOperationMode( MODE_TREA ); - return state; } @@ -418,7 +456,7 @@ /*********************************************************************//** * @brief * The PreTxRequestContinueFromRecirculate function signals a request to - * transition the Pre-Treatment mode state machine to Patient Connection state. + * transition the Pre-Treatment mode state machine to Confirm Rx state. * @details \b Inputs: none * @details \b Outputs: continueFromRecirculateRequested * @return none @@ -442,6 +480,68 @@ } /*********************************************************************//** +* @brief +* The handleStartTreatmentRequest function handles the UI request to +* start treatment. +* @details \b Message \b Received: MSG_ID_UI_START_TREATMENT_REQUEST. +* @details \b Message \b Sent: MSG_ID_TD_START_TREATMENT_RESPONSE. +* @details \b Inputs: current operation mode and Pre-Treatment state. +* @details \b Outputs: treatmentStartRequested. +* @param message Pointer to the received Start Treatment request message. +* @return TRUE if the request was accepted, otherwise FALSE. +*************************************************************************/ +BOOL handleStartTreatmentRequest( MESSAGE_T *message ) +{ + TD_OP_MODE_T mode = getCurrentOperationMode(); + TD_PRE_TREATMENT_MODE_STATE_T preTxState = currentPreTreatmentState; + U32 payloadLen = message->hdr.payloadLen; + BOOL accepted = FALSE; + UI_RESPONSE_PAYLOAD_T response; + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; + + if ( ( 0U == payloadLen ) && ( MODE_PRET == mode ) && + ( TD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == preTxState ) ) + + { + treatmentStartRequested = TRUE; + accepted = TRUE; + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + } + + sendMessage( MSG_ID_TD_START_TREATMENT_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, + (U08 *)&response, sizeof( UI_RESPONSE_PAYLOAD_T ) ); + + return accepted; +} + +/*********************************************************************//** +* @brief +* The signalPreTreatmentBackoutToStandby function handles a request to +* back out of Pre-Treatment to Standby. +* @details \b Inputs: current operation mode, currentPreTreatmentState, +* and Tube Set Install state. +* @details \b Outputs: Requests Standby Mode when backout is allowed. +* @return TRUE if the request is accepted, otherwise FALSE. +*************************************************************************/ +BOOL signalPreTreatmentBackoutToStandby( void ) +{ + BOOL accepted = FALSE; + + if ( ( MODE_PRET == getCurrentOperationMode() ) && + ( TD_PRE_TREATMENT_TUBING_SET_INSTALL_STATE == currentPreTreatmentState ) && + ( TRUE == isTubeSetInstallAwaitingConfirmation() ) ) + { + requestNewOperationMode( MODE_STAN ); + accepted = TRUE; + } + + return accepted; +} + +/*********************************************************************//** * @brief * The signalAlarmActionToPreTreatmentMode function executes the given alarm action * as appropriate while in Pre-Treatment Mode. @@ -475,7 +575,8 @@ case ALARM_ACTION_ACK: if ( ( TD_PRE_TREATMENT_HEPARIN_SETUP_STATE == currentPreTreatmentState ) && - ( TRUE == isPreTxHeparinAwaitingSyringeLoadConfirmation() ) ) + ( TRUE == isPreTxHeparinAwaitingSyringeLoadConfirmation() ) && + ( FALSE == isAlarmActive( ALARM_ID_TD_PRE_TX_HEPARIN_LOAD_SYRINGE ) ) ) { // OK on the Load Syringe clear-only alarm confirms that // the syringe was loaded and resumes the paused state. @@ -489,4 +590,64 @@ } } +/*********************************************************************//** + * @brief + * The publishPreTreatmentStates function publishes the current + * Pre-Treatment state and associated sub-state data to the UI. + * @details \b Inputs: currentPreTreatmentState, preTreatmentStatePublishInterval + * preTreatmentStateBroadcastTimerCtr. + * @details \b Outputs: preTreatmentStateBroadcastTimerCtr. + * @return none + *************************************************************************/ +static void publishPreTreatmentStates( void ) +{ + if ( ++preTreatmentStateBroadcastTimerCtr >= getU32OverrideValue( &preTreatmentStatePublishInterval ) ) + { + PRE_TREATMENT_STATES_DATA_PAYLOAD_T payload = { 0 }; + + preTreatmentStateBroadcastTimerCtr = 0; + + payload.mSubMode = (U32)currentPreTreatmentState; + payload.mInstallState = (U32)getTubeSetInstallState(); + payload.mSelfTestDryState = 0; + payload.mPrimeState = 0; + payload.mRecirculateState = getPreTxRecirculateState(); + payload.mConfirmRxState = 0; + payload.mHeparinState = 0; + payload.mPatientConnectionState = 0; + + broadcastData( MSG_ID_TD_PRE_TREATMENT_STATES_DATA, + COMM_BUFFER_OUT_CAN_TD_BROADCAST, + (U08 *)&payload, + sizeof( PRE_TREATMENT_STATES_DATA_PAYLOAD_T ) ); + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testPreTreatmentStatePublishIntervalOverride function overrides or + * resets the Pre-Treatment state data publication interval. + * @details \b Inputs: message + * @details \b Outputs: preTreatmentStatePublishInterval + * @param message Override message from Dial-in containing the interval + * in milliseconds, or a reset command. + * @return TRUE if the override or reset is successful, otherwise FALSE. + *************************************************************************/ +BOOL testPreTreatmentStatePublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + result = u32BroadcastIntervalOverride( message, + &preTreatmentStatePublishInterval, + TASK_GENERAL_INTERVAL ); + + return result; +} + /**@}*/