Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rf7b149d8b8c9ea6ac58e4739101693d251d7a355 -r1eac55db00559965a7dc6752fc42a2c54d56f4b9 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision f7b149d8b8c9ea6ac58e4739101693d251d7a355) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 1eac55db00559965a7dc6752fc42a2c54d56f4b9) @@ -23,10 +23,16 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" +#include "ModePostTreat.h" +#include "ModePreTreat.h" +#include "ModeStandby.h" +#include "ModeTreatment.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "SystemComm.h" #include "SystemCommMessages.h" -#include "ModeStandby.h" +#include "TaskGeneral.h" +#include "Timers.h" #ifdef EMC_TEST_BUILD // TODO - test code #include "FPGA.h" #endif @@ -38,14 +44,30 @@ // ********** private definitions ********** +#define DISINFECTS_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Disinfects data publish interval in counts. + // ********** private data ********** -static HD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. +static HD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. -static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of a treatment +static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of a treatment. +static BOOL flushStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of flush mode. +static BOOL heatDisinfectStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of heat disinfect mode. +static BOOL chemDisinfectStartReqReceived = FALSE; ///< Flag indicates user has requested initiation of chemical disinfect mode. +static U32 dataPublishCounter = 0; ///< Disinfects data publish counter. +static BOOL hasDisinfectCmdBeenSet = FALSE; ///< Flag indicates that a disinfect command has been set. +static DG_DISINFECT_STATE_T dgDisinfectState; ///< DG disinfect state to be boadcast to UI. // ********** private function prototypes ********** +static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); +static HD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ); +static HD_STANDBY_STATE_T handleStandbyModeDGFlushInProgressState( void ); +static HD_STANDBY_STATE_T handleStandbyModeDGHeatDisinfectInProgressState( void ); +static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ); + +static void publishDisinfectData( void ); + /*********************************************************************//** * @brief * The initStandbyMode function initializes the Standby Mode module. @@ -55,8 +77,12 @@ *************************************************************************/ void initStandbyMode( void ) { - currentStandbyState = STANDBY_START_STATE; - treatStartReqReceived = FALSE; + currentStandbyState = STANDBY_START_STATE; + treatStartReqReceived = FALSE; + flushStartReqReceived = FALSE; + dataPublishCounter = 0; + hasDisinfectCmdBeenSet = FALSE; + dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; } /*********************************************************************//** @@ -103,30 +129,38 @@ #ifndef RUN_WITHOUT_DG if ( TRUE == stop ) { - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); // TODO - remove alarm? Nothing to stop here. } // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: - // Temporary test code - TODO - remove later - if ( TRUE == isDGCommunicating() ) - { - currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; - } + currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; break; case STANDBY_WAIT_FOR_TREATMENT_STATE: - if ( TRUE == treatStartReqReceived ) - { - requestNewOperationMode( MODE_TPAR ); - treatStartReqReceived = FALSE; - } + currentStandbyState = handleStandbyModeWaitForTreatmentState(); break; + case STANDBY_WAIT_FOR_DISINFECT_STATE: + currentStandbyState = handleStandbyModeWaitForDisinfectState(); + break; + + case STANDBY_DG_FLUSH_IN_PROGRESS_STATE: + currentStandbyState = handleStandbyModeDGFlushInProgressState(); + break; + + case STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE: + currentStandbyState = handleStandbyModeDGHeatDisinfectInProgressState(); + break; + + case STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE: + currentStandbyState = handleStandbyModeDGChemDisininfectInProgressState(); + break; + default: - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); currentStandbyState = STANDBY_START_STATE; break; } @@ -141,6 +175,10 @@ homeDialInPump(); homeDialOutPump(); #ifdef EMC_TEST_BUILD + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); startAirTrapControl(); #endif break; @@ -154,44 +192,43 @@ // TODO - test code if ( TRUE == stop ) { +#ifndef EMC_TEST_BUILD treatStartReqReceived = FALSE; setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); requestNewOperationMode( MODE_TPAR ); -#ifdef EMC_TEST_BUILD +#else if ( stop != button_state ) { toggle = INC_WRAP( toggle, 0, 3 ); switch ( toggle ) { case 0: // Pumps and valves off + setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); break; - case 1: // Pumps on, valves off - setBloodPumpTargetFlowRate( 200, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + case 1: // Pumps off, valves in pos A + 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 ); + break; + + case 2: // Pumps on, valves in pos A + setBloodPumpTargetFlowRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); break; - case 2: // Pumps on, valves on - setValvePosition( VDI, VALVE_POSITION_B_OPEN ); - setValvePosition( VDO, VALVE_POSITION_B_OPEN ); - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - break; - case 3: // Pumps off, valves on - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - break; - default: // Should not get here, reset if we do toggle = 0; setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); @@ -212,7 +249,7 @@ break; default: - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, currentStandbyState ); currentStandbyState = STANDBY_START_STATE; break; } @@ -223,23 +260,45 @@ /*********************************************************************//** * @brief - * The signalUserStartingTreatment function handles user initiation of a + * The signalUserInitiateTreatment function handles user initiation of a * treatment. * @details Inputs: none - * @details Outputs: requested mode transition to treatment parameters mode + * @details Outputs: treatStartReqReceived * @return TRUE if signal accepted, FALSE if not *************************************************************************/ -BOOL signalUserStartingTreatment( void ) +BOOL signalUserInitiateTreatment( void ) { BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; - if ( ( MODE_STAN == getCurrentOperationMode() ) && ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + if ( TRUE == getNoNewTreatmentStatus() ) { - treatStartReqReceived = TRUE; + rejReason = REQUEST_REJECT_REASON_NO_NEW_TREATMENT_ALARM_TRIGGERED; + } + + if ( ( MODE_STAN != getCurrentOperationMode() ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + + if ( TRUE != isDGCommunicating() ) + { + rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; + } + + if ( ( DG_MODE_STAN != getDGOpMode() ) || ( DG_STANDBY_MODE_STATE_IDLE != getDGSubMode() ) ) + { + rejReason = REQUEST_REJECT_REASON_DG_NOT_IN_STANDBY_IDLE_STATE; + } + + if ( REQUEST_REJECT_REASON_NONE == rejReason ) + { result = TRUE; + treatStartReqReceived = TRUE; } - sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected + sendInitiateTreatmentResponseMsg( result, rejReason ); + return result; } @@ -254,7 +313,344 @@ *************************************************************************/ void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ) { - // TODO - implement + // Alarm actions not handled in Standby mode } +/*********************************************************************//** + * @brief + * The signalUserInitiateFlushMode function handles user initiation of flush + * mode. + * @details Inputs: currentStandbyState + * @details Outputs: flushStartReqReceived + * @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; + + if ( MODE_STAN == getCurrentOperationMode() ) + { + if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + { + if ( TRUE == isDGCommunicating() ) + { + flushStartReqReceived = TRUE; + result = TRUE; + currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; + } + } + } + + sendDisinfectConfirmResponse( result, rejReason ); + + return result; +} + +/*********************************************************************//** + * @brief + * The signalUserInitiateFlushMode function handles user initiation of heat + * disinfect mode. + * @details Inputs: currentStandbyState + * @details Outputs: heatDisinfectStartReqReceived + * @return TRUE if signal accepted, FALSE if not + *************************************************************************/ +BOOL signalUserInitiateHeatDisinfectMode( void ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( MODE_STAN == getCurrentOperationMode() ) + { + if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + { + if ( TRUE == isDGCommunicating() ) + { + heatDisinfectStartReqReceived = TRUE; + result = TRUE; + currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; + } + } + } + + sendDisinfectConfirmResponse( result, rejReason ); + + return result; +} + +/*********************************************************************//** + * @brief + * The signalUserInitiateChemicalDisinfectMode function handles user + * initiation of chemical disinfect mode. + * @details Inputs: currentStandbyState + * @details Outputs: chemDisinfectStartReqReceived + * @return TRUE if signal accepted, FALSE if not + *************************************************************************/ +BOOL signalUserInitiateChemicalDisinfectMode( void ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( MODE_STAN == getCurrentOperationMode() ) + { + if ( ( STANDBY_WAIT_FOR_DISINFECT_STATE == currentStandbyState ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + { + if ( TRUE == isDGCommunicating() ) + { + chemDisinfectStartReqReceived = TRUE; + result = TRUE; + currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; + } + } + } + + sendDisinfectConfirmResponse( result, rejReason ); + + return result; +} + +/*********************************************************************//** + * @brief + * The signalInitiateStandbyDisinfectSubmode function handles user + * initiation of setting the disinfects submode. + * @details Inputs: currentStandbyState + * @details Outputs: currentStandbyState + * @return TRUE if signal accepted, FALSE if not + *************************************************************************/ +BOOL signalInitiateStandbyDisinfectSubmode( void ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( ( MODE_STAN == getCurrentOperationMode() ) && ( STANDBY_WAIT_FOR_TREATMENT_STATE == currentStandbyState ) ) + { + if ( TRUE == isDGCommunicating() ) + { + currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; + result = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_DG_COMM_LOST; + } + } + + sendDisinfectConfirmResponse( result, rejReason ); + + return result; +} + +// ********** private functions ********** + +/*********************************************************************//** + * @brief + * The handleStandbyModeWaitForTreatmentState function handles wait for + * treatment state. + * @details Inputs: treatStartReqReceived + * @details Outputs: treatStartReqReceived + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) +{ + HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; + + if ( TRUE == treatStartReqReceived ) + { + // Initialize treatment modes before starting a new treatment + initTreatParamsMode(); + initPreTreatmentMode(); + initTreatmentMode(); + initPostTreatmentMode(); + // Start treatment workflow with treatment parameters mode + requestNewOperationMode( MODE_TPAR ); + treatStartReqReceived = FALSE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleStandbyModeWaitForDisinfectState function handles wait for + * disinfect state. + * @details Inputs: flushStartReqReceived, heatDisinfectStartReqReceived, + * chemDisinfectStartReqReceived, hasDisinfectCmdBeenSet + * @details Outputs: flushStartReqReceived, heatDisinfectStartReqReceived, + * chemDisinfectStartReqReceived, hasDisinfectCmdBeenSet, dgDisinfectState, + * currentStandbyState + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ) +{ + HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_DISINFECT_STATE; + + if ( TRUE == flushStartReqReceived ) + { + if ( FALSE == hasDisinfectCmdBeenSet ) + { + cmdStartDGFlush(); + hasDisinfectCmdBeenSet = TRUE; + } + else if ( DG_MODE_FLUS == getDGOpMode() ) + { + hasDisinfectCmdBeenSet = FALSE; + flushStartReqReceived = FALSE; + dgDisinfectState = DG_DISINFECT_FLUSH_STATE; + state = STANDBY_DG_FLUSH_IN_PROGRESS_STATE; + } + } + else if ( TRUE == heatDisinfectStartReqReceived ) + { + if ( FALSE == hasDisinfectCmdBeenSet ) + { + cmdStartDGHeatDisinfect(); + hasDisinfectCmdBeenSet = TRUE; + } + else if ( DG_MODE_HEAT == getDGOpMode() ) + { + hasDisinfectCmdBeenSet = FALSE; + heatDisinfectStartReqReceived = FALSE; + dgDisinfectState = DG_DISINFECT_HEAT_STATE; + state = STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE; + } + } + else if ( TRUE == chemDisinfectStartReqReceived ) + { + if ( FALSE == hasDisinfectCmdBeenSet ) + { + cmdStartDGChemicalDisinfect(); + hasDisinfectCmdBeenSet = TRUE; + } + else if ( DG_MODE_CHEM == getDGOpMode() ) + { + hasDisinfectCmdBeenSet = FALSE; + chemDisinfectStartReqReceived = FALSE; + dgDisinfectState = DG_DISINFECT_CHEM_STATE; + state = STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleStandbyModeDGFlushInProgressState function handles DG flush + * in progress state. + * @details Inputs: none + * @details Outputs: dgDisinfectState, currentStandbyState + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeDGFlushInProgressState( void ) +{ + HD_STANDBY_STATE_T state = STANDBY_DG_FLUSH_IN_PROGRESS_STATE; + + if ( getDGOpMode() != DG_MODE_FLUS ) + { + dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; + state = STANDBY_WAIT_FOR_TREATMENT_STATE; + } + publishDisinfectData(); + + return state; +} + +/*********************************************************************//** + * @brief + * The handleStandbyModeDGHeatDisinfectInProgressState function handles DG + * heat disinfect in progress state. + * @details Inputs: none + * @details Outputs: dgDisinfectState, currentStandbyState + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeDGHeatDisinfectInProgressState( void ) +{ + HD_STANDBY_STATE_T state = STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE; + + if ( getDGOpMode() != DG_MODE_HEAT ) + { + dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; + state = STANDBY_WAIT_FOR_TREATMENT_STATE; + } + publishDisinfectData(); + + return state; +} + +/*********************************************************************//** + * @brief + * The handleStandbyModeDGChemDisininfectInProgressState function handles + * DG chemical disinfect in progress state. + * @details Inputs: none + * @details Outputs: dgDisinfectState, currentStandbyState + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ) +{ + HD_STANDBY_STATE_T state = STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE; + + if ( getDGOpMode() != DG_MODE_CHEM ) + { + dgDisinfectState = DG_DISINFECT_NOT_RUNNING_STATE; + state = STANDBY_WAIT_FOR_TREATMENT_STATE; + } + publishDisinfectData(); + + return state; +} + +/*********************************************************************//** + * @brief + * The publishDisinfectData function publishes disinfects data at + * the set interval. + * @details Inputs: dataPublishCounter + * @details Outputs: dataPublishCounter + * @return: none + *************************************************************************/ +static void publishDisinfectData( void ) +{ + if ( ++dataPublishCounter > DISINFECTS_DATA_PUB_INTERVAL ) + { + DG_DISINFECT_UI_STATES_T state = getDGDisinfectsStates(); + DISINFECTS_DATA_T data; + + switch( currentStandbyState ) + { + case STANDBY_DG_FLUSH_IN_PROGRESS_STATE: + data.disinfectDGFlushState = state.flushUIState; + break; + + case STANDBY_DG_HEAT_DISINFECT_IN_PROGRESS_STATE: + data.disinfectDGHeatState = state.heatDisinfectUIState; + break; + + case STANDBY_DG_CHEM_DISINFECT_IN_PROGRESS_STATE: + data.disinfectDGChemState = state.chemDisinfectUIState; + break; + } + + data.disinfectSubModeHDState = (U32)dgDisinfectState; + + broadcastDisinfectsData( &data ); + + dataPublishCounter = 0; + } +} + /**@}*/