Index: firmware/App/Modes/TreatmentRecirc.c =================================================================== diff -u -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 -rcd5be724d5a3ba7457e761191d82f278654d7f5c --- firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) +++ firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision cd5be724d5a3ba7457e761191d82f278654d7f5c) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2021 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 TreatmentRecirc.c * * @author (last) Sean Nash -* @date (last) 18-Aug-2021 +* @date (last) 31-Jul-2023 * * @author (original) Sean Nash * @date (original) 20-Jan-2021 @@ -34,10 +34,6 @@ // ********** private definitions ********** -/// Maximum time allowed to be in recirculation sub-mode. -static const U32 RECIRC_TIMEOUT = ( ( 15 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); -/// Warn user they need to reconnect to system and resume their treatment soon. -static const U32 RECIRC_WARNING_TIMEOUT = ( ( 13 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); /// Re-circulation status broadcast interval. static const U32 RECIRC_DATA_PUBLISH_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Target flow rate for re-circulation of saline on blood-side circuit. @@ -49,8 +45,8 @@ static U32 recircTimerCtr; ///< Timer counter (in GP task intervals) counts time spent in re-circulation sub-mode. static U32 recircPublishTimerCtr; ///< Timer counter (in GP task intervals) counts time to next status broadcast. -static BOOL recircTimeoutWarningGiven; ///< Flag indicates 10 minute warning has been given to user. +static BOOL recircStartRecircRequested; ///< Flag indicates user requesting to start recirculating (confirming disconnected). static BOOL recircReconnectRequested; ///< Flag indicates user requesting re-circulate stop so they can re-connect. static BOOL recircBackToTreatmenRequested; ///< Flag indicates user requesting to go back to treatment (confirming re-connected). static BOOL recircResumeRequested; ///< Flag indicates user requesting resumption of re-circulating. @@ -63,13 +59,15 @@ static void setupForRecirculationState( void ); static void setupForRecirculationStopState( void ); +static TREATMENT_RECIRC_STATE_T handleRecircDisconnectPatientState( void ); static TREATMENT_RECIRC_STATE_T handleRecircRecircState( void ); static TREATMENT_RECIRC_STATE_T handleRecircStoppedState( void ); +static TREATMENT_RECIRC_STATE_T handleRecircReconnectPatientState( void ); static BOOL handleRecircReconnectUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleRecicConfirmReconnectUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleRecircResumeUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); -static BOOL handleRecircEndTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); +static BOOL handleRecircConfirmDisconnectUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static void publishTreatmentRecircData( void ); @@ -83,11 +81,10 @@ *************************************************************************/ void initTreatmentRecirc( void ) { - treatmentRecircState = TREATMENT_RECIRC_RECIRC_STATE; + treatmentRecircState = TREATMENT_RECIRC_DISCONNECT_PATIENT_STATE; recircTimerCtr = 0; recircPublishTimerCtr = 0; resetTreatmentRecircFlags(); - recircTimeoutWarningGiven = FALSE; } /*********************************************************************//** @@ -99,6 +96,7 @@ *************************************************************************/ static void resetTreatmentRecircFlags( void ) { + recircStartRecircRequested = FALSE; recircReconnectRequested = FALSE; recircBackToTreatmenRequested = FALSE; recircResumeRequested = FALSE; @@ -116,20 +114,24 @@ void transitionToTreatmentRecirc( void ) { initTreatmentRecirc(); + setCurrentSubState( (U32)treatmentRecircState ); + doorClosedRequired( TRUE, TRUE ); // Set valves to safe state setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + setupForRecirculationStopState(); - // Start blood pump at re-circulate flow rate - setBloodPumpTargetFlowRate( RECIRC_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Enable venous bubble detection while recirculating + setVenousBubbleDetectionEnabled( TRUE ); + // Ensure syringe pump is stopped stopSyringePump(); - // Start air trap control - startAirTrapControl(); - // *Note - Dialysate pump should already be re-circulating from rinseback sub-mode + // Stop air trap leveling control + endAirTrapControl(); + // Re-circulate dialysate side of dialyzer w/ heating to maintain temperature + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + cmdStartDGTrimmerHeater(); // Set user alarm recovery actions allowed in this sub-mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); @@ -153,8 +155,6 @@ setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Start blood pump at re-circulate flow rate setBloodPumpTargetFlowRate( RECIRC_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Start air trap leveling control - startAirTrapControl(); } /*********************************************************************//** @@ -173,25 +173,29 @@ // Close arterial and venous lines setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - // Stop air trap leveling control - endAirTrapControl(); } /*********************************************************************//** * @brief * The execTreatmentRecirc function executes the Treatment circulate sub-mode * state machine. * @details Inputs: treatmentRecircState - * @details Outputs: treatmentRecircState, recircTimerCtr + * @details Outputs: treatmentRecircState, recircTimerCtr, recircEndTreatmentRequested * @return none *************************************************************************/ void execTreatmentRecirc( void ) { + TREATMENT_RECIRC_STATE_T priorSubState = treatmentRecircState; + // Count time in this sub-mode recircTimerCtr++; switch ( treatmentRecircState ) { + case TREATMENT_RECIRC_DISCONNECT_PATIENT_STATE: + treatmentRecircState = handleRecircDisconnectPatientState(); + break; + case TREATMENT_RECIRC_RECIRC_STATE: treatmentRecircState = handleRecircRecircState(); break; @@ -200,11 +204,20 @@ treatmentRecircState = handleRecircStoppedState(); break; + case TREATMENT_RECIRC_RECONNECT_PATIENT_STATE: + treatmentRecircState = handleRecircReconnectPatientState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_TREATMENT_RECIRC_INVALID_STATE, treatmentRecircState ); break; } + if ( priorSubState != treatmentRecircState ) + { + setCurrentSubState( (U32)treatmentRecircState ); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, treatmentRecircState ); + } // Re-circulate flags should be handled by now - reset in case not handled by current state resetTreatmentRecircFlags(); @@ -214,6 +227,27 @@ /*********************************************************************//** * @brief + * The handleRecircDisconnectPatientState function handles the re-circulation + * disconnect patient state operations. + * @details Inputs: flags + * @details Outputs: flags handled + * @return next Treatment re-circulation state + *************************************************************************/ +static TREATMENT_RECIRC_STATE_T handleRecircDisconnectPatientState( void ) +{ + TREATMENT_RECIRC_STATE_T result = TREATMENT_RECIRC_DISCONNECT_PATIENT_STATE; + + if ( TRUE == recircStartRecircRequested ) + { + setupForRecirculationState(); + result = TREATMENT_RECIRC_RECIRC_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleRecircRecircState function handles the re-circulating state * operations. * @details Inputs: flags @@ -224,30 +258,24 @@ { TREATMENT_RECIRC_STATE_T result = TREATMENT_RECIRC_RECIRC_STATE; - // Is alarm stop or user reconnect requested? - if ( ( TRUE == recircReconnectRequested ) || ( TRUE == doesAlarmStatusIndicateStop() ) ) + // Is alarm stop? + if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForRecirculationStopState(); result = TREATMENT_RECIRC_STOPPED_STATE; } + // Is user reconnect requested? + else if ( TRUE == recircReconnectRequested ) + { + setupForRecirculationStopState(); + result = TREATMENT_RECIRC_RECONNECT_PATIENT_STATE; + } // Is end treatment requested? else if ( TRUE == recircEndTreatmentRequested ) { setupForRecirculationStopState(); signalEndTreatment(); // signal end Tx sub-mode } - // Has max time in re-circ sub-mode been exceeded? - else if ( recircTimerCtr > RECIRC_TIMEOUT ) - { - signalGoToTreatmentStopped(); - clearAlarm( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); - activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); - } - else if ( ( recircTimeoutWarningGiven != TRUE ) && ( RECIRC_WARNING_TIMEOUT == recircTimerCtr ) ) - { - recircTimeoutWarningGiven = TRUE; - activateAlarmNoData( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); - } return result; } @@ -264,13 +292,8 @@ { TREATMENT_RECIRC_STATE_T result = TREATMENT_RECIRC_STOPPED_STATE; - // Is back to treatment requested? - if ( TRUE == recircBackToTreatmenRequested ) - { - signalGoToTreatmentStopped(); - } // Is end treatment requested? - else if ( TRUE == recircEndTreatmentRequested ) + if ( TRUE == recircEndTreatmentRequested ) { signalEndTreatment(); } @@ -280,17 +303,39 @@ setupForRecirculationState(); result = TREATMENT_RECIRC_RECIRC_STATE; } - // Has max time in re-circ sub-mode been exceeded? - else if ( recircTimerCtr > RECIRC_TIMEOUT ) + + return result; +} + +/*********************************************************************//** + * @brief + * The handleRecircReconnectPatientState function handles the re-circulation + * reconnect patient state operations. + * @details Inputs: flags + * @details Outputs: flags handled + * @return next Treatment re-circulation state + *************************************************************************/ +static TREATMENT_RECIRC_STATE_T handleRecircReconnectPatientState( void ) +{ + TREATMENT_RECIRC_STATE_T result = TREATMENT_RECIRC_RECONNECT_PATIENT_STATE; + + // Is back to treatment requested? + if ( TRUE == recircBackToTreatmenRequested ) { signalGoToTreatmentStopped(); - activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); } - else if ( ( recircTimeoutWarningGiven != TRUE ) && ( recircTimerCtr > RECIRC_WARNING_TIMEOUT ) ) + // Is end treatment requested? + else if ( TRUE == recircEndTreatmentRequested ) { - recircTimeoutWarningGiven = TRUE; - activateAlarmNoData( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); + setupForRecirculationStopState(); + signalEndTreatment(); // signal end Tx sub-mode } + // Is re-circ resume requested? + else if ( TRUE == recircResumeRequested ) + { + setupForRecirculationState(); + result = TREATMENT_RECIRC_RECIRC_STATE; + } return result; } @@ -327,9 +372,15 @@ break; case REQUESTED_USER_ACTION_TX_RECIRC_END_TREATMENT: - accepted = handleRecircEndTreatmentUserAction( &rejReason ); + // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI + addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + accepted = TRUE; break; + case REQUESTED_USER_ACTION_TX_RECIRC_CONFIRM_DISCONNECT: + accepted = handleRecircConfirmDisconnectUserAction( &rejReason ); + break; + default: rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; break; @@ -358,14 +409,18 @@ { BOOL result = FALSE; - if ( TREATMENT_RECIRC_RECIRC_STATE == treatmentRecircState ) + if ( treatmentRecircState != TREATMENT_RECIRC_RECIRC_STATE ) { - result = TRUE; - recircReconnectRequested = TRUE; + *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } + else if ( TRUE == isTreatmentResumeBlocked() ) + { + *rejReason = REQUEST_REJECT_REASON_TREATMENT_CANNOT_BE_RESUMED; + } else { - *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; + result = TRUE; + recircReconnectRequested = TRUE; } return result; @@ -385,7 +440,7 @@ { BOOL result = FALSE; - if ( TREATMENT_RECIRC_STOPPED_STATE == treatmentRecircState ) + if ( TREATMENT_RECIRC_RECONNECT_PATIENT_STATE == treatmentRecircState ) { result = TRUE; recircBackToTreatmenRequested = TRUE; @@ -412,7 +467,7 @@ { BOOL result = FALSE; - if ( TREATMENT_RECIRC_STOPPED_STATE == treatmentRecircState ) + if ( ( TREATMENT_RECIRC_STOPPED_STATE == treatmentRecircState ) || ( TREATMENT_RECIRC_RECONNECT_PATIENT_STATE == treatmentRecircState ) ) { result = TRUE; recircResumeRequested = TRUE; @@ -427,22 +482,22 @@ /*********************************************************************//** * @brief - * The handleRecircEndTreatmentUserAction function handles an e reatment - * user action request. It is assumed that the calling function will set - * the reject reason parameter to None beforehand. + * The handleRecircConfirmDisconnectUserAction function handles a confirm + * patient disconnect user action request. It is assumed that the calling + * function will set the reject reason parameter to None beforehand. * @details Inputs: treatmentRecircState - * @details Outputs: ending of treatment action handled + * @details Outputs: confirming patient disconnect action handled * @param rejReason Code indicating reason for rejection * @return TRUE if user action accepted, FALSE if not *************************************************************************/ -static BOOL handleRecircEndTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) +static BOOL handleRecircConfirmDisconnectUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; - if ( ( TREATMENT_RECIRC_RECIRC_STATE == treatmentRecircState ) || ( TREATMENT_RECIRC_STOPPED_STATE == treatmentRecircState ) ) + if ( TREATMENT_RECIRC_DISCONNECT_PATIENT_STATE == treatmentRecircState ) { result = TRUE; - recircEndTreatmentRequested = TRUE; + recircStartRecircRequested = TRUE; } else { @@ -479,11 +534,11 @@ { TREATMENT_RECIRC_PAYLOAD_T data; - data.timeout = RECIRC_TIMEOUT / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - data.countdown = ( recircTimerCtr >= RECIRC_TIMEOUT ? 0 : ( RECIRC_TIMEOUT - recircTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + data.timeout = 0; // currently no timeout or countdown in this mode + data.countdown = 0; recircPublishTimerCtr = 0; - broadcastData( MSG_ID_HD_RECIRC_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_RECIRC_PAYLOAD_T ) ); + broadcastData( MSG_ID_HD_RECIRC_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_RECIRC_PAYLOAD_T ) ); } }