/************************************************************************** * * Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeStandby.c * * @author (last) Vinayakam Mani * @date (last) 06-Aug-2024 * * @author (original) Vinayakam Mani * @date (original) 06-Aug-2024 * ***************************************************************************/ #include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "Heaters.h" #include "ModeFault.h" #include "ModeStandby.h" #include "MessageSupport.h" #include "Messaging.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressure.h" #include "SystemCommDD.h" #include "TaskGeneral.h" //#include "Timers.h" #include "Valves.h" /** * @addtogroup DDStandbyMode * @{ */ // ********** private definitions ********** // ********** private data ********** static DD_STANDBY_MODE_STATE_T standbyState; ///< Currently active standby state. static OVERRIDE_U32_T pendingStartDDRequest; ///< Flag indicating TD has requested DD start the dialysis delivery(Overridable). //static BOOL pendingStartDDFlushRequest; ///< Flag indicating TD has requested DD start flush. //static BOOL pendingStartDDHeatDisinfectRequest; ///< Flag indicating TD has requested DD start heat disinfect. //static BOOL pendingStartDDHeatDisinfectActiveCoolRequest; ///< Flag indicating TD has requested DD start heat disinfect active cool. //static BOOL pendingStartDGROPermeateSampleRequest; ///< Flag indicating TD has requested DD to command RO to start permeate sample. // ********** private function prototypes ********** static DD_STANDBY_MODE_STATE_T handleStandbyIdleState( void ); static DD_STANDBY_MODE_STATE_T handleStandbyPauseState( void ); /*********************************************************************//** * @brief * The initStandbyMode function initializes the standby mode unit. * @details \b Inputs: none * @details \b Outputs:unit variables initialized. * @return none *************************************************************************/ void initStandbyMode( void ) { standbyState = DD_STANDBY_MODE_STATE_IDLE; pendingStartDDRequest.data = FALSE; pendingStartDDRequest.ovData = FALSE; pendingStartDDRequest.ovInitData = FALSE; pendingStartDDRequest.override = OVERRIDE_RESET; // pendingStartDDFlushRequest = FALSE; // pendingStartDDHeatDisinfectRequest = FALSE; // pendingStartDDHeatDisinfectActiveCoolRequest = FALSE; // pendingStartDDROPermeateSampleRequest = FALSE; } /*********************************************************************//** * @brief * The transitionToStandbyMode function prepares for transition to standby mode. * while transition, deenergize all actuators and update DD usage info to TD module. * @details \b Inputs: none * @details \b Outputs: Re-initialized standby mode * @return initial state *************************************************************************/ U32 transitionToStandbyMode( void ) { // MESSAGE_T usageMsg; // re-initialize standby mode each time we transition to standby mode initStandbyMode(); deenergizeActuators( PARK_CONC_PUMPS ); // // Upon transition to mode standby set CD1 and CD2 calibration records to be picked to the normal // // table. If the chemical disinfect fails, the mode transitions back to mode standby. // setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD1_SENSOR, CAL_DATA_CD1_COND_SENSOR ); // setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR ); // // // Send DD usage data to TD // The message ID will not be put here because the messages list script will pick this up for another send command // The only important item is the payload length that must be 0 for the handler // usageMsg.hdr.msgID = 0; // usageMsg.hdr.payloadLen = 0; //handleTDRequestDDUsageInfo( &usageMsg ); return standbyState; } /*********************************************************************//** * @brief * The execStandbyMode function executes the standby mode state machine. * @details \b Inputs: none * @details \b Outputs: Standby mode state machine executed * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if stanbyState is invalid. * @return current state *************************************************************************/ U32 execStandbyMode( void ) { if ( TRUE == areInletWaterConditionsAlarmsActive() ) { standbyState = DD_STANDBY_MODE_STATE_PAUSE; } // execute current Standby state switch ( standbyState ) { case DD_STANDBY_MODE_STATE_IDLE: standbyState = handleStandbyIdleState(); break; case DD_STANDBY_MODE_STATE_PAUSE: standbyState = handleStandbyPauseState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_STANDBY_MODE_INVALID_EXEC_STATE, standbyState ) standbyState = DD_STANDBY_MODE_STATE_IDLE; break; } return standbyState; } /*********************************************************************//** * @brief * The areInletWaterConditionsAlarmsActive function checks whether the inlet * water pressure conditions are out of range and any of their alarms are active. * @details \b Inputs: Input and Output pressure of water inlet pressur regulator. * @details \b Outputs: None * @return TRUE if any of the alarms are active, otherwise, FALSE *************************************************************************/ BOOL areInletWaterConditionsAlarmsActive( void ) { BOOL status = FALSE; // Check Inlet Water Pressure - both Water inlet pressure Input, pressure Output after pressure regulator. checkInletWaterPressure(); // Check any active alarms status |= isAlarmActive( ALARM_ID_DD_INLET_WATER_PRESSURE_OUT_LOW_RANGE ); status |= isAlarmActive( ALARM_ID_DD_INLET_WATER_PRESSURE_OUT_HIGH_RANGE ); status |= isAlarmActive( ALARM_ID_DD_INLET_WATER_PRESSURE_IN_HIGH_RANGE ); status |= isAlarmActive( ALARM_ID_DD_INLET_WATER_PRESSURE_IN_LOW_RANGE ); return status; } /*********************************************************************//** * @brief * The handleStandbyIdleState function executes the idle state of the * standby mode state machine. * @details \b Inputs: pendingSampleWaterRequest, pendingStartDDRequest, * pendingStartDDFlushRequest, pendingStartDDHeatDisinfectRequest, * pendingStartDDChemicalDisinfectRequest * @details \b Outputs: Idle state of the standby mode executed, * pendingStartDDFlushRequest, pendingStartDDHeatDisinfectRequest, * pendingStartDDChemicalDisinfectRequest * @details \b Message \Sent: DD_EVENT_TD_COMMUNICATION_LOSS ( Evend Id:8 ) * updates TD communication loss. * @return the next state *************************************************************************/ static DD_STANDBY_MODE_STATE_T handleStandbyIdleState( void ) { DD_STANDBY_MODE_STATE_T state = DD_STANDBY_MODE_STATE_IDLE; // go to standby solo mode if TD is turned off or stops communicating. if ( FALSE == isTDCommunicating() ) { // TODO if TD comm loss, do we need solo standby? SEND_EVENT_WITH_2_U32_DATA( DD_EVENT_TD_COMMUNICATION_LOSS, 0, 0 ) //requestNewOperationMode( DD_MODE_SOLO ); } else if ( TRUE == getU32OverrideValue( &pendingStartDDRequest ) ) { pendingStartDDRequest.data = FALSE; requestNewOperationMode( DD_MODE_GEND ); } // else if ( TRUE == pendingStartDDFlushRequest ) // { // pendingStartDDFlushRequest = FALSE; // requestNewOperationMode( DD_MODE_FLUS ); // } // else if ( TRUE == pendingStartDDHeatDisinfectRequest ) // { // pendingStartDDHeatDisinfectRequest = FALSE; // requestNewOperationMode( DD_MODE_HEAT ); // } // else if ( TRUE == pendingStartDDHeatDisinfectActiveCoolRequest ) // { // pendingStartDDHeatDisinfectActiveCoolRequest = FALSE; // // requestNewOperationMode( DD_MODE_HCOL ); // } // else if ( TRUE == pendingStartDDROPermeateSampleRequest ) // { // pendingStartDDROPermeateSampleRequest = FALSE; // requestNewOperationMode( DD_MODE_ROPS ); // } return state; } /*********************************************************************//** * @brief * The handleStandbyPauseState function executes the standby pause state. * @details \b Inputs: Water inlet pressure alarms * @details \b Outputs: state * @return the next state *************************************************************************/ static DD_STANDBY_MODE_STATE_T handleStandbyPauseState( void ) { DD_STANDBY_MODE_STATE_T state = DD_STANDBY_MODE_STATE_PAUSE; if ( FALSE == areInletWaterConditionsAlarmsActive() ) { state = DD_STANDBY_MODE_STATE_IDLE; } return state; } /*********************************************************************//** * @brief * The requestDDStart function handles an TD request to start (go to generation dialysis mode). * @details \b Inputs: standbyState * @details \b Outputs: pendingStartDDRequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ BOOL requestDDStart( void ) { BOOL result = FALSE; if ( DD_STANDBY_MODE_STATE_IDLE == standbyState ) { result = TRUE; pendingStartDDRequest.data = TRUE; } return result; } /*********************************************************************//** * @brief * The startDDFlush function starts DD flush mode. * @details \b Inputs: standbyState * @details \b Outputs: none * @return: TRUE if the switch was successful, otherwise FALSE *************************************************************************/ BOOL startDDFlush( void ) { BOOL result = FALSE; // // If DD is in standby mode or in the solo mode and the standby mode is in Idle state, request DD flush // if ( ( DD_MODE_STAN == getCurrentOperationMode() ) && ( DD_STANDBY_MODE_STATE_IDLE == standbyState ) || ( DD_MODE_SOLO == getCurrentOperationMode() ) ) // { // DD_CMD_RESPONSE_T cmdResponse; // DD_USAGE_INFO_RECORD_T usageInfo; // // getNVRecord2Driver( GET_USAGE_RECORD, (U08*)&usageInfo, sizeof( DD_USAGE_INFO_RECORD_T ), 0, ALARM_ID_NO_ALARM ); // // OPN_CLS_STATE_T concCap = getSwitchStatus( CONCENTRATE_CAP ); // OPN_CLS_STATE_T diaCap = getSwitchStatus( DIALYSATE_CAP ); // cmdResponse.commandID = DD_CMD_START_FLUSH; // cmdResponse.rejected = FALSE; // cmdResponse.rejectCode = DD_CMD_REQUEST_REJECT_REASON_NONE; // //#ifndef _RELEASE_ // if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) ) // { // concCap = STATE_CLOSED; // diaCap = STATE_CLOSED; // // Using the caps switch to disable the chemical disinfect date checks // // This is for debug builds only to simulate that a chem flush has been done after chem // usageInfo.lastChemDisFlushCompleteDateEpoch = 40; // usageInfo.lastChemDisStartDateEpoch = 32; // } //#endif // // if ( ( STATE_OPEN == concCap ) || ( STATE_OPEN == diaCap ) ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ? REQUEST_REJECT_REASON_DD_DIALYSATE_CAP_OPEN : // REQUEST_REJECT_REASON_DD_CONCENTRATE_CAP_OPEN ); // } // else if ( usageInfo.lastChemDisFlushCompleteDateEpoch < usageInfo.lastChemDisStartDateEpoch ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = REQUEST_REJECT_REASON_DD_CHEM_FLUSH_NOT_COMPLETED; // } // else // { // pendingStartDDFlushRequest = TRUE; // result = TRUE; // } // // sendCommandResponseMsg( &cmdResponse ); // } return result; } /*********************************************************************//** * @brief * The startDDHeatDisinfect function starts heat disinfect mode. * @details \b Inputs: standbyState * @details \b Outputs: none * @return: TRUE if the switch was successful *************************************************************************/ BOOL startDDHeatDisinfect( void ) { BOOL status = FALSE; // // If DD is in standby mode and the standby mode is in Idle state or if DD is in solo mode, request DD heat disinfect // if ( ( ( DD_MODE_STAN == getCurrentOperationMode() ) && ( DD_STANDBY_MODE_STATE_IDLE == standbyState ) ) || ( DD_MODE_SOLO == getCurrentOperationMode() ) ) // { // DD_CMD_RESPONSE_T cmdResponse; // DD_USAGE_INFO_RECORD_T usageInfo; // OPN_CLS_STATE_T concCap = getSwitchStatus( CONCENTRATE_CAP ); // OPN_CLS_STATE_T diaCap = getSwitchStatus( DIALYSATE_CAP ); // // getNVRecord2Driver( GET_USAGE_RECORD, (U08*)&usageInfo, sizeof( DD_USAGE_INFO_RECORD_T ), 0, ALARM_ID_NO_ALARM ); // // cmdResponse.commandID = DD_CMD_START_HEAT_DISINFECT; // cmdResponse.rejected = FALSE; // cmdResponse.rejectCode = DD_CMD_REQUEST_REJECT_REASON_NONE; // //#ifndef _RELEASE_ // if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) ) // { // concCap = STATE_CLOSED; // diaCap = STATE_CLOSED; // // Using the caps switch to disable the chemical disinfect date checks // // This is for debug builds only to simulate that a chem flush has been done after chem // usageInfo.lastChemDisFlushCompleteDateEpoch = 40; // usageInfo.lastChemDisStartDateEpoch = 32; // } //#endif // // if ( ( STATE_OPEN == concCap ) || ( STATE_OPEN == diaCap ) ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ? REQUEST_REJECT_REASON_DD_DIALYSATE_CAP_OPEN : // REQUEST_REJECT_REASON_DD_CONCENTRATE_CAP_OPEN ); // } // else if ( usageInfo.lastChemDisFlushCompleteDateEpoch < usageInfo.lastChemDisStartDateEpoch ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = REQUEST_REJECT_REASON_DD_CHEM_FLUSH_NOT_COMPLETED; // } // else // { // pendingStartDDHeatDisinfectRequest = TRUE; // status = TRUE; // } // // sendCommandResponseMsg( &cmdResponse ); // } return status; } /*********************************************************************//** * @brief * The startDDHeatDisinfectActiveCool function starts heat disinfect active * cool mode. * @details \b Inputs: standbyState * @details \b Outputs: none * @return: TRUE if the switch was successful *************************************************************************/ BOOL startDDHeatDisinfectActiveCool( void ) { BOOL status = FALSE; // // If DD is in standby mode and the standby mode is in Idle state or if DD is in solo mode, request DD heat disinfect // if ( ( DD_MODE_STAN == getCurrentOperationMode() ) && ( DD_STANDBY_MODE_STATE_IDLE == standbyState ) || ( DD_MODE_SOLO == getCurrentOperationMode() ) ) // { // DD_CMD_RESPONSE_T cmdResponse; // DD_USAGE_INFO_RECORD_T usageInfo; // OPN_CLS_STATE_T concCap = getSwitchStatus( CONCENTRATE_CAP ); // OPN_CLS_STATE_T diaCap = getSwitchStatus( DIALYSATE_CAP ); // // getNVRecord2Driver( GET_USAGE_RECORD, (U08*)&usageInfo, sizeof( DD_USAGE_INFO_RECORD_T ), 0, ALARM_ID_NO_ALARM ); // // cmdResponse.commandID = DD_CMD_START_HEAT_DISINFECT; // cmdResponse.rejected = FALSE; // cmdResponse.rejectCode = DD_CMD_REQUEST_REJECT_REASON_NONE; // //#ifndef _RELEASE_ // if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) ) // { // concCap = STATE_CLOSED; // diaCap = STATE_CLOSED; // // Using the caps switch to disable the chemical disinfect date checks // // This is for debug builds only to simulate that a chem flush has been done after chem // usageInfo.lastChemDisFlushCompleteDateEpoch = 40; // usageInfo.lastChemDisStartDateEpoch = 32; // } //#endif // // if ( ( STATE_OPEN == concCap ) || ( STATE_OPEN == diaCap ) ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ? REQUEST_REJECT_REASON_DD_DIALYSATE_CAP_OPEN : // REQUEST_REJECT_REASON_DD_CONCENTRATE_CAP_OPEN ); // } // else if ( usageInfo.lastChemDisFlushCompleteDateEpoch < usageInfo.lastChemDisStartDateEpoch ) // { // cmdResponse.rejected = TRUE; // cmdResponse.rejectCode = REQUEST_REJECT_REASON_DD_CHEM_FLUSH_NOT_COMPLETED; // } // else // { // pendingStartDDHeatDisinfectActiveCoolRequest = TRUE; // status = TRUE; // } // // sendCommandResponseMsg( &cmdResponse ); // } return status; } /*********************************************************************//** * @brief * The getCurrentStandbyState function returns the current state of standby mode. * @details \b Inputs: standbyState * @details \b Outputs: none * @return the current state of standby mode. *************************************************************************/ DD_STANDBY_MODE_STATE_T getCurrentStandbyState( void ) { return standbyState; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testDDstartGenDialysateOverride function sets the override value * to start the gen dialysate operation mode. * @details Inputs: pendingStartDDRequest * @details Outputs: pendingStartDDRequest * @param message Override message from Dialin which includes the flag * to override the operation mode. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDstartGenDialysateOverride( MESSAGE_T *message ) { BOOL result = u32Override( message, &pendingStartDDRequest, FALSE, TRUE ); return result; } /**@}*/