Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r120487ddf3e3d69d1de5094d5252c037588e2ed8 -rf1b7fd13c6136989018e0907d037ab1c713620c6 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 120487ddf3e3d69d1de5094d5252c037588e2ed8) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision f1b7fd13c6136989018e0907d037ab1c713620c6) @@ -7,8 +7,8 @@ * * @file ModeStandby.c * -* @author (last) Arpita Srivastava -* @date (last) 18-May-2026 +* @author (last) Vijay Pamula +* @date (last) 27-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -17,16 +17,23 @@ #include "AirTrap.h" #include "BloodFlow.h" +#include "Bubbles.h" #include "Buttons.h" +#include "DDDefs.h" #include "DDInterface.h" #include "Messaging.h" +#include "ModeInitPOST.h" +#include "ModePostTreat.h" #include "ModePreTreat.h" -#include "ModeTreatment.h" #include "ModeStandby.h" +#include "ModeTreatment.h" #include "OperationModes.h" #include "Switches.h" #include "SystemCommTD.h" +#include "SyringePump.h" #include "TxParams.h" +#include "Valve3Way.h" +#include "Valves.h" /** * @addtogroup TDStandbyMode @@ -38,27 +45,49 @@ #define USER_COMMAND_CANCEL 0 ///< Cancel treatment workflow command code. #define USER_COMMAND_INITIATE 1 ///< Initiate treatment workflow command code. +/// DD cleaning mode status data structure +typedef struct +{ + BOOL startCleaningMode; ///< Flag to indicate to start cleaning mode. + DD_COMMAND_T startRequestCmdID; ///< DD cleaning mode start request command ID. + ALARM_ID_T alarmID; ///< The informative alarm to trigger for each cleaning mode. + DD_OP_MODE_T ddOpMode; ///< DD operation mode. + BOOL sampleRqstTrgrd; ///< Flag to indicate the sample alarm has been triggered (for RO perm and chem flush). + GENERIC_CONFIRM_ID_T sampleRequestID; ///< Sample request pass/fail message status. + GENERIC_CONFIRM_ID_T stopRequestCmdID; ///< Stop DD cleaning request command ID +} DD_CLEANING_MODE_STATUS_T; + // ********** private data ********** static TD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. static BOOL treatStartReqReceived; ///< Flag indicates user has requested initiation of a treatment. +static BOOL homingInitiated; ///< Flag indicates actuators have been homed. +static FLUID_TYPE_T fluidType; ///< Fluid type assigned based on user selection. +static TREATMENT_TYPE_T modality; ///< Modality from the treatment initiation. +static DD_CLEANING_MODE_STATUS_T currentDDCleaningMode; ///< Current DD cleaning mode status. // ********** private function prototypes ********** static TD_STANDBY_STATE_T handleStandbyModeStartState( void ); static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); +static void setStandbyWaitForTreatmentActuators( TD_STANDBY_STATE_T state ); +static void setRequestedCleaningMode( DD_OP_MODE_T opMode, BOOL isHeatDisPassiveCool ); +static TD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ); /*********************************************************************//** * @brief * The initStandbyMode function initializes the Standby Mode Unit. * @details \b Inputs: none - * @details \b Outputs: currentStandbyState, treatStartReqReceived + * @details \b Outputs: Standby mode variables initialized. * @return none *************************************************************************/ void initStandbyMode( void ) { currentStandbyState = STANDBY_START_STATE; treatStartReqReceived = FALSE; + homingInitiated = FALSE; + fluidType = FLUID_TYPE_UNKNOWN; + modality = TREATMENT_MODALITY_HD_SALINE_FLUID; } /*********************************************************************//** @@ -71,32 +100,48 @@ *************************************************************************/ U32 transitionToStandbyMode( void ) { - TD_OP_MODE_T previousOpMode = getPreviousOperationMode(); + TD_OP_MODE_T previousOpMode = getPreviousOperationMode(); //TODO +// U08 requestPayload[3] = { 0U, 0U, 0U }; // Re-initialize when transitioning to standby mode initStandbyMode(); resetDDInterface(); + resetAirTrap(); + resetBloodPumpRotorCount(); + resetPreLoadStatus(); + setVenousBubbleDetectionEnabled( H18_BBLD, FALSE ); setCurrentSubState( NO_SUB_STATE ); +// clearNoRetriggerFlag(); // Alarm flag // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); + // Set valves to default positions + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + if ( VALVE_STATE_IDLE == getValveState( H1_VALV ) ) + { + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + } + if ( VALVE_STATE_IDLE == getValveState( H19_VALV ) ) + { + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + } + // Standby currently supports Start and Wait For Treatment states. + currentStandbyState = STANDBY_START_STATE; // Pumps should be off -// signalBloodPumpHardStop(); + signalBloodPumpHardStop(); // stopSyringePump(); + doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode - // Set valves to default positions -// setValveAirTrap( VALVE_3WAY_COMMON_TO_CLOSED_STATE ); -// setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); -// setValvePosition( H19, VALVE_POSITION_A_INSERT_EJECT ); - -// doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode - // Request DD service record and usage information from DD -// sendDGServiceRequestToDG(); -// sendDGUsageInfoRequestToDG(); +// sendDDServiceRequestToDD(); + //TODO: Service record id not available +// sendMessage( MSG_ID_TD_DD_REQUEST_SERVICE_RECORD_FROM_TD, COMM_BUFFER_OUT_CAN_TD_2_DD, requestPayload, sizeof( requestPayload ) ); +// sendMessage( MSG_ID_TD_DD_USAGE_INFO_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_DD, requestPayload, sizeof( requestPayload ) ); +// sendDDUsageInfoRequestToDD(); //TODO need to enable return currentStandbyState; } @@ -128,6 +173,10 @@ currentStandbyState = handleStandbyModeWaitForTreatmentState(); break; + case STANDBY_WAIT_FOR_DISINFECT_STATE: + currentStandbyState = handleStandbyModeWaitForDisinfectState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); currentStandbyState = STANDBY_START_STATE; @@ -140,58 +189,46 @@ /*********************************************************************//** * @brief * The handleStandbyModeStartState function handles the standby start state. - * This state waits for the door to be closed and then initiates homing of - * pumps and valves and transitions to the wait for treatment state. + * This state initiates homing of the syringe pump and pinch valves, + * then transitions to Wait For Treatment after homing completes and + * then initiates homing of pumps and valves and transitions to the + * wait for treatment state. * @details \b Inputs: * @details \b Outputs: * @return next state of the standby mode state machine *************************************************************************/ static TD_STANDBY_STATE_T handleStandbyModeStartState( void ) { - TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; + TD_STANDBY_STATE_T state = STANDBY_START_STATE; - // Wait for door to be closed so we can home actuators -// if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) -// { -// // If we haven't already initiated homing of actuators, initiate now -// if ( homingInitiated != TRUE ) -// { -// VALVE_T valve; -// -// // Home pumps and valves -// for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) -// { -// homeValve( valve, VALVE_NO_FORCE_HOME, VALVE_CARTRIDGE_MAY_BE_PRESENT ); -// } -// homeBloodPump(); -// homeDialInPump(); -// homeDialOutPump(); -// retractSyringePump(); -// -// homingInitiated = TRUE; -// } -// else -// { -// // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration -//#ifndef _RELEASE_ -// if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) ) -// { -// state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check -// } -// else -//#endif -// { -// if ( ( TRUE == isSyringePumpHome() ) && ( TRUE == isSyringePumpStopped() ) ) -// { -// syringePumpVerifyForceSensorDACCalibration(); -// homingInitiated = FALSE; // reset for next time -// doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode -// state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check -// } -// } -// } -// } + // If we haven't already initiated homing of actuators, initiate now + if ( homingInitiated != TRUE ) + { + // Home pumps and valves + homeValve( H1_VALV, FALSE, TRUE ); + homeValve( H19_VALV, FALSE, TRUE ); + + if ( FALSE == isSyringePumpHome() ) + { + retractSyringePump(); + } + homingInitiated = TRUE; + } + else + { + // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration + if ( ( TRUE == isSyringePumpHome() ) && ( TRUE == isSyringePumpStopped() ) + && ( VALVE_POSITION_A_INSERT_EJECT == getValvePosition( H1_VALV ) ) + && ( VALVE_POSITION_A_INSERT_EJECT == getValvePosition( H19_VALV ) ) ) + { + syringePumpVerifyForceSensorDACCalibration(); + homingInitiated = FALSE; // reset for next time + setStandbyWaitForTreatmentActuators( STANDBY_WAIT_FOR_TREATMENT_STATE ); + state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check + } + } + return state; } @@ -206,43 +243,44 @@ static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) { TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; - DD_OP_MODE_T ddOperationMode = getDDOpMode(); F32 bicarbConvFactor = BICARBONATE_CONVERSION_FACTOR; + //TODO +// DD_OP_MODE_T ddOperationMode = getDDOpMode(); -// switch ( dgOperationMode ) +// switch ( ddOperationMode ) // { -// case DG_MODE_GENE: -// // If DG is in idle generation state while we are in standby mode, transition DG to standby too -// cmdStopDG(); +// case DD_MODE_GENE: +// // If DD is in idle generation state while we are in standby mode, transition DD to standby too +// cmdStopDD(); // break; // -// // If DG is any of the cleaning modes, set the HD standby to be in the corresponding cleaning mode -// case DG_MODE_FLUS: -// case DG_MODE_HEAT: -// case DG_MODE_CHEM: -// case DG_MODE_CHFL: -// case DG_MODE_HCOL: -// case DG_MODE_ROPS: -// setRequestedCleaningMode( dgOperationMode ); -// state = STANDBY_WAIT_FOR_DG_CLEANING_MODE_TO_START_STATE; +// // If DD is any of the cleaning modes, set the TD standby to be in the corresponding cleaning mode +// case DD_MODE_HEAT: +// case DD_MODE_HCOL: +// case DD_MODE_ROPS: +// setRequestedCleaningMode( ddOperationMode ); +// state = STANDBY_WAIT_FOR_DD_CLEANING_MODE_TO_START_STATE; +// // DD cleaning mode handling is not enabled yet. +// // Stay in Wait For Treatment until DD returns to a supported standby state. // break; // // default: -// // Do nothing. There are other DG modes that HD standby does not need to act upon them. +// // Do nothing. There are other DD modes that TD standby does not need to act upon them. // break; // } // If DD is communicating and we don't yet have DD version info, request it -// if ( TRUE == isDDCommunicating() ) -// { -// DG_VERSIONS_T ddVersion = getDDVersion(); -// -// if ( 0 == dgVersion.compatibilityRev ) -// { -// sendFWVersionRequest(); -// } -// } + if ( TRUE == isDDCommunicating() ) + { + if ( FALSE == isDDCompatible()) + { + U08 fwVersionRequestPayload[3] = { 0U, 0U, 0U }; + sendMessage( MSG_ID_FW_VERSIONS_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_DD, fwVersionRequestPayload, + sizeof( fwVersionRequestPayload ) ); + } + } + // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). if ( TRUE == treatStartReqReceived ) { @@ -251,22 +289,25 @@ // Initialize treatment modes before starting a new treatment initPreTreatmentMode(); initTreatmentMode(); -// initPostTreatmentMode(); + initPostTreatmentMode(); resetAirTrap(); // Send UI default pressure settings since user is not asked to set them. respRecord.artPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ); - respRecord.venPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ); - respRecord.venPresLimitAsymmetricmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ); + respRecord.venPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_HIGH_LIMIT_WINDOW ); + respRecord.venPresLimitAsymmetricmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_LOW_LIMIT_WINDOW ); respRecord.tmpPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW ); sendPressureLimitsChangeResponse( &respRecord ); - // start DD pre-gen // TODO + // start DD pre-gen // TODO we need to add UF rate as per new requirement + cmdStartPreGenerateDialysate( (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ), getTreatmentParameterF32( TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR ), bicarbConvFactor, getTreatmentParameterU32( TREATMENT_PARAM_SODIUM ), getTreatmentParameterU32( TREATMENT_PARAM_BICARBONATE ) ); // Start treatment workflow with pretreatment mode + // Set fluid type + setFluidType( modality ); requestNewOperationMode( MODE_PRET ); treatStartReqReceived = FALSE; } @@ -276,71 +317,345 @@ /*********************************************************************//** * @brief + * The handleStandbyModeWaitForDisinfectState function handles wait for + * disinfect state. + * @details \b Inputs: flushStartReqReceived, heatDisinfectStartReqReceived, + * chemDisinfectStartReqReceived + * @details \b Outputs: none + * @return next state of the standby mode state machine + *************************************************************************/ +static TD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ) +{ + TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DISINFECT_STATE; + + if ( TRUE == currentDDCleaningMode.startCleaningMode ) + { + switch ( currentDDCleaningMode.ddOpMode ) + { + case DD_MODE_FLUS: + cmdStartDDFlush(); + break; + + case DD_MODE_HEAT: + if ( DD_CMD_START_HEAT_DISINFECT_ACTIVE_COOL == currentDDCleaningMode.startRequestCmdID ) + { + //cmdStartDDHeatDisinfectActiveCool(); + } + else + { + //cmdStartDDHeatDisinfectPassiveCool(); + } + break; + + case DD_MODE_HCOL: + //cmdStartDDActiveCool(); + break; + } + state = STANDBY_WAIT_FOR_DD_CLEANING_MODE_CMD_RESPONSE_STATE; + } + else + { + switch ( getDDOpMode() ) + { + case DD_MODE_FLUS: + case DD_MODE_HEAT: + case DD_MODE_ROPS: + // This is for the situations that any of the disinfect modes are started using the proxy commands while the HD + // is in this state of the Standby Mode. + setRequestedCleaningMode( getDDOpMode(), FALSE ); + state = STANDBY_WAIT_FOR_DD_CLEANING_MODE_TO_START_STATE; + currentDDCleaningMode.startCleaningMode = FALSE; + break; + + default: + // Do nothing we are not in the cleaning mode + break; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The setStandbyWaitForTreatmentActuators function sets TD actuators to + * the required Standby: Wait For Treatment state. + * @details \b Inputs: none + * @details \b Outputs: TD actuators set to standby state. + * @return none + *************************************************************************/ +static void setStandbyWaitForTreatmentActuators( TD_STANDBY_STATE_T state ) +{ + currentStandbyState = state; + // Pumps should be off. + signalBloodPumpHardStop(); + stopSyringePump(); + + // Set air trap valves to closed position. + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + + // Set pinch valves to load / insert-eject position. + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + +// TODO: Add remaining Standby actuator settings when existing control +// functions are confirmed: +// H12 Air Pump Off +// H5 Ejector Off +// Dialyzer Bypassed +// Qd 0 +// Quf 0 +// Qs 0 +} + +/*********************************************************************//** + * @brief + * The setFluidType function sets the fluid type based on the user's + * treatment selection from the home screen. + * @details \b Inputs: none + * @details \b Outputs: fluidType + * @param modality Treatment modality selected by the user on the home screen. + * @return none + *************************************************************************/ +void setFluidType( TREATMENT_TYPE_T modality ) +{ + if ( TREATMENT_MODALITY_HD_SALINE_FLUID == modality ) + { + fluidType = FLUID_TYPE_SALINE; + } + else + { + // For HDF and HD_ONLINE_FLUID + fluidType = FLUID_TYPE_SUBSTITUTE; + } +} + +/*********************************************************************//** + * @brief + * The setRequestedCleaningMode function sets the variables for the requested + * DD cleaning mode. + * @details \b Inputs: currentDDCleaningMode + * @details \b Outputs: none + * @param opMode DD operation mode that has been requested (i.e. heat disinfect) + * @param isHeatDisPassiveCool boolean flag to indicate whether this is a passive + * cool heat disinfect or not. + * @return none + *************************************************************************/ +static void setRequestedCleaningMode( DD_OP_MODE_T opMode, BOOL isHeatDisPassiveCool ) +{ + switch ( opMode ) + { + case DD_MODE_FLUS: + currentDDCleaningMode.startCleaningMode = TRUE; + currentDDCleaningMode.startRequestCmdID = DD_CMD_START_FLUSH; + currentDDCleaningMode.ddOpMode = DD_MODE_FLUS; + currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_DISINFECT_FLUSH; + currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_WATERFLUSH; + break; + +// case DD_MODE_HEAT: +// currentDDCleaningMode.startCleaningMode = TRUE; +// currentDDCleaningMode.startRequestCmdID = ( FALSE == isHeatDisPassiveCool ? DD_CMD_START_HEAT_DISINFECT_ACTIVE_COOL : DD_CMD_START_HEAT_DISINFECT_PASSIVE_COOL ); +// currentDDCleaningMode.ddOpMode = DD_MODE_HEAT; +// currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_DISINFECT_HEAT; +// currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_HEAT; +// break; +// +// case DD_MODE_CHEM: +// currentDDCleaningMode.startCleaningMode = TRUE; +// currentDDCleaningMode.startRequestCmdID = DD_CMD_START_CHEM_DISINFECT; +// currentDDCleaningMode.ddOpMode = DD_MODE_CHEM; +// currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_DISINFECT_CHEM; +// currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_CHEMICAL; +// break; +// +// case DD_MODE_CHFL: +// currentDDCleaningMode.startCleaningMode = TRUE; +// currentDDCleaningMode.startRequestCmdID = DD_CMD_START_CHEM_DISINFECT_FLUSH; +// currentDDCleaningMode.ddOpMode = DD_MODE_CHFL; +// currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_DISINFECT_CHEM_FLUSH; +// currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_CHEMICAL_FLUSH; +// break; +// +// case DD_MODE_HCOL: +// currentDDCleaningMode.startCleaningMode = FALSE; +// currentDDCleaningMode.startRequestCmdID = DD_CMD_START_ACTIVE_COOL; +// currentDDCleaningMode.ddOpMode = DD_MODE_HCOL; +// currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_DISINFECT_HEAT_COOL; +// currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_ACTIVE_COOL; +// break; +// +// case DD_MODE_ROPS: +// currentDDCleaningMode.startCleaningMode = TRUE; +// currentDDCleaningMode.startRequestCmdID = DD_CMD_START_RO_PERMEATE_SAMPLE; +// currentDDCleaningMode.ddOpMode = DD_MODE_ROPS; +// currentDDCleaningMode.sampleRqstTrgrd = FALSE; +// currentDDCleaningMode.alarmID = ALARM_ID_TD_RO_PERMEATE_SAMPLE; +// currentDDCleaningMode.stopRequestCmdID = GENERIC_CONFIRM_ID_DISINFECT_STOP_RO_PERMEATE_SAMPLE; +// break; + } +} + +/*********************************************************************//** + * @brief + * The getFluidType function returns the current fluid type assigned + * based on the user's treatment selection. + * @details \b Inputs: none + * @details \b Outputs: none + * @return Current fluid type (saline or substitution fluid). + *************************************************************************/ +FLUID_TYPE_T getFluidType( void ) +{ + return fluidType; +} + +/*********************************************************************//** + * @brief + * The getModality function returns the treatment modality received from + * the UI at treatment initiation. + * @details \b Inputs: modality + * @details \b Outputs: none + * @return Treatment modality selected by the user on the home screen. + *************************************************************************/ +TREATMENT_TYPE_T getModality( void ) +{ + return modality; +} + +/*********************************************************************//** + * @brief * The signalUserInitiateTreatment function handles user initiation of a * treatment. * @details \b Inputs: none - * @details \b Outputs: treatStartReqReceived + * @details \b Outputs: treatStartReqReceived, modality * @param message initiate/reject treatment workflow message from UI which * includes the command code (0=cancel, 1=initiate). * @return TRUE if signal accepted, FALSE if not *************************************************************************/ BOOL signalUserInitiateTreatment( MESSAGE_T *message ) { BOOL result = FALSE; - U32 cmd = 0; - TD_OP_MODE_T mode = getCurrentOperationMode(); + INITIATE_TREATMENT_REQUEST_PAYLOAD_T cmd; + TD_OP_MODE_T mode = getCurrentOperationMode(); REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + INITIATE_TREATMENT_REQUEST_PAYLOAD_T request; UI_RESPONSE_PAYLOAD_T response; + memset( &cmd, 0, sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) ); + memset( &response, 0, sizeof( UI_RESPONSE_PAYLOAD_T ) ); // Verify message payload length is valid - if ( sizeof( U32 ) == message->hdr.payloadLen ) + if ( sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) == message->hdr.payloadLen ) { - memcpy( &cmd, message->payload, sizeof( U32 ) ); + memcpy( &request, message->payload, sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) ); - if ( USER_COMMAND_INITIATE == cmd ) + cmd.command = request.command; + + if ( USER_COMMAND_INITIATE == cmd.command ) { - // Verify TD is in standby mode waiting for treatment start request - if ( ( mode != MODE_STAN ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) + // Verify TD is in Standby mode and waiting for treatment start request. + if ( ( MODE_STAN != mode ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } + else if ( TRUE == treatStartReqReceived ) + { + rejReason = REQUEST_REJECT_REASON_REQUEST_ALREADY_PENDING; + } + else if ( request.modality >= NUM_OF_TREATMENT_MODALITY_TYPES ) + { + rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; + } #ifndef TEST_UI_ONLY - // Verify DD is communicating with HD - else if ( isDDCommunicating() != TRUE ) + // Verify DD is communicating. + else if ( TRUE != isDDCommunicating() ) { rejReason = REQUEST_REJECT_REASON_DD_COMM_LOST; } - // Verify DD is not busy - else if ( ( DD_MODE_STAN != getDDOpMode() ) || ( DD_STANDBY_MODE_STATE_IDLE != getDDSubMode() ) ) // || ( isDDPOSTPassed() != TRUE ) ) + // Verify DD is ready and not busy with flush/disinfect/cleaning/generation. + else if ( ( DD_MODE_STAN != getDDOpMode() ) || ( DD_STANDBY_MODE_STATE_IDLE != getDDSubMode() ) ) { - rejReason = REQUEST_REJECT_REASON_DD_NOT_IN_STANDBY_IDLE_STATE; + rejReason = REQUEST_REJECT_REASON_DD_BUSY; } + else if ( FALSE == isDDCompatible() ) + { + rejReason = REQUEST_REJECT_REASON_DD_INCOMPATIBLE; + } + // TODO: Need to uncomment below after implementation +// else if ( TRUE == isDDDisinfectionOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_DISINFECT_HAS_BEEN_EXPIRED; +// } +// else if ( TRUE == isDDFlushOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_FILTER_FLUSH_HAS_BEEN_EXPIRED; +// } +// else if ( TRUE == isDDTemperatureTooHigh() ) +// { +// rejReason = REQUEST_REJECT_REASON_DD_TEMPERATURE_OUT_OF_RANGE; +// } +// else if ( TRUE == isDDServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_DD_SERVICE_IS_DUE; +// } +// else if ( TRUE == isTDServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_TD_SERVICE_IS_DUE; +// } +// else if ( FALSE == isFPStandbymode() ) +// { +// rejReason = REQUEST_REJECT_REASON_FP_BUSY; +// } +// else if ( TRUE == isfpServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_FP_SERVICE_IS_DUE; +// } + #endif else { - // If request to start treatment not rejected, set flag to initiate treatment workflow +// Low battery is a warning only, not a rejection. + //TODO +// if ( TRUE == isBatteryRemainingCapacityLessThan60Wh() ) +// { +// SET_ALARM( ALARM_ID_TD_LOW_BATTERY_CHARGE ); +// } + + // If request to start treatment not rejected, set flag to initiate treatment workflow. result = TRUE; treatStartReqReceived = TRUE; + // Save modality to set later + modality = (TREATMENT_TYPE_T)request.modality; } } - else if ( USER_COMMAND_CANCEL == cmd ) + else if ( USER_COMMAND_CANCEL == cmd.command ) { - //result = signalUserCancelTreatment(); - if ( result != TRUE ) + result = signalPreTreatmentBackoutToStandby(); + + if ( TRUE != result ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } } else { - rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; + rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; } } + else + { + rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } - // Respond to request to start treatment - response.accepted = result; + // Respond to request to start treatment. + response.accepted = result; response.rejectionReason = rejReason; - sendMessage( MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( UI_RESPONSE_PAYLOAD_T ) ); + sendMessage( MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*) &response, sizeof( UI_RESPONSE_PAYLOAD_T ) ); return result; } @@ -359,22 +674,23 @@ switch ( action ) { case ALARM_ACTION_STOP: -// if ( isAlarmActive( ALARM_ID_HD_VENOUS_BUBBLE_DETECTED ) != TRUE ) -// { -// // no stop action in standby mode -// } -// // if Dialin enabled bubble detection, stop on venous bubble detection alarm -// else -// { -// // Pumps should be off -// signalBloodPumpHardStop(); -// stopSyringePump(); -// -// // Set valves to safe positions -// setValveAirTrap( STATE_CLOSED ); -// setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); -// setValvePosition( H19, VALVE_POSITION_C_CLOSE ); -// } + if ( isAlarmActive( ALARM_ID_TD_VENOUS_BUBBLE_DETECTED ) != TRUE ) + { + // no stop action in standby mode + } + // if Dialin enabled bubble detection, stop on venous bubble detection alarm + else + { + // Pumps should be off + signalBloodPumpHardStop(); + stopSyringePump(); + + // Set valves to safe positions + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + } break; default: @@ -383,7 +699,48 @@ } } +/*********************************************************************//** + * @brief + * The signalUserInitiateFlushMode function handles user initiation of flush + * mode. + * @details \b Inputs: currentStandbyState + * @details \b Outputs: currentStandbyState + * @return TRUE if signal accepted, FALSE if not + *************************************************************************/ +BOOL signalUserInitiateFlushMode( void ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + UI_RESPONSE_PAYLOAD_T response; + memset( &response, 0, sizeof( UI_RESPONSE_PAYLOAD_T ) ); + if ( MODE_STAN == getCurrentOperationMode() ) + { + if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + { + if ( TRUE == isDDCommunicating() ) + { + setRequestedCleaningMode( DD_MODE_FLUS, FALSE ); + result = TRUE; + currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DD_COMM_LOST; + } + } + } + + // Respond to request to start treatment. + response.accepted = result; + response.rejectionReason = rejReason; + sendMessage( MSG_ID_TD_DISINFECT_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*) &response, sizeof( UI_RESPONSE_PAYLOAD_T ) ); + + return result; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/