/************************************************************************** * * Copyright (c) 2019-2020 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 OperationModes.c * * @date 11-Dec-2019 * @author L. Baloa * * @brief Top-level state machine for the HD operation modes. * **************************************************************************/ #include "ModeDisinfect.h" #include "ModeDrain.h" #include "ModeFill.h" #include "ModeFlush.h" #include "gio.h" #include "OperationModes.h" #include "ModeFault.h" #include "ModeFill.h" #include "ModeInitPOST.h" #include "ModePostTreat.h" #include "ModeService.h" #include "ModeStandby.h" // ********** private data ********** static volatile BOOL modeRequest[NUM_OF_MODES - 1]; static OP_MODE currentMode = MODE_INIT; // this matrix determines legal transitions from one mode to another static const OP_MODE MODE_TRANSITION_TABLE[NUM_OF_MODES - 1][NUM_OF_MODES - 1] = { // from to-> FAULT SERVICE INIT STANBY FILL DRAI FLUS DISI /* FAUL */{ MODE_FAUL, MODE_SERV, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG }, /* SERV */{ MODE_FAUL, MODE_SERV, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG }, /* INIT */{ MODE_FAUL, MODE_NLEG, MODE_INIT, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG }, /* STAN */{ MODE_FAUL, MODE_SERV, MODE_NLEG, MODE_STAN, MODE_FILL, MODE_NLEG, MODE_NLEG, MODE_NLEG }, /* FILL */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_FILL, MODE_NLEG, MODE_NLEG, MODE_NLEG }, /* DRAI */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_DRAI, MODE_NLEG, MODE_NLEG }, /* FLUS */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_FLUS, MODE_NLEG }, /* DISI */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_DISI } }; // ********** private function prototypes ********** static OP_MODE arbitrateModeRequest( void ); static void transitionToNewOperationMode( OP_MODE newMode ); /************************************************************************* * @brief execOperationModes * The execOperationModes function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Operation Modes module initialized. * @param none * @return none *************************************************************************/ void initOperationModes( void ) { U32 i; // initialize mode requests to none pending for ( i = 0; i < ( NUM_OF_MODES - 1 ); i++ ) { modeRequest[i] = FALSE; } // start in init mode currentMode = MODE_INIT; transitionToNewOperationMode( MODE_INIT ); // call initializers for the individual modes initFaultMode(); initServiceMode(); initInitAndPOSTMode(); initStandbyMode(); initFillMode(); initDrainMode(); initFlushMode(); initDisinfectMode(); } /************************************************************************* * @brief execOperationModes * The execOperationModes function executes the Operation Modes state machine. * @details * Inputs : none * Outputs : currentMode is set by state machine. * @param none * @return none *************************************************************************/ void execOperationModes( void ) { OP_MODE newMode; // any new mode requests? newMode = arbitrateModeRequest(); // will return current mode if no pending requests newMode = MODE_TRANSITION_TABLE[currentMode][newMode]; // is requested new mode valid and legal at this time? if ( newMode >= MODE_NLEG ) { // TODO - s/w fault newMode = currentMode; } // has mode changed? if ( currentMode != newMode ) { // handle transition to new mode transitionToNewOperationMode( newMode ); currentMode = newMode; } // mode specific processing to be done continuously switch ( currentMode ) { case MODE_FAUL: execFaultMode(); break; case MODE_SERV: execServiceMode(); break; case MODE_INIT: execInitAndPOSTMode(); break; case MODE_STAN: execStandbyMode(); break; case MODE_FILL: execFillMode(); break; case MODE_DRAI: execDrainMode(); break; case MODE_FLUS: execFlushMode(); break; case MODE_DISI: execDisinfectMode(); break; default: currentMode = MODE_FAUL; // TODO - trigger s/w fault break; } // end switch } /************************************************************************* * @brief requestNewOperationMode * The requestNewOperationMode function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Initializes the Operation Modes module. * @param none * @return none *************************************************************************/ void requestNewOperationMode( OP_MODE newMode ) { // validate requested mode if ( newMode < MODE_NLEG ) { // make request modeRequest[newMode] = TRUE; } else { // invalid mode requested // TODO - trigger s/w fault } } /************************************************************************* * @brief getCurrentOperationMode * The getCurrentOperationMode function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Initializes the Operation Modes module. * @param none * @return none *************************************************************************/ OP_MODE getCurrentOperationMode( void ) { return currentMode; } /************************************************************************* * @brief arbitrateModeRequest * The arbitrateModeRequest function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Initializes the Operation Modes module. * @param none * @return none *************************************************************************/ static OP_MODE arbitrateModeRequest( void ) { OP_MODE reqMode = currentMode; U32 i; // block additional requests until after mode arbitration // TODO - disable priority task // select highest priority mode request -or- current mode if no requests pending for ( i = 0; i < MODE_NLEG; i++ ) { if ( modeRequest[i] != FALSE ) { reqMode = (OP_MODE)i; break; } } // clear all requests now that an arbitration winner is selected for ( i = 0; i < MODE_NLEG; i++ ) { modeRequest[i] = FALSE; } // un-block requests // TODO - enable priority task return reqMode; } /************************************************************************* * @brief transitionToNewOperationMode * The transitionToNewOperationMode function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Initializes the Operation Modes module. * @param none * @return none *************************************************************************/ static void transitionToNewOperationMode( OP_MODE newMode ) { // setup for new operating mode switch ( newMode ) { case MODE_FAUL: transitionToFaultMode(); break; case MODE_SERV: transitionToServiceMode(); break; case MODE_INIT: transitionToInitAndPOSTMode(); break; case MODE_STAN: transitionToStandbyMode(); break; case MODE_FILL: transitionToFillMode(); break; case MODE_DRAI: transitionToDrainMode(); break; case MODE_FLUS: transitionToFlushMode(); break; case MODE_DISI: transitionToDisinfectMode(); break; default: // TODO - s/w fault break; } }