Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -r3970ba21aa2500f662620ef3d4b3e1e7a48fc47a -rcd5be724d5a3ba7457e761191d82f278654d7f5c --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 3970ba21aa2500f662620ef3d4b3e1e7a48fc47a) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision cd5be724d5a3ba7457e761191d82f278654d7f5c) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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 ModePostTreat.c * -* @author (last) Michael Garthwaite -* @date (last) 15-May-2023 +* @author (last) Dara Navaei +* @date (last) 03-Oct-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -48,11 +48,19 @@ #define DIP_DRAIN_DG_FLOW_RATE_ML_MIN 60 ///< DG drain inlet pump flow rate in mL/min. #define DIP_DRAIN_DG_RUNTIME_MS ( 40 * MS_PER_SECOND ) ///< DG drain inlet pump run time in ms. +// Concentrates values +#define ACID_1251_1_K 1.0F ///< Acid 1251_1 potassium concentrate. +#define ACID_2251_0_K 2.0F ///< Acid 2251_0 potassium concentrate. +#define ACID_3251_9_K 3.0F ///< Acid 3251_9 potassium concentrate. + +#define ACID_TYPES_CA 2.5F ///< Acid types calcium concentrate. +#define ACID_TYPES_BICARB 33 ///< Acid type bicarb concentrate. +#define ACID_TYPES_NA 137 ///< Acid type sodium concentrate. + /// Post-Treatment drain reservoirs state machine. typedef enum Drain_States { - DRAIN_DG_DEPRIME_STATE = 0, ///< Drain DG De-prime dialysate lines of excess fluid state. - DRAIN_RESERVOIR_SWITCH_STATE, ///< Switch reservoir state. + DRAIN_RESERVOIR_SWITCH_STATE = 0, ///< Switch reservoir state. DRAIN_RESERVOIR_START_DRAIN_STATE, ///< Drain reservoir start drain state. DRAIN_RESERVOIR_DRAIN_STATE, ///< Drain first reservoir state. DRAIN_RESERVOIR_COMPLETE_STATE, ///< Drain complete state. @@ -62,11 +70,10 @@ // ********** private data ********** static BOOL patientDisconnectionConfirmed; ///< Flag indicates user confirms patient disconnection. +static bool patientDisconnectHandled; ///< Flag indicates patient disconnect actions have been handled static BOOL disposableRemovalConfirmed; ///< Flag indicates user confirms disposable removal. static BOOL rinseConcentrateLines; ///< FLag indicates to rinse concentrate lines. static BOOL isThisFirstDrain; ///< Flag to indicate whether this is the first time the reservoir is drained. -static BOOL drainDGDePrimeActive; ///< FLag to indicate DePrime DG Dialysate lines active -static U32 drainDGDePrimeStarttime; ///< DG DePrime start time static BOOL dgCommandSent; ///< Flag indicates whether a DG command has been already sent. static HD_POST_TREATMENT_STATE_T currentPostTreatmentState; ///< Current state of post-treatment mode state machine. static DRAIN_STATE_T currentDrainReservoirState; ///< Current drain reservoir state. @@ -77,6 +84,10 @@ static TREATMENT_LOG_DATA_PAYLOAD_T treatmentLogData; ///< Treatment parameters record for logging. +static const F32 ACID_TYPES_K[ NUM_OF_ACID_CONC_TYPES ] = { ACID_1251_1_K, + ACID_2251_0_K, + ACID_3251_9_K }; ///< Acid types potassium. + // ********** private function prototypes ********** static HD_POST_TREATMENT_STATE_T handlePostTreatmentDrainReservoirsState( void ); @@ -85,7 +96,6 @@ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ); static void execDrainReservoirs( void ); -static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ); static DRAIN_STATE_T handleDrainReservoirSwitchState( void ); static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ); static DRAIN_STATE_T handleDrainReservoirDrainState( void ); @@ -103,15 +113,14 @@ void initPostTreatmentMode( void ) { patientDisconnectionConfirmed = FALSE; + patientDisconnectHandled = FALSE; disposableRemovalConfirmed = FALSE; rinseConcentrateLines = FALSE; isThisFirstDrain = TRUE; dgCommandSent = FALSE; currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; - currentDrainReservoirState = DRAIN_DG_DEPRIME_STATE; + currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; postTreatmentPublishTimerCounter = 0; - drainDGDePrimeActive = FALSE; - drainDGDePrimeStarttime = 0; // Reset treatment log data memset( &treatmentLogData, 0x0, sizeof( TREATMENT_LOG_DATA_PAYLOAD_T ) ); @@ -139,7 +148,7 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); - doorClosedRequired( FALSE, FALSE ); + doorClosedRequired( TRUE, TRUE ); cmdStopDGTrimmerHeater(); @@ -153,7 +162,7 @@ signalBloodPumpHardStop(); signalDialOutPumpHardStop(); signalDialInPumpHardStop(); - setCurrentSubState( NO_SUB_STATE ); + setCurrentSubState( (U32)currentDrainReservoirState ); collectTreatmentLogData(); exitBloodLeakNormalState(); @@ -237,6 +246,11 @@ treatmentLogData.acidConcentrate = getTreatmentParameterU32( TREATMENT_PARAM_ACID_CONCENTRATE ); treatmentLogData.bicarbConcentrate = getTreatmentParameterU32( TREATMENT_PARAM_BICARB_CONCENTRATE ); + treatmentLogData.potassiumConcentration = ACID_TYPES_K[ treatmentLogData.acidConcentrate ]; + treatmentLogData.calciumConcentration = ACID_TYPES_CA; + treatmentLogData.bicarbonateConcentration = ACID_TYPES_BICARB; + treatmentLogData.sodiumConcentration = ACID_TYPES_NA; + treatmentLogData.dialysateTemperature_degC = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); treatmentLogData.dialyzerType = getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ); treatmentLogData.treatmentStartDateAndTime = getTreatmentStartTimeStamp(); @@ -316,6 +330,32 @@ /*********************************************************************//** * @brief + * The requestPostTxNext requests to go to next screen after treatment record + * review screen in post-treatment mode + * @details Inputs: currentPostTreatmentState + * @details Outputs: none + * @return none + *************************************************************************/ +void requestPostTxNext( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + + if ( currentPostTreatmentState >= HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE ) + { + accepted = TRUE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DRAIN_NOT_COMPLETE; + } + + // Respond to user request to move to next screen + sendPostTxNextCmdResponse( accepted, (U32)rejReason ); +} + +/*********************************************************************//** + * @brief * The signalUserConfirmDisposableRemoval signals post-treatment mode * user has confirmed disposable removal. * @details Inputs: none @@ -353,6 +393,41 @@ /*********************************************************************//** * @brief + * The checkPostTreatmentPatientDisconnect function checks UI patient + * disconnect and handles valve release, pump homing, door requirement. + * @details Inputs: patientDisconnectionConfirmed, patientDisconnectHandled + * @details Outputs: patientDisconnectHandled, home pumps, open valves, + * retract syringe, door closed requirement. + * @return none + *************************************************************************/ +static void checkPostTreatmentPatientDisconnect( void ) +{ + VALVE_T valve; + + if ( ( TRUE == patientDisconnectionConfirmed ) && ( FALSE == patientDisconnectHandled ) ) + { + // home valves and pumps while front door is still closed. + homeBloodPump(); + homeDialInPump(); + homeDialOutPump(); + for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) + { + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); + } + if ( ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ) > 0.0 ) || + ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ) > 0.0 ) ) + { + retractSyringePump(); + } + doorClosedRequired( FALSE, FALSE ); + // NOTE: patientDisconnectionConfirmed is NOT reset because + // Patient Disconnect State needs it to move to next state + patientDisconnectHandled = TRUE; + } +} + +/*********************************************************************//** + * @brief * The handlePostTreatmentDrainReservoirsState function executes drain reservoirs * operation state machine and transition to next state once completed. * @details Inputs: currentDrainReservoirState @@ -361,17 +436,17 @@ *************************************************************************/ static HD_POST_TREATMENT_STATE_T handlePostTreatmentDrainReservoirsState( void ) { - HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; + HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; execDrainReservoirs(); if ( DRAIN_RESERVOIR_COMPLETE_STATE == currentDrainReservoirState ) { // Done with draining the reservoirs state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; - doorClosedRequired( TRUE, TRUE ); setCurrentSubState( NO_SUB_STATE ); } + checkPostTreatmentPatientDisconnect(); return state; } @@ -386,44 +461,24 @@ *************************************************************************/ static HD_POST_TREATMENT_STATE_T handlePostTreatmentPatientDisconnectionState( void ) { - VALVE_T valve; - - F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); - F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); - if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) ) - { + checkPostTreatmentPatientDisconnect(); + #ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) - { - patientDisconnectionConfirmed = TRUE; - } + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) + { + patientDisconnectionConfirmed = TRUE; + } #endif - if ( TRUE == patientDisconnectionConfirmed ) - { - patientDisconnectionConfirmed = FALSE; - state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; - - for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) - { - setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); - } - - homeBloodPump(); - homeDialInPump(); - homeDialOutPump(); - - doorClosedRequired( FALSE, FALSE ); - - if ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ) - { - retractSyringePump(); - } - } + if ( TRUE == patientDisconnectionConfirmed ) + { + patientDisconnectionConfirmed = FALSE; + patientDisconnectHandled = FALSE; + state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; } return state; @@ -520,13 +575,21 @@ static void execDrainReservoirs( void ) { DRAIN_STATE_T priorSubState = currentDrainReservoirState; + DG_OP_MODE_T dgMode = getDGOpMode(); + if ( DG_MODE_STAN == dgMode ) + { // In case DG was reset/power cycled, re-start DG so we can drain the reservoirs + cmdStartDG(); + currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; + } + else if ( DG_MODE_FAUL == dgMode ) + { // In case DG faulted, skip DG drain states and move on + currentDrainReservoirState = DRAIN_RESERVOIR_COMPLETE_STATE; + } + + // Execute post-tx drain state machine switch ( currentDrainReservoirState ) { - case DRAIN_DG_DEPRIME_STATE: - currentDrainReservoirState = handleDrainDePrimeDGDialysateLinesState(); - break; - case DRAIN_RESERVOIR_SWITCH_STATE: currentDrainReservoirState = handleDrainReservoirSwitchState(); break; @@ -558,50 +621,6 @@ /*********************************************************************//** * @brief - * The handleDrainDePrimeDGDialysateLinesState function de-primes the return - * dialysate line so that it will not leak when user disconnects the line - * from the DG. - * @details Inputs: drainDGDePrimeActive - * @details Outputs: drainDGDePrimeActive - * @return next state - *************************************************************************/ -static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ) -{ - DRAIN_STATE_T state = DRAIN_DG_DEPRIME_STATE; - - if ( ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) || ( DG_MODE_FAUL == getDGOpMode() ) ) - { - if ( FALSE == drainDGDePrimeActive ) - { - // First entry - Run DPi slow reverse, VDi, VDo closed in init, DPo Off in init. - setDialInPumpTargetFlowRate( DIP_DRAIN_DG_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); - drainDGDePrimeStarttime = getMSTimerCount(); - drainDGDePrimeActive = TRUE; - } - } - if ( TRUE == drainDGDePrimeActive ) - { - // Thereafter, check for time elapsed - if ( TRUE == didTimeout( drainDGDePrimeStarttime, DIP_DRAIN_DG_RUNTIME_MS ) ) - { - drainDGDePrimeActive = FALSE; - signalDialInPumpHardStop( ); - if ( getDGOpMode() != DG_MODE_FAUL ) - { - state = DRAIN_RESERVOIR_SWITCH_STATE; - } - else - { - state = DRAIN_RESERVOIR_COMPLETE_STATE; - } - } - } - - return state; -} - -/*********************************************************************//** - * @brief * The handleDrainReservoirSwitchState function waits for DG to complete * reservoir switch. * @details Inputs: isThisFirstDrain, dgCommandSent @@ -610,9 +629,10 @@ *************************************************************************/ static DRAIN_STATE_T handleDrainReservoirSwitchState( void ) { - DRAIN_STATE_T state = DRAIN_RESERVOIR_SWITCH_STATE; + DRAIN_STATE_T state = DRAIN_RESERVOIR_SWITCH_STATE; + DG_OP_MODE_T dgMode = getDGOpMode(); - if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) + if ( ( DG_MODE_GENE == dgMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { DG_CMD_RESPONSE_T dgCmdResp;