Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r7d229e65a33d587e2e5b03b4ce06e814012686e4 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 7d229e65a33d587e2e5b03b4ce06e814012686e4) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 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. @@ -16,14 +16,17 @@ ***************************************************************************/ #include "AlarmMgmt.h" -#include "Buttons.h" +#include "ConsumableSelfTest.h" #include "FPGA.h" #include "ModePreTreat.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PreTreatmentRecirc.h" #include "Prime.h" #include "SelfTests.h" +#include "SampleWater.h" #include "SystemCommMessages.h" +#include "TaskGeneral.h" /** * @addtogroup HDPreTreatmentMode @@ -32,24 +35,76 @@ // ********** private definitions ********** +/// Interval (ms/task time) at which the pre-treatment state data is published on the CAN bus. +#define PRE_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) + +/// Wait time for ui to transition on completion of a sub-mode (ms/task time). +#define SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +#define DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN 100 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. + +#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 700 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. + +#define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 ///< Primary heater target temperature offset from trimmer heater temperature. + + +/// States of the pre-treatment reservoir management state machine. +typedef enum PreTreatmentReservoirMgmt_States +{ + PRE_TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< Wait for signal to start drain and fill reservoirs + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE, ///< Command DG to start draining reservoir + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE, ///< After sending drain command, process DG drain command response + PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE, ///< Command DG to start filling reservoir + PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE, ///< After sending fill command, process DG fill command response + PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE, ///< Reservoir fill has completed + PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE, ///< Wait for prime operation to switch reservoir + PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE, ///< Pre-treatment reservoir management complete state + NUM_OF_PRE_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of pre-treatments reservoir mgmt. states +} PRE_TREATMENT_RESERVOIR_MGMT_STATE_T; + // ********** private data ********** -static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user requests treatment begin. -static BOOL alarmActionStopReceived = FALSE; ///< Flag indicates an alarm w/ stop property was triggered. +static BOOL confirmInstallRequested = FALSE; ///< Flag indicates user confirms disposable installation. +static BOOL continueToTreatmentRequested = FALSE; ///< Flag indicates user requests to continue to treatment from re-circ. +static BOOL setUFVolStatus; ///< The status of set UF volume operation. +static BOOL patientConnectionConfirm; ///< Flag indicates user has confirmed patient connection complete. +static BOOL treatmentStartRequested = FALSE; ///< Flag indicates user requests treatment begin. + static BOOL alarmActionResumeReceived = FALSE; ///< Flag indicates alarm action resume received. static HD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current state of pre-treatment mode state machine. +static U32 preTreatmentPublishTimerCounter; ///< Pre-treatment data broadcast timer counter used to schedule when to transmit data. +static U32 submodeCompleteTransitionTimeCounter; ///< Sub-mode completed transition wait time counter. +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T currentReservoirMgmtState; ///< Current pre-treatment reservoir management state. +static BOOL fillReservoirOneStartRequested; ///< Flag indicates fill reservoir one has been requested. +static BOOL reservoirFilledStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Flag indicates a reservoir has been filled. + // ********** private function prototypes ********** +static void publishPreTreatmentState( void ); static void resetSignalFlags( void ); +static void transitionToCartridgeInstallation( void ); +static void transitionToPatientConnection( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); +static void execPreTreatmentReservoirMgmt( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ); + /*********************************************************************//** * @brief * The initPreTreatmentMode function initializes the Pre-Treatment Mode module. @@ -60,7 +115,17 @@ void initPreTreatmentMode( void ) { currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + fillReservoirOneStartRequested = FALSE; + submodeCompleteTransitionTimeCounter = 0; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = FALSE; + reservoirFilledStatus[ DG_RESERVOIR_2 ] = FALSE; + + initSampleWater(); + initConsumableSelfTest(); initPrime(); initSelfTests(); @@ -83,6 +148,7 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); initPreTreatmentMode(); + cmdStopDGTrimmerHeater(); } /*********************************************************************//** @@ -105,16 +171,20 @@ switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_START_STATE: - cmdStartDG(); - cmdSetDGDialysateTargetTemps( 39.0, 37.0 ); +#ifndef SKIP_SAMPLE_WATER + transitionToSampleWater(); +#endif currentPreTreatmentState = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; break; case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: - transitionToNoCartSelfTests(); - currentPreTreatmentState = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + currentPreTreatmentState = handleWaterSampleState(); break; + case HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE: + currentPreTreatmentState = handleSelfTestConsumableState(); + break; + case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: currentPreTreatmentState = handleSelfTestNoCartState(); break; @@ -141,38 +211,133 @@ break; } + // Execute reservoir management for pre-treatment mode + execPreTreatmentReservoirMgmt(); + // Alarm response request flags should be handled at this point, reset in case not handled in current state resetSignalFlags(); + // Broadcast pre-treatment data + publishPreTreatmentState(); + return (U32)currentPreTreatmentState; } /*********************************************************************//** * @brief - * The signalUserBeginningTreatment function handles user start of a - * treatment. + * The signalUserConfirmInstallation function handles user confirmation of + * disposable installation. * @details Inputs: none - * @details Outputs: treatStartReqReceived, send response to treatment start + * @details Outputs: confirmInstallRequested * @return TRUE if signal accepted, FALSE if not *************************************************************************/ -BOOL signalUserBeginningTreatment( void ) +void signalUserConfirmInstallation( void ) { - BOOL result = FALSE; + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) ) + { + confirmInstallRequested = TRUE; + } +} - // TODO: check patient connection sub-mode state - if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) +/*********************************************************************//** + * @brief + * The signalUserContinueToTreatment function handles user request to continue + * to treatment. + * @details Inputs: none + * @details Outputs: handled and send response to continue to treatment request + * @return none + *************************************************************************/ +void signalUserContinueToTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( HD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ) { - treatStartReqReceived = TRUE; - result = TRUE; + continueToTreatmentRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; } - sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected + sendContinueToTreatmentCmdResponse( accepted, rejReason ); +} - return result; +/*********************************************************************//** + * @brief + * The setUserSetUFVolumeStatus function sets the status for user sets UF + * volume operation. + * @details Inputs: set UF volume operation status + * @details Outputs: setUFVolStatus + * @return none + *************************************************************************/ +void setUserSetUFVolumeStatus( BOOL status ) +{ + setUFVolStatus = status; } /*********************************************************************//** * @brief + * The signalUserConfirmPatientConnection function handles user confirms + * patient connection message. + * @details Inputs: none + * @details Outputs: handled and send response to patient connection confirmation + * @return none + *************************************************************************/ +void signalUserConfirmPatientConnection( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_UF_VOLUME_NOT_SET; + + if ( TRUE == setUFVolStatus ) + { + if ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) + { + patientConnectionConfirm = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendPatientConnectionConfirmCmdResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief + * The signalUserStartTreatment function handles user requests to start treatment. + * @details Inputs: patientConnectionConfirm, currentPreTreatmentState + * @details Outputs: handled and send response to treatment start request + * @return none + *************************************************************************/ +void signalUserStartTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NO_PATIENT_CONNECTION_CONFIRM; + +#ifndef SKIP_UI_INTERACTION + if ( TRUE == patientConnectionConfirm ) +#endif + { + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) + { + treatmentStartRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendStartTreatmentResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToPreTreatmentMode function executes the given alarm action * as appropriate while in PreTreatment Mode. * @details Inputs: none @@ -185,15 +350,22 @@ switch( action ) { case ALARM_ACTION_STOP: - alarmActionStopReceived = TRUE; + // Stop signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: alarmActionResumeReceived = TRUE; break; case ALARM_ACTION_END_TREATMENT: - requestNewOperationMode( MODE_STAN ); + if ( HD_PRE_TREATMENT_PRIME_STATE > currentPreTreatmentState ) + { + requestNewOperationMode( MODE_STAN ); + } + else + { + requestNewOperationMode( MODE_POST ); + } break; case ALARM_ACTION_ACK: @@ -208,20 +380,187 @@ /*********************************************************************//** * @brief + * The getReservoirFillStatus function returns the fill complete status for + * given reservoir. + * @details Inputs: reservoirFilledStatus + * @details Outputs: none + * @return TRUE if reservoir has been filled, otherwise FALSE; + *************************************************************************/ +BOOL getReservoirFillStatus( DG_RESERVOIR_ID_T reservoirID ) +{ + return reservoirFilledStatus[ reservoirID ]; +} + +/*********************************************************************//** + * @brief + * The publishPreTreatmentState function broadcasts pre-treatment sub-mode + * and current sub-mode state. + * @details Inputs: pre-treatment sub-mode, state + * @details Outputs: pre-treatment sub-mode, state messages sent on interval + * @return none + *************************************************************************/ +static void publishPreTreatmentState( void ) +{ + // Broadcast treatment time and state data at interval + if ( ++preTreatmentPublishTimerCounter >= PRE_TREATMENT_DATA_PUB_INTERVAL ) + { + PRE_TREATMENT_STATE_DATA_T preTreatmentData; + + preTreatmentData.preTreatmentSubMode = currentPreTreatmentState; + preTreatmentData.sampleWaterState = getSampleWaterState(); + preTreatmentData.consumableSelfTestsState = getConsumableSelfTestState(); + preTreatmentData.noCartSelfTestsState = getNoCartSelfTestsState(); + preTreatmentData.installState = 0; + preTreatmentData.drySelfTestsState = getDrySelfTestsState(); + preTreatmentData.primeState = getPrimeState(); + preTreatmentData.recircState = getPreTreatmentRecircState(); + preTreatmentData.patientConnectionState = 0; + + broadcastPreTreatmentState( &preTreatmentData ); + preTreatmentPublishTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief * The resetSignalFlags function resets all signal flags. * @details Inputs: none * @details Outputs: signal flags set to FALSE * @return none *************************************************************************/ static void resetSignalFlags( void ) { - treatStartReqReceived = FALSE; - alarmActionStopReceived = FALSE; + treatmentStartRequested = FALSE; + confirmInstallRequested = FALSE; + continueToTreatmentRequested = FALSE; + alarmActionResumeReceived = FALSE; } /*********************************************************************//** * @brief + * The transitionToCartridgeInstallation function prepares actuators before + * transition to pre-treatment install state. + * @details Inputs: none + * @details Outputs: valves are in insert position + * @return none + *************************************************************************/ +static void transitionToCartridgeInstallation( void ) +{ + VALVE_T valve; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); + } + + setValveAirTrap( STATE_CLOSED ); +} + +/*********************************************************************//** + * @brief + * The transitionToPatientConnection function prepares actuators before + * transition to pre-treatment patient connection state. + * @details Inputs: none + * @details Outputs: Stopped pumps + * @return none + *************************************************************************/ +static void transitionToPatientConnection( void ) +{ + VALVE_T valve; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + treatmentStartRequested = FALSE; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_C_CLOSE ); + } + + signalBloodPumpHardStop(); + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + cmdStartDGTrimmerHeater(); +} + +/*********************************************************************//** + * @brief + * The handleWaterSampleState function handles sample water state during + * pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed sample water state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + execSampleWater(); + +#ifndef SKIP_SAMPLE_WATER + if ( SAMPLE_WATER_COMPLETE_STATE == getSampleWaterState() ) +#endif + { + cmdDGSampleWater( SAMPLE_WATER_CMD_END ); + + if ( SELF_TEST_STATUS_PASSED == getSampleWaterResult() ) + { + if ( ( DG_MODE_STAN == dgOpMode ) && ( DG_STANDBY_MODE_STATE_IDLE == dgSubMode ) ) + { + state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + F32 const trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + F32 const primaryHeaterTemp = trimmerHeaterTemp + PRIMARY_HEATER_TARGET_TEMP_OFFSET; + + cmdStartDG(); + cmdSetDGDialysateTargetTemps( primaryHeaterTemp, trimmerHeaterTemp ); + transitionToConsumableSelfTest(); + } + else + { + cmdStopDG(); + } + } + else + { + requestNewOperationMode( MODE_STAN ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestConsumableState function handles consumable self-test state + * during pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed consumable self-test state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + + execConsumableSelfTest(); + + if ( CONSUMABLE_SELF_TESTS_COMPLETE_STATE == getConsumableSelfTestState() ) + { + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + fillReservoirOneStartRequested = TRUE; + transitionToNoCartSelfTests(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleSelfTestNoCartState function handles self-test with no cartridge. * @details Inputs: none * @details Outputs: home blood pump and dialysate pumps @@ -238,19 +577,44 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) + execNoCartSelfTests(); + + if ( NO_CART_SELF_TESTS_COMPLETE_STATE == getNoCartSelfTestsState() ) { - signalStopSelfTests(); + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + transitionToCartridgeInstallation(); + } } - execNoCartSelfTests(); + return state; +} - if ( TRUE == isNoCartSelfTestsPassed() ) +/*********************************************************************//** + * @brief + * The handleInstallState function handles disposable installation. + * @details Inputs: none + * @details Outputs: transition to prime sub-mode when blood pump finished + * homing + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleInstallState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + +#ifndef SKIP_UI_INTERACTION + if ( TRUE == confirmInstallRequested ) +#endif { - state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + confirmInstallRequested = FALSE; + state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + transitionToDrySelfTests(); } return state; @@ -274,28 +638,29 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopSelfTests(); - } - execDrySelfTests(); - if ( TRUE == isDrySelfTestsPassed() ) + if ( DRY_SELF_TESTS_COMPLETE_STATE == getDrySelfTestsState() ) { - transitionToPrime(); - state = HD_PRE_TREATMENT_PRIME_STATE; + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_PRIME_STATE; + transitionToPrime(); + } } return state; } /*********************************************************************//** * @brief - * The handlePrimeState function handles priming the blood and dialysate circuits. + * The handlePrimeState function handles priming the blood and dialysate + * circuits. * @details Inputs: none * @details Outputs: transition to self test wet state after priming passed * @return current state (sub-mode) @@ -311,21 +676,21 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePrime(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPrime(); - } - execPrime(); - if ( TRUE == isPrimeCompleted() ) + if ( HD_PRIME_COMPLETE == getPrimeState() ) { - state = HD_PRE_TREATMENT_RECIRCULATE_STATE; - activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); - transitionToPreTreatmentRecirc(); + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); + transitionToPreTreatmentRecirc(); + } } return state; @@ -350,19 +715,19 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePreTreatmentRecirc(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPreTreatmentRecirc(); - } - execPreTreatmentRecirc(); - if ( TRUE == isPatientConnectionRequested() ) +#ifndef SKIP_UI_INTERACTION + if ( TRUE == continueToTreatmentRequested ) +#endif { + continueToTreatmentRequested = FALSE; state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + transitionToPatientConnection(); } return state; @@ -378,15 +743,259 @@ *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) { - DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); - - if ( TRUE == treatStartReqReceived ) + if ( TRUE == treatmentStartRequested ) { + DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); setStartReservoirVolume( activeRes ); requestNewOperationMode( MODE_TREA ); } return HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; } +/*********************************************************************//** + * @brief + * The execPreTreatmentReservoirMgmt function executes the state machine for + * reservoir management during pre-treatment mode. + * @details Inputs: currentReservoirMgmtState + * @details Outputs: DG reservoirs' fills managed. + * @return none + *************************************************************************/ +static void execPreTreatmentReservoirMgmt( void ) +{ + // treatment reservoir mgmt. state machine + switch ( currentReservoirMgmtState ) + { + case PRE_TREATMENT_RESERVOIR_MGMT_START_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtStartState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCompleteState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtWaitReservoirSwitchState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE: + break; + + default: + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRIME_RESERVOIR_MGMT_INVALID_STATE, (U32)currentReservoirMgmtState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtStartState function handles reservoir + * management start state for pre-treatment mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + + if ( TRUE == fillReservoirOneStartRequested ) + { + fillReservoirOneStartRequested = FALSE; + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdState function sends drain + * command to DG when DG is in re-circulate mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + // If DG has not started yet, start DG + if ( DG_MODE_STAN == dgOpMode ) + { + cmdStartDG(); + } + + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdRespState function waits + * and processes DG drain command response. + * @details Inputs: DG drain command response + * @details Outputs: processed DG drain command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + if ( DG_MODE_DRAI == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdState function sends fill + * command to DG when DG is in re-circulate mode. + * @details Inputs: DG operation mode and operation sub-mode + * @details Outputs: sent fill command to DG + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + + if ( DG_RESERVOIR_1 == getDGInactiveReservoir() ) + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML ); + } + else + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdRespState function waits + * and processes DG fill command response. + * @details Inputs: DG fill command response + * @details Outputs: processed DG fill command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_FILL, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + if ( DG_MODE_FILL == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCompleteState function switches + * reservoir after the first one fill is complete and restart reservoir management + * state machine. + * @details Inputs: DG operation mode + * @details Outputs: switch active reservoir and signal prime fill complete status + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + if ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = TRUE; + } + else if ( ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) && ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) ) + { + reservoirFilledStatus[ DG_RESERVOIR_2 ] = TRUE; + state = PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE; + } + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtWaitReservoirSwitchState function waits + * until prime operation switches the active reservoir before filling up next reservoir. + * @details Inputs: DG intactive reservoir + * @details Outputs: start filling next reservoir + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + + if ( DG_RESERVOIR_2 == getDGInactiveReservoir() ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + return state; +} + /**@}*/