/************************************************************************** * * 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 * * @author (last) Sean Nash * @date (last) 24-Sep-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "gio.h" #include "HDCommon.h" #include "ModeInitPOST.h" #include "ModeService.h" #include "ModeFault.h" #include "ModeStandby.h" #include "ModeTreatmentParams.h" #include "ModePreTreat.h" #include "ModeTreatment.h" #include "ModePostTreat.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" /** * @addtogroup HDOperationModes * @{ */ // ********** private data ********** /// HD operation mode broadcast interval (in task interval/sec). static const U32 BROADCAST_HD_OP_MODE_INTERVAL = ( 250 / TASK_GENERAL_INTERVAL ); // ********** private data ********** static volatile BOOL modeRequest[ NUM_OF_MODES - 1 ]; ///< Pending operation mode change requests. static HD_OP_MODE_T lastMode = MODE_INIT; ///< Last operation mode prior to current mode. static HD_OP_MODE_T currentMode = MODE_INIT; ///< Current operation mode. static U32 currentSubMode = 0; ///< The currently active state of the active mode. static U32 broadcastModeIntervalCtr = 11; ///< Interval counter used to determine when to broadcast operation mode. Initialize to 11 to stagger broadcast. /// This matrix determines legal transitions from one mode to another static const HD_OP_MODE_T MODE_TRANSITION_TABLE[ NUM_OF_MODES - 1 ][ NUM_OF_MODES - 1 ] = { // From to-> FAULT SERVICE INIT STANBY TRT.PARAMS PRE-TREAT TREATMENT POST_TREA /* 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_TPAR, MODE_NLEG, MODE_NLEG, MODE_NLEG, }, /* TPAR */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_TPAR, MODE_PRET, MODE_NLEG, MODE_NLEG, }, /* PRET */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_PRET, MODE_TREA, MODE_POST, }, /* TREA */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_TREA, MODE_POST, }, /* POST */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_POST, }, }; // ********** private function prototypes ********** static HD_OP_MODE_T arbitrateModeRequest( void ); static void transitionToNewOperationMode( HD_OP_MODE_T newMode ); static void broadcastOperationMode( void ); /*********************************************************************//** * @brief * The initOperationModes function initializes the Operation Modes module. * @details Inputs: none * @details Outputs: Operation Modes module initialized. * @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; currentSubMode = 0; transitionToNewOperationMode( MODE_INIT ); // Call initializers for the individual modes initFaultMode(); initServiceMode(); initInitAndPOSTMode(); initStandbyMode(); initTreatParamsMode(); initPreTreatmentMode(); initTreatmentMode(); initPostTreatmentMode(); } /*********************************************************************//** * @brief * The execOperationModes function executes the Operation Modes state machine. * @details Inputs: none * @details Outputs: currentMode is set by state machine. * @return none *************************************************************************/ void execOperationModes( void ) { HD_OP_MODE_T 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 ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_ILLEGAL_MODE_TRANSITION_REQUESTED, newMode ) newMode = currentMode; } // Has mode changed? if ( currentMode != newMode ) { // Handle transition to new mode lastMode = currentMode; transitionToNewOperationMode( newMode ); currentMode = newMode; } // Mode specific processing to be done continuously switch ( currentMode ) { case MODE_FAUL: currentSubMode = execFaultMode(); break; case MODE_SERV: currentSubMode = execServiceMode(); break; case MODE_INIT: currentSubMode = execInitAndPOSTMode(); break; case MODE_STAN: currentSubMode = execStandbyMode(); break; case MODE_TPAR: currentSubMode = execTreatParamsMode(); break; case MODE_PRET: currentSubMode = execPreTreatmentMode(); break; case MODE_TREA: currentSubMode = execTreatmentMode(); break; case MODE_POST: currentSubMode = execPostTreatmentMode(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_STATE, currentMode ) currentMode = MODE_FAUL; currentSubMode = 0; break; } // End switch // Broadcast current operation mode on interval broadcastOperationMode(); } /*********************************************************************//** * @brief * The requestNewOperationMode function requests transition to a new * operation mode. The request will be arbitrated when the state machine * is next executed. * @details Inputs: none * @details Outputs: modeRequest[] * @return none *************************************************************************/ void requestNewOperationMode( HD_OP_MODE_T newMode ) { // Validate requested mode if ( newMode < MODE_NLEG ) { // Make request modeRequest[ newMode ] = TRUE; } else { // Invalid mode requested SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_REQUESTED, newMode ) } } /*********************************************************************//** * @brief * The getCurrentOperationMode function gets the current operation mode. * @details Inputs: currentMode * @details Outputs: none * @return the current operation mode *************************************************************************/ HD_OP_MODE_T getCurrentOperationMode( void ) { return currentMode; } /*********************************************************************//** * @brief * The initiateAlarmAction function initiate an alarm or alarm recovery * action according to the current operation mode. * @details Inputs: currentMode * @details Outputs: given action forwarded to current operation mode for execution * @param action ID of action to be initiated * @return none *************************************************************************/ void initiateAlarmAction( ALARM_ACTION_T action ) { // Forward request to the current operation mode switch ( currentMode ) { case MODE_FAUL: signalAlarmActionToFaultMode( action ); break; case MODE_SERV: signalAlarmActionToServiceMode( action ); break; case MODE_INIT: signalAlarmActionToInitAndPOSTMode( action ); break; case MODE_STAN: signalAlarmActionToStandbyMode( action ); break; case MODE_TPAR: signalAlarmActionToTreatParamsMode( action ); break; case MODE_PRET: signalAlarmActionToPreTreatmentMode( action ); break; case MODE_TREA: signalAlarmActionToTreatmentMode( action ); break; case MODE_POST: signalAlarmActionToPostTreatmentMode( action ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_SIGNAL_ACTION, currentMode ) break; } } /*********************************************************************//** * @brief * The arbitrateModeRequest function arbitrates any pending mode transition * requests. * @details Inputs: modeRequest[] * @details Outputs: modeRequest[] is reset * @return the next operation mode (current mode if no requests pending) *************************************************************************/ static HD_OP_MODE_T arbitrateModeRequest( void ) { HD_OP_MODE_T reqMode = currentMode; U32 i; // Block additional requests until after mode arbitration _disable_IRQ(); // Select highest priority mode request -or- current mode if no requests pending for ( i = 0; i < MODE_NLEG; i++ ) { if ( modeRequest[ i ] != FALSE ) { reqMode = (HD_OP_MODE_T)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 _enable_IRQ(); return reqMode; } /*********************************************************************//** * @brief * The transitionToNewOperationMode function calls the transition to function * for a new operation mode that we are transitioning to. * @details Inputs: none * @details Outputs: transition function called for new mode * @return none *************************************************************************/ static void transitionToNewOperationMode( HD_OP_MODE_T 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_TPAR: transitionToTreatParamsMode(); break; case MODE_PRET: transitionToPreTreatmentMode(); break; case MODE_TREA: transitionToTreatmentMode(); break; case MODE_POST: transitionToPostTreatmentMode(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, newMode ) break; } } /*********************************************************************//** * @brief * The broadcastOperationMode function sends the current operation mode at * the prescribed interval. * @details Inputs: broadcastModeIntervalCtr * @details Outputs: HD operation mode broadcast message sent. * @return none *************************************************************************/ static void broadcastOperationMode( void ) { if ( ++broadcastModeIntervalCtr >= BROADCAST_HD_OP_MODE_INTERVAL ) { broadcastModeIntervalCtr = 0; broadcastHDOperationMode( (U32)currentMode, currentSubMode ); } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetOperationMode function will transition to a given operation * mode if the transition is legal. * @details Inputs: none * @details Outputs: modeRequest[] * @param newMode ID of requested mode to transition to * @return TRUE if request successful, FALSE if not *************************************************************************/ BOOL testSetOperationMode( HD_OP_MODE_T newMode ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { HD_OP_MODE_T check = MODE_TRANSITION_TABLE[ currentMode ][ newMode ]; // Is mode transition legal? if ( check == newMode ) { requestNewOperationMode( newMode ); result = TRUE; } } return result; } /**@}*/