Index: firmware/App/Modes/TreatmentEnd.c =================================================================== diff -u -rb7b4599fe79b345762856e0e3a67b808f55bfacc -rcd5be724d5a3ba7457e761191d82f278654d7f5c --- firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision b7b4599fe79b345762856e0e3a67b808f55bfacc) +++ firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision cd5be724d5a3ba7457e761191d82f278654d7f5c) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2024 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 TreatmentEnd.c * -* @author (last) Dara Navaei -* @date (last) 07-Apr-2023 +* @author (last) Sean Nash +* @date (last) 11-Oct-2023 * * @author (original) Sean Nash * @date (original) 05-Feb-2021 @@ -24,6 +24,7 @@ #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TreatmentEnd.h" +#include "TreatmentStop.h" #include "Valves.h" /** @@ -33,6 +34,8 @@ // ********** private definitiions *********** +/// Interval at which treatment end progress is to be published to UI. +#define TREATMENT_END_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Target flow rate for blood while waiting for user to initiate final rinseback. #define TX_END_BP_FLOW_RATE_ML_MIN 100 @@ -46,18 +49,19 @@ static U32 txEndTimerCtr; ///< Timer counter (in GP task intervals) counts time spent waiting for user to initiate final rinseback. static U32 bloodSittingTimerCtr; ///< Timer counter tracks time in paused state while blood is sitting. -static BOOL txEndAlarmResumeRequested; ///< Flag indicates user requesting resume from alarm. static BOOL txEndAlarmRinsebackRequested; ///< Flag indicates user requesting rinseback from alarm. static BOOL txEndAlarmEndTreatmentRequested; ///< Flag indicates user requesting end treatment from alarm. static BOOL txEndRinsebackRequested; ///< Flag indicates user requesting final rinseback. static BOOL txEndDrainCmdSent; ///< Flag indicates DG Drain command has been sent. +static U32 treatmentEndPublishTimerCtr; ///< Timer counter for determining interval for treatment end status to be published. // ********** private function prototypes ********** static void resetTreatmentEndFlags( void ); static void setupForTxEndWait4RinsebackState( void ); static void setupForTxEndPausedState( void ); +static void publishTreatmentEndData( void ); static TREATMENT_END_STATE_T handleTxEndWait4RinsebackState( void ); static TREATMENT_END_STATE_T handleTxEndPausedState( void ); @@ -77,6 +81,7 @@ treatmentEndState = TREATMENT_END_WAIT_FOR_RINSEBACK_STATE; txEndTimerCtr = 0; bloodSittingTimerCtr = 0; + treatmentEndPublishTimerCtr = 0; txEndDrainCmdSent = FALSE; resetTreatmentEndFlags(); } @@ -90,7 +95,6 @@ *************************************************************************/ static void resetTreatmentEndFlags( void ) { - txEndAlarmResumeRequested = FALSE; txEndAlarmRinsebackRequested = FALSE; txEndAlarmEndTreatmentRequested = FALSE; txEndRinsebackRequested = FALSE; @@ -112,9 +116,11 @@ cmdStopDGFill(); // Set user alarm recovery actions allowed in this sub-mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - + setCurrentSubState( (U32)treatmentEndState ); + setCurrent4thLevelState( NO_SUB_STATE ); // Set valves, pumps and heater setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); @@ -123,6 +129,8 @@ stopSyringePump(); cmdStopDGTrimmerHeater(); setupForTxEndWait4RinsebackState(); + // Enable venous bubble detection + setVenousBubbleDetectionEnabled( TRUE ); } /*********************************************************************//** @@ -137,8 +145,6 @@ static void setupForTxEndWait4RinsebackState( void ) { doorClosedRequired( TRUE, TRUE ); - // No resume alarm action allowed - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); // Resume in this sub-mode indicates resume wait for user rinseback request (not resume treatment) // Open VBA and VBV valves to allow flow from/to patient setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); @@ -161,8 +167,6 @@ static void setupForTxEndPausedState( void ) { doorClosedRequired( FALSE, FALSE ); - // Resume alarm action will take us back to TxEndWait4RinsebackState - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); // Stop blood pump signalBloodPumpHardStop(); // Close arterial and venous lines @@ -177,14 +181,18 @@ * The execTreatmentEnd function executes the Treatment End sub-mode * state machine. * @details Inputs: treatmentEndState - * @details Outputs: treatmentEndState + * @details Outputs: treatmentEndState, txEndAlarmEndTreatmentRequested * @return none *************************************************************************/ void execTreatmentEnd( void ) { TREATMENT_END_STATE_T priorSubState = treatmentEndState; - txEndTimerCtr++; + // Has max time waiting for user to initiate final rinseback been exceeded? + if ( ( ++txEndTimerCtr > TX_END_TIMEOUT_MS ) && ( txEndAlarmRinsebackRequested != TRUE ) ) + { + activateAlarmNoData( ALARM_ID_HD_END_TREATMENT_TIMEOUT_ALARM ); + } switch ( treatmentEndState ) { @@ -203,8 +211,11 @@ if ( priorSubState != treatmentEndState ) { + setCurrentSubState( (U32)treatmentEndState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, treatmentEndState ); } + publishTreatmentEndData(); + // Re-circulate flags should be handled by now - reset in case not handled by current state resetTreatmentEndFlags(); } @@ -260,11 +271,6 @@ { signalGoToRinseback(); } - // Has max time waiting for user to initiate final rinseback been exceeded? - else if ( txEndTimerCtr > TX_END_TIMEOUT_MS ) - { - activateAlarmNoData( ALARM_ID_HD_END_TREATMENT_TIMEOUT_ALARM ); - } return result; } @@ -288,51 +294,35 @@ { signalGoToRinseback(); } - // Is slow blood flow resume requested? - else if ( TRUE == txEndAlarmResumeRequested ) - { - setupForTxEndWait4RinsebackState(); - result = TREATMENT_END_WAIT_FOR_RINSEBACK_STATE; - } // Is treatment end requested? else if ( TRUE == txEndAlarmEndTreatmentRequested ) { signalEndTreatment(); } else { - // Ensure we do not sit in stopped state for too long - if ( bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) + if ( FALSE == doesAlarmStatusIndicateEndTxOnly() ) // Alarms appropriate only if we are not already at an alarm stop, end Tx only { - activateAlarmNoData( ALARM_ID_HD_END_OF_TREATMENT_ALARM ); + // Ensure we do not sit in stopped state for too long + if ( bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) + { + activateAlarmNoData( ALARM_ID_HD_END_OF_TREATMENT_ALARM ); + } + if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) + { + // Raise the alarm + activateAlarmNoData( ALARM_ID_HD_END_OF_TREATMENT_HIGH ); + } } - if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) - { - // Raise the alarm - activateAlarmNoData( ALARM_ID_HD_END_OF_TREATMENT_HIGH ); - } } return result; } /*********************************************************************//** * @brief - * The signalTreatmentEndAlarmResumeUserAction function signals the treatment end - * sub-mode to stop per an active alarm. - * @details Inputs: none - * @details Outputs: txEndAlarmResumeRequested - * @return none - *************************************************************************/ -void signalTreatmentEndAlarmResumeUserAction( void ) -{ - txEndAlarmResumeRequested = TRUE; -} - -/*********************************************************************//** - * @brief * The signalTreatmentEndAlarmRinsebackUserAction function signals the treatment end - * sub-mode to stop per an active alarm. + * sub-mode to start rinseback per user alarm action. * @details Inputs: none * @details Outputs: txEndAlarmRinsebackRequested * @return none @@ -345,7 +335,7 @@ /*********************************************************************//** * @brief * The signalTreatmentEndAlarmEndTxUserAction function signals the treatment end - * sub-mode to stop per an active alarm. + * sub-mode to end treatment per user alarm action. * @details Inputs: none * @details Outputs: txEndAlarmEndTreatmentRequested * @return none @@ -432,4 +422,31 @@ return treatmentEndState; } +/*********************************************************************//** + * @brief + * The publishTreatmentEndData function publishes Treatment End progress to UI + * at 1 Hz interval. + * @details Inputs: treatmentEndPublishTimerCtr + * @details Outputs: Treatment end data published + * @return none + *************************************************************************/ +static void publishTreatmentEndData( void ) +{ + if ( ++treatmentEndPublishTimerCtr >= TREATMENT_END_DATA_PUBLISH_INTERVAL ) + { + TREATMENT_STOP_PAYLOAD_T data; + + data.timeout = 0; + data.countdown = 0; + + // update blood sitting timer if active + if ( bloodSittingTimerCtr > 0 ) + { + data.timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + data.countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + } + broadcastData( MSG_ID_HD_TREATMENT_STOP_TIMER_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_STOP_PAYLOAD_T ) ); + } +} + /**@}*/