Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -reb877ae36c28eb83553ee11ccccf42e2c4a5b4d2 -r3fc2a198a40b588b8d1a5684838be098456ad023 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision eb877ae36c28eb83553ee11ccccf42e2c4a5b4d2) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 3fc2a198a40b588b8d1a5684838be098456ad023) @@ -1,74 +1,1457 @@ /************************************************************************** - * - * Copyright (c) 2019-2019 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 ModePreTreat.c - * - * @date 19-Sep-2019 - * @author S. Nash - * - * @brief Top-level state machine for the pre-treatment mode. - * - *************************************************************************/ +* +* Copyright (c) 2019-2023 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 ModePreTreat.c +* +* @author (last) Michael Garthwaite +* @date (last) 08-Mar-2023 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ -#include -#include -#include "Common.h" -#include "OperationModes.h" +#include "AlarmMgmt.h" +#include "Buttons.h" +#include "ConsumableSelfTest.h" +#include "FPGA.h" #include "ModePreTreat.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PresOccl.h" +#include "PreTreatmentRecirc.h" +#include "Prime.h" +#include "Reservoirs.h" +#include "SelfTests.h" +#include "SampleWater.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +/** + * @addtogroup HDPreTreatmentMode + * @{ + */ + +// ********** 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 250 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. +#define PRE_TREATMENT_HEATING_DIA_FLOW_ML_PER_MIN 600 ///< Pre treatment heating parameters dialysate flow in mL/min. +#define PRE_TREATMENT_FLUSH_FILL_TARGET_TEMP_C 45.0F ///< Pre treatment flush fill target temperature in C. +#define PRE_TREATMENT_NORMAL_FILL_TARGET_TEMP_C ( 37.0F + 2.0F ) ///< Pre treatment normal fill target temperature in C. + +#define PRE_TREATMENT_MIN_FILL_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume minimum to prep volume during development. +#define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume (in mL) to flush filter and lines. +#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 600 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FULL_RESERVOIR_VOLUME_ML 1500 ///< Fill reservoir to this volume minimum to prep volume during development. + +#define PRE_TREATMENT_FLUSH_COUNT 2 ///< Number of flush cycles for each reservoir. + +typedef struct +{ + BOOL initialDrain; ///< Flags indicate whether a reservoir has been requested to initially drain. + BOOL startFlushFill; ///< Flags "GO" for a flush reservoir fill, to synchronize with self-test requirements + BOOL startNormalFill; ///< Flags "GO" for a normal reservoir fill, to synchronize with self-test requirements + BOOL flushComplete; ///< Flag indicates a reservoir has been flushed. + BOOL fillComplete; ///< Flag indicates a reservoir has been filled. + U32 flushCount; ///< Flag indicates the number of reservoir flush cycles required. +} PRE_TREATMENT_RESERVOIR_VAR_T; + +/// 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_REQUEST_RESERVOIR_SWITCH_STATE, ///< Command DG to switch (toggle) reservoirs + PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE, ///< After sending switch command, process DG fill command response + 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 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 BOOL fillReservoirOneStartRequested; ///< Flag indicates fill reservoir one has been requested. +static U32 preTreatmentPublishTimerCounter; ///< Pre-treatment data broadcast timer counter used to schedule when to transmit data. +/// Interval (in task intervals) at which to publish pre-treatment mode data to CAN bus. +static OVERRIDE_U32_T preTreatmentModePublishInterval = { PRE_TREATMENT_DATA_PUB_INTERVAL, PRE_TREATMENT_DATA_PUB_INTERVAL, PRE_TREATMENT_DATA_PUB_INTERVAL, 0 }; +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 PRE_TREATMENT_RESERVOIR_VAR_T reservoirStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Detailed state of each reservoir. + +#ifndef _RELEASE_ +const PRE_TREATMENT_RESERVOIR_VAR_T reservoirPrimingDisabled = {FALSE,FALSE,FALSE,TRUE,FALSE,(0)}; +#endif +const PRE_TREATMENT_RESERVOIR_VAR_T reservoirPretreatmentInit = {FALSE,FALSE,FALSE,FALSE,FALSE,PRE_TREATMENT_FLUSH_COUNT}; + // ********** private function prototypes ********** -/************************************************************************* - * @brief initPreTreatmentMode +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 handleInstallState( 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 handlePreTreatmentReservoirMgmtRequestReservoirSwitchState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ); +static U32 getPreTreatmentFillVolume( DG_RESERVOIR_ID_T inactiveRes ); +static void setPreTreatmentHeatingParams( F32 targetTempC, U32 targetVolML, F32 targetFillFlowLPM, U32 dialysateFlowMLPM ); + +/*********************************************************************//** + * @brief * The initPreTreatmentMode function initializes the Pre-Treatment Mode module. - * @details - * Inputs : none - * Outputs : Pre-Treatment Mode module initialized. - * @param none + * @details Inputs: none + * @details Outputs: Pre-Treatment Mode module initialized. * @return none -*************************************************************************/ + *************************************************************************/ void initPreTreatmentMode( void ) { + U32 reservoirIndex = 0; + + currentPreTreatmentState = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + fillReservoirOneStartRequested = FALSE; + submodeCompleteTransitionTimeCounter = 0; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) + { + for ( reservoirIndex = 0; reservoirIndex < NUM_OF_DG_RESERVOIRS; reservoirIndex++ ) + { + reservoirStatus[reservoirIndex] = reservoirPrimingDisabled; + } + } + else +#endif + { + for ( reservoirIndex = 0; reservoirIndex < NUM_OF_DG_RESERVOIRS; reservoirIndex++ ) + { + reservoirStatus[reservoirIndex] = reservoirPretreatmentInit; + } + } + + initSampleWater(); + initConsumableSelfTest(); + initPrime(); + initSelfTests(); + // Reservoirs state machine is not used in Pre-treatment but the + // init function is called here to initialize all the variables in + // the reservoirs driver since an API from the reservoirs is used + // to setup the DG heaters. + initReservoirs(); + + resetSignalFlags(); } -/************************************************************************* - * @brief transitionToPreTreatmentMode - * The transitionToPreTreatmentMode function prepares for transition to \n +/*********************************************************************//** + * @brief + * The transitionToPreTreatmentMode function prepares for transition to * pre-treatment mode. - * @details - * Inputs : none - * Outputs : - * @param none + * @details Inputs: none + * @details Outputs: none + * @return initial state + *************************************************************************/ +U32 transitionToPreTreatmentMode( void ) +{ + F32 trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + + initPreTreatmentMode(); + + // Set the heating parameters to start the heaters + setPreTreatmentHeatingParams( PRE_TREATMENT_FLUSH_FILL_TARGET_TEMP_C, PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML, + DEFAULT_TARGET_FILL_FLOW_RATE_LPM, PRE_TREATMENT_HEATING_DIA_FLOW_ML_PER_MIN ); + + cmdStopDGTrimmerHeater(); + + // Pumps should be off + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + stopSyringePump(); + + // Set valves to default positions + setValveAirTrap( STATE_CLOSED ); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); + + // Set user alarm recovery actions allowed in this mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); + + doorClosedRequired( FALSE, FALSE ); + + // Start pre-treatment mode in sample water state + transitionToSampleWater(); + + return currentPreTreatmentState; +} + +/*********************************************************************//** + * @brief + * The execPreTreatmentMode function executes the Pre-Treatment Mode state machine. + * @details Inputs: none + * @details Outputs: none + * @return current state (sub-mode) + *************************************************************************/ +U32 execPreTreatmentMode( void ) +{ + BOOL stop = isStopButtonPressed(); + + if ( TRUE == stop ) + { + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); + } + + // execute mode state machine + switch ( currentPreTreatmentState ) + { + case HD_PRE_TREATMENT_WATER_SAMPLE_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; + + case HD_PRE_TREATMENT_CART_INSTALL_STATE: + currentPreTreatmentState = handleInstallState(); + break; + + case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: + currentPreTreatmentState = handleSelfTestDryState(); + break; + + case HD_PRE_TREATMENT_PRIME_STATE: + currentPreTreatmentState = handlePrimeState(); + break; + + case HD_PRE_TREATMENT_RECIRCULATE_STATE: + currentPreTreatmentState = handleRecirculateState(); + break; + + case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: + currentPreTreatmentState = handlePatientConnectionState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); + 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 signalUserConfirmInstallation function handles user confirmation of + * disposable installation. + * @details Inputs: none + * @details Outputs: confirmInstallRequested * @return none -*************************************************************************/ -void transitionToPreTreatmentMode( void ) + *************************************************************************/ +void signalUserConfirmInstallation( void ) { - // temporary test code - alarm lamp low alarm - requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + + confirmInstallRequested = FALSE; + + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + + // Accept installation confirmation if we are in install state of pre-treatment mode and + // Door closed, Cartridge installed, syringe is detected or Heparin not being used in this treatment. + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) ) + { + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + + if ( STATE_CLOSED == pumpTrack ) + { + if ( STATE_CLOSED == frontDoor ) + { + if ( ( TRUE == isSyringeDetected() ) || ( ( bolusVol < NEARLY_ZERO ) && ( hepRate < NEARLY_ZERO ) ) ) + { + // Everything is properly installed + accepted = TRUE; + confirmInstallRequested = TRUE; + if ( ( bolusVol > NEARLY_ZERO ) || ( hepRate > NEARLY_ZERO ) ) + { + syringeDetectionRequired( TRUE ); + } + } + else + { + rejReason = REQUEST_REJECT_REASON_SYRINGE_NOT_PRESENT; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_DOOR_NOT_CLOSED; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_PUMP_TRACK_NOT_CLOSED; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; + } + + sendConsumableInstallCmdResponse( accepted, (U32) rejReason ); } -/************************************************************************* - * @brief execPreTreatmentMode - * The execFaultMode function executes the Pre-Treatment Mode state machine. - * @details - * Inputs : none - * Outputs : - * @param none +/*********************************************************************//** + * @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 execPreTreatmentMode( void ) + *************************************************************************/ +void signalUserContinueToTreatment( void ) { - BOOL stop = isStopButtonPressed(); + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; - if ( TRUE == stop ) - { - requestNewOperationMode( MODE_TREA ); - } + if ( HD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ) + { + continueToTreatmentRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + + sendContinueToTreatmentCmdResponse( accepted, rejReason ); } +/*********************************************************************//** + * @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 _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) + { + patientConnectionConfirm = TRUE; + } +#endif + + if ( TRUE == patientConnectionConfirm ) + { + 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 + * @details Outputs: given alarm action executed + * @param action ID of alarm action to execute + * @return none + *************************************************************************/ +void signalAlarmActionToPreTreatmentMode( ALARM_ACTION_T action ) +{ + switch( action ) + { + case ALARM_ACTION_STOP: + // Stop signal actively polled by mode/sub-mode/state + break; + + case ALARM_ACTION_RESUME: + alarmActionResumeReceived = TRUE; + break; + + case ALARM_ACTION_END_TREATMENT: + if ( HD_PRE_TREATMENT_PRIME_STATE > currentPreTreatmentState ) + { + if ( HD_PRE_TREATMENT_WATER_SAMPLE_STATE == currentPreTreatmentState ) + { + cmdDGSampleWater( SAMPLE_WATER_CMD_END ); + } + requestNewOperationMode( MODE_STAN ); + } + else + { + requestNewOperationMode( MODE_POST ); + } + break; + + case ALARM_ACTION_ACK: + // Nothing to be done here + break; + + default: + // Ignore + break; + } +} + +/*********************************************************************//** + * @brief + * The signalAllowDGFlushFills function sets the reservoir flush flags + * to allow reservoir flush fills to proceed when ready. + * @details Inputs: none + * @details Outputs: reservoirStatus[] + * @return none + *************************************************************************/ +void signalAllowDGFlushFills( void ) +{ + reservoirStatus[ DG_RESERVOIR_1 ].startFlushFill = TRUE; + reservoirStatus[ DG_RESERVOIR_2 ].startFlushFill = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalAllowDGFillRes1 function sets the reservoir 1 fill flag + * to allow reservoir 1 fill to proceed when ready. + * @details Inputs: none + * @details Outputs: reservoirStatus[] + * @return none + *************************************************************************/ +void signalAllowDGFillRes1( void ) +{ + reservoirStatus[ DG_RESERVOIR_1 ].startNormalFill = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalAllowDGFillRes2 function sets the reservoir 2 fill flag + * to allow reservoir 2 fill to proceed when ready. + * @details Inputs: none + * @details Outputs: reservoirStatus[] + * @return none + *************************************************************************/ +void signalAllowDGFillRes2( void ) +{ + reservoirStatus[ DG_RESERVOIR_2 ].startNormalFill = TRUE; +} + +/*********************************************************************//** + * @brief + * The getReservoirFillStatus function returns the fill complete status for + * given reservoir. + * @details Inputs: reservoirStatus[] + * @details Outputs: none + * @return TRUE if reservoir has been filled, otherwise FALSE + *************************************************************************/ +BOOL getReservoirFillStatus( DG_RESERVOIR_ID_T reservoirID ) +{ + return reservoirStatus[ reservoirID ].fillComplete; +} + +/*********************************************************************//** + * @brief + * The getPreTreatmentSubState function gets the current + * pre-treatment mode state. + * @details Inputs: currentPreTreatmentState + * @details Outputs: none + * @return currentPreTreatmentState + *************************************************************************/ +HD_PRE_TREATMENT_MODE_STATE_T getPreTreatmentSubState( void ) +{ + return currentPreTreatmentState; +} + +/*********************************************************************//** + * @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 >= getU32OverrideValue( &preTreatmentModePublishInterval ) ) + { + 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; + preTreatmentData.wetSelfTestsState = getWetSelfTestState(); + preTreatmentData.preTreatmentRsrvrState = currentReservoirMgmtState; + + broadcastData( MSG_ID_PRE_TREATMENT_STATE_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&preTreatmentData, sizeof( PRE_TREATMENT_STATE_DATA_T ) ); + 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 ) +{ + 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; + + doorClosedRequired( FALSE, FALSE ); + + // Set valves + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); + } + setValveAirTrap( STATE_CLOSED ); + + // Pumps should be off + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + stopSyringePump(); +} + +/*********************************************************************//** + * @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; + + doorClosedRequired( TRUE, TRUE ); + + 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(); + + if ( SAMPLE_WATER_COMPLETE_STATE == getSampleWaterState() ) + { + 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; + cmdStartDG(); + transitionToConsumableSelfTest(); + } + else + { + cmdStopDG(); + } + } + else + { + requestNewOperationMode( MODE_STAN ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestConsumableState function handles consumable self-test state + * during pre-treatment mode. + * @details Inputs: submodeCompleteTransitionTimeCounter + * @details Outputs: execute 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(); + } +#ifndef _RELEASE_ + if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) // Allow reservoir flushes now if air pump not disabled +#endif + { + signalAllowDGFlushFills(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestNoCartState function handles self-test with no cartridge. + * @details Inputs: none + * @details Outputs: home blood pump and dialysate pumps + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + + if ( TRUE == alarmActionResumeReceived ) + { + alarmActionResumeReceived = FALSE; + signalResumeSelfTests(); + } + + execNoCartSelfTests(); + + if ( NO_CART_SELF_TESTS_COMPLETE_STATE == getNoCartSelfTestsState() ) + { + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + transitionToCartridgeInstallation(); + } + } + + return state; +} + +/*********************************************************************//** + * @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 _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) + { + confirmInstallRequested = TRUE; + } +#endif + + if ( TRUE == confirmInstallRequested ) + { + confirmInstallRequested = FALSE; + state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + transitionToDrySelfTests(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestDryState function performs dry self-test. + * @details Inputs: none + * @details Outputs: transition to prime state on user request + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + + if ( TRUE == alarmActionResumeReceived ) + { + alarmActionResumeReceived = FALSE; + signalResumeSelfTests(); + } + + execDrySelfTests(); + + if ( DRY_SELF_TESTS_COMPLETE_STATE == getDrySelfTestsState() ) + { + 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. + * @details Inputs: none + * @details Outputs: transition to self test wet state after priming passed + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_PRIME_STATE; + + if ( TRUE == alarmActionResumeReceived ) + { + alarmActionResumeReceived = FALSE; + signalResumePrime(); + } + + execPrime(); + + if ( HD_PRIME_COMPLETE == getPrimeState() ) + { + 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; +} + +/*********************************************************************//** + * @brief + * The handleRecirculateState function handles blood and dialysate circuits + * recirculation state during pre-treatment mode. + * @details Inputs: none + * @details Outputs: controlled valves and pumps + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + + if ( TRUE == alarmActionResumeReceived ) + { + alarmActionResumeReceived = FALSE; + signalResumePreTreatmentRecirc(); + } + + execPreTreatmentRecirc(); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) + { + continueToTreatmentRequested = TRUE; + } +#endif + + if ( TRUE == continueToTreatmentRequested ) + { + continueToTreatmentRequested = FALSE; + state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + transitionToPatientConnection(); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePatientConnectionState function handles patient connection state + * during pre-treatment mode. + * @details Inputs: alarmActionResumeReceived + * @details Outputs: requested mode transition to treatment mode + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) +{ + if ( TRUE == treatmentStartRequested ) + { + DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); + + setStartReservoirVolume( activeRes ); + requestNewOperationMode( MODE_TREA ); + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + signalDialInPumpHardStop(); + cmdStopDGTrimmerHeater(); + } + else if ( TRUE == alarmActionResumeReceived ) + { + alarmActionResumeReceived = FALSE; + //setDialInPumpTargetFlowRate( DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( 250, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); // TODO remove this line once the new flow control is implemented + cmdStartDGTrimmerHeater(); + } + + 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_REQUEST_RESERVOIR_SWITCH_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtRequestReservoirSwitchState(); + 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_PRE_TREATMENT_RESERVOIR_MGMT_INVALID_STATE, currentReservoirMgmtState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtStartState function handles reservoir + * management start state for pre-treatment mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: fillReservoirOneStartRequested + * @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 ) + { + DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; + + rsrvrCmd.reservoirID = (U32)DG_RESERVOIR_2; + rsrvrCmd.useLastTrimmerHeaterDC = FALSE; + fillReservoirOneStartRequested = FALSE; + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + cmdSetDGActiveReservoir( &rsrvrCmd ); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdState function sends drain + * command to DG when DG is in re-circulate mode. + * @details Inputs: none + * @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(); + } + + // Ensure any pending reservoir switches are completed before sending drain command + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, 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(); + + // Check DG response to drain command + if ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) + { + if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) + { + if ( DG_MODE_DRAI == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + } + else + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdState function sends fill + * command to DG when DG is in re-circulate mode. + * @details Inputs: DG operation mode, DG operation sub-mode, + * reservoirStatus.flushedStatus, reservoirStatus + * @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_RESERVOIR_ID_T inactiveReservoir = getDGInactiveReservoir(); + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + U32 dialysateFlowMLPM = ( HD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ? DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN : + PRE_TREATMENT_HEATING_DIA_FLOW_ML_PER_MIN ); + + if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) + { + U32 volume = 0; + + // Drain both reservoirs and return to active res 2 before initial fills + if ( reservoirStatus[ inactiveReservoir ].initialDrain != TRUE ) + { + reservoirStatus[ inactiveReservoir ].initialDrain = TRUE; + state = PRE_TREATMENT_RESERVOIR_MGMT_REQUEST_RESERVOIR_SWITCH_STATE; + } + + // Determine target fill volume for next fill + volume = getPreTreatmentFillVolume( inactiveReservoir ); + + // Determine whether we can start next fill yet + if ( ( FALSE == reservoirStatus[ inactiveReservoir ].flushComplete ) && + ( TRUE == reservoirStatus[ inactiveReservoir ].startFlushFill ) ) + { + cmdStartDGFill( volume, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); + setPreTreatmentHeatingParams( PRE_TREATMENT_FLUSH_FILL_TARGET_TEMP_C, volume, DEFAULT_TARGET_FILL_FLOW_RATE_LPM, dialysateFlowMLPM ); + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + } + else if ( ( TRUE == reservoirStatus[ inactiveReservoir ].flushComplete ) && + ( TRUE == reservoirStatus[ inactiveReservoir ].startNormalFill ) ) + { + cmdStartDGFill( volume, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); + setPreTreatmentHeatingParams( PRE_TREATMENT_NORMAL_FILL_TARGET_TEMP_C, volume, DEFAULT_TARGET_FILL_FLOW_RATE_LPM, dialysateFlowMLPM ); + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + } + } + + 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(); + + // handle fill command response from DG + if ( TRUE == getDGCommandResponse( DG_CMD_START_FILL, &dgCmdResp ) ) + { + if ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + else if ( dgCmdResp.rejectCode != DG_CMD_REQUEST_REJECT_REASON_NONE ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_FILL_COMMAND_REJECTED, dgCmdResp.rejectCode ) + } + } + + // wait for DG to begin filling before moving on to next 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, reservoirStatus[] + * @details Outputs: switch active reservoir and signal prime fill complete status, + * reservoirStatus[] + * @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(); + DG_RESERVOIR_ID_T inactiveReservoir = getDGInactiveReservoir(); + DG_RESERVOIR_ID_T activeReservoir = getDGActiveReservoir(); + + if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_REQUEST_RESERVOIR_SWITCH_STATE; + + if ( ( TRUE == reservoirStatus[ DG_RESERVOIR_1 ].flushComplete ) && + ( TRUE == reservoirStatus[ DG_RESERVOIR_2 ].flushComplete ) ) + { + reservoirStatus[ inactiveReservoir ].fillComplete = TRUE; + } + else + { + // Start tracking flush cycles, flushComplete => don't drain again, this completes the final fill. + if ( FALSE == reservoirStatus[ inactiveReservoir ].flushComplete ) + { + reservoirStatus[ inactiveReservoir ].flushCount--; + if ( 0 == reservoirStatus[ inactiveReservoir ].flushCount ) + { + reservoirStatus[ inactiveReservoir ].flushComplete = TRUE; + } + } + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtRequestReservoirSwitchState function waits + * until prime operation switches the active reservoir before filling up next reservoir. + * @details Inputs: DG inactive reservoir + * @details Outputs: start filling next reservoir + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtRequestReservoirSwitchState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_REQUEST_RESERVOIR_SWITCH_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + BOOL waitBeforeSwitch = TRUE; + + //wait after drain or fill + if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) + { + // We do not want to switch over to res 2 final fill until prime is ready for it. +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) + { + waitBeforeSwitch = FALSE; + } +#endif + if ( TRUE == reservoirStatus[ DG_RESERVOIR_2 ].fillComplete ) + { + if ( ( getPreTreatmentSubState() > HD_PRE_TREATMENT_PRIME_STATE ) || + ( ( HD_PRE_TREATMENT_PRIME_STATE == getPreTreatmentSubState() ) && + ( getPrimeState() >= HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE ) && + ( getPrimeState() < HD_PRIME_PAUSE ) ) ) + { + waitBeforeSwitch = FALSE; + } + } + else + { + waitBeforeSwitch = FALSE; + } + + if ( waitBeforeSwitch != TRUE ) + { + DG_RESERVOIR_ID_T inactiveReservoir = getDGInactiveReservoir(); + DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; + + rsrvrCmd.reservoirID = (U32)inactiveReservoir; + rsrvrCmd.useLastTrimmerHeaterDC = TRUE; + state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + cmdSetDGActiveReservoir( &rsrvrCmd ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtWaitReservoirSwitchState function waits + * until prime operation switches the active reservoir before filling up next reservoir. + * @details Inputs: DG inactive 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; + DG_CMD_RESPONSE_T dgCmdResp; + + // handle fill command response from DG + if ( TRUE == getDGCommandResponse( DG_CMD_SWITCH_RESERVOIR, &dgCmdResp ) ) + { + if ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_REQUEST_RESERVOIR_SWITCH_STATE; + } + else if ( dgCmdResp.rejectCode != DG_CMD_REQUEST_REJECT_REASON_NONE ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_FILL_COMMAND_REJECTED, dgCmdResp.rejectCode ) + } + else + { + if ( ( TRUE == reservoirStatus[ DG_RESERVOIR_1 ].fillComplete ) && + ( TRUE == reservoirStatus[ DG_RESERVOIR_2 ].fillComplete ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE; + } + else + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The getPreTreatmentFillVolume function determines which volume to fill + * the inactive reservoir. + * @details Inputs: reservoirStatus[] + * @details Outputs: none + * @param DG inactive Reservoir + * @return volume to fill + *************************************************************************/ +static U32 getPreTreatmentFillVolume( DG_RESERVOIR_ID_T inactiveRes ) +{ + U32 volume = 0; + + // Fill volumes after flushing + if ( TRUE == reservoirStatus[ inactiveRes ].flushComplete ) + { + #ifndef _RELEASE_ + if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) ) + { + if ( DG_RESERVOIR_1 == inactiveRes ) + { + volume = PRE_TREATMENT_FULL_RESERVOIR_VOLUME_ML; + } + // Reservoir 2 + else + { + volume = PRE_TREATMENT_MIN_FILL_RESERVOIR_VOLUME_ML; + } + } + else + #endif + { + if ( DG_RESERVOIR_1 == inactiveRes ) + { + volume = PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML; + } + // Reservoir 2 + else + { + volume = PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML; + } + } + } + // Flush fill volumes + else + { + volume = PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML; + } + + return volume; +} + +/*********************************************************************//** + * @brief + * The setPreTreatmentHeatingParams function calculates and set the heating + * parameters to be sent to DG. + * @details Inputs: none + * @details Outputs: none + * @param targetTempC target temperature in C + * @param targetVolML target fill volume in milliliters + * @param targetFillFlowLPM target fill flow rate in L/min + * @param dialysateFlowMLPM dialysate flow in mL/min + * @return none + *************************************************************************/ +static void setPreTreatmentHeatingParams( F32 targetTempC, U32 targetVolML, F32 targetFillFlowLPM, U32 dialysateFlowMLPM ) +{ + DG_CMD_DIALYSATE_HEATING_PARAMS_T params; + F32 fillTimeMS = ( (F32)targetVolML / ( targetFillFlowLPM * ML_PER_LITER ) ) * SEC_PER_MIN * MS_PER_SECOND; + + params.trimmerTargetTemperature = targetTempC; + params.timeReservoirWait2SwitchMS = 0; + params.timeReservoirFillMS = fillTimeMS; + params.timeReservoirCycleMS = (U32)fillTimeMS; + params.dialysateFlowLPM = ( (F32)dialysateFlowMLPM ) / ML_PER_LITER; + params.usePriTargetTempEquation = FALSE; + cmdSetDGDialysateHeatingParams( params ); +} + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + +/*********************************************************************//** + * @brief + * The testSetPreTreatmentModePublishIntervalOverride function sets the override of the + * pre-treatment mode data publication interval. + * @details Inputs: none + * @details Outputs: preTreatmentModePublishInterval + * @param ms milliseconds between pre-treatment mode broadcasts + * @return TRUE if override set successful, FALSE if not + *************************************************************************/ +BOOL testSetPreTreatmentModePublishIntervalOverride( U32 ms ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = ms / TASK_GENERAL_INTERVAL; + + result = TRUE; + preTreatmentModePublishInterval.ovData = intvl; + preTreatmentModePublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetPreTreatmentModePublishIntervalOverride function resets the override of the + * pre-treatment mode data publication interval. + * @details Inputs: none + * @details Outputs: preTreatmentModePublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetPreTreatmentModePublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + preTreatmentModePublishInterval.override = OVERRIDE_RESET; + preTreatmentModePublishInterval.ovData = preTreatmentModePublishInterval.ovInitData; + } + + return result; +} + +/**@}*/