Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r499e5de29e706d09f79ba22511068990c4044e84 -r0dec8744af40d0c87a6d7cd1923920c1c2bd1d2f --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 499e5de29e706d09f79ba22511068990c4044e84) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 0dec8744af40d0c87a6d7cd1923920c1c2bd1d2f) @@ -1,111 +1,140 @@ /************************************************************************** - * - * 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. - * - **************************************************************************/ +* +* 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) Quang Nguyen +* @date (last) 21-Jul-2020 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ -#include "ModeDisinfect.h" -#include "ModeDrain.h" -#include "ModeFill.h" -#include "ModeFlush.h" #include "gio.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" #include "OperationModes.h" - +#include "ModeChemicalDisinfect.h" +#include "ModeDrain.h" #include "ModeFault.h" #include "ModeFill.h" +#include "ModeFlush.h" +#include "ModeHeatDisinfect.h" #include "ModeInitPOST.h" -#include "ModePostTreat.h" +#include "ModeRecirculate.h" #include "ModeService.h" +#include "ModeSolo.h" #include "ModeStandby.h" +/** + * @addtogroup DGOperationModes + * @{ + */ + +// ********** private definitions ********** + +#define BROADCAST_DG_OP_MODE_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the op mode is published on the CAN bus. + // ********** private data ********** -static volatile BOOL modeRequest[NUM_OF_MODES - 1]; -static OP_MODE currentMode = MODE_INIT; +static volatile BOOL modeRequest[NUM_OF_DG_MODES - 1]; ///< Array of mode request flags. +static DG_OP_MODE_T currentMode = DG_MODE_INIT; ///< The currently active mode. +static U32 currentSubMode = 0; ///< The currently active state of the active mode. +static U32 broadcastModeIntervalCtr = 11; ///< Interval counter used to determine when to broadcase operation mode. Initialize to 11 to stagger broadcast. -// 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] = +/// This matrix determines legal transitions from one mode to another. +static const DG_OP_MODE_T MODE_TRANSITION_TABLE[NUM_OF_DG_MODES - 1][NUM_OF_DG_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 } +// from to-> FAULT SERVICE INIT STANBY STBY-SOLO RE-CIRC FILL DRAIN FLUSH HEAT DIS CHEM DIS + /* FAUL */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* SERV */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* INIT */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_CIRC, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_NLEG, DG_MODE_CHEM }, + /* SOLO */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG }, + /* CIRC */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_CIRC, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* FILL */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_CIRC, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* DRAI */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_CIRC, DG_MODE_NLEG, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* FLUS */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_NLEG, DG_MODE_NLEG }, + /* HEAT */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_HEAT, DG_MODE_NLEG }, + /* CHEM */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_CHEM } }; +static U32 dgOpModePublicationTimerCounter = 0; + // ********** private function prototypes ********** -static OP_MODE arbitrateModeRequest( void ); -static void transitionToNewOperationMode( OP_MODE newMode ); +static DG_OP_MODE_T arbitrateModeRequest( void ); +static void transitionToNewOperationMode( DG_OP_MODE_T newMode ); +static void broadcastOperationMode( void ); -/************************************************************************* +/*********************************************************************//** * @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++ ) + for ( i = 0; i < ( NUM_OF_DG_MODES - 1 ); i++ ) { modeRequest[i] = FALSE; } // start in init mode - currentMode = MODE_INIT; - transitionToNewOperationMode( MODE_INIT ); +#ifndef CAN_TEST + currentMode = DG_MODE_INIT; +#else + currentMode = DG_MODE_FAUL; +#endif + currentSubMode = 0; + transitionToNewOperationMode( DG_MODE_INIT ); // call initializers for the individual modes initFaultMode(); initServiceMode(); initInitAndPOSTMode(); initStandbyMode(); + initSoloMode(); + initRecirculateMode(); initFillMode(); initDrainMode(); initFlushMode(); - initDisinfectMode(); + initHeatDisinfectMode(); + initChemicalDisinfectMode(); + + // initialize broadcast timer counter + dgOpModePublicationTimerCounter = 0; } -/************************************************************************* +/*********************************************************************//** * @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; + DG_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 ) + if ( newMode >= DG_MODE_NLEG ) { // TODO - s/w fault newMode = currentMode; @@ -122,58 +151,76 @@ // mode specific processing to be done continuously switch ( currentMode ) { - case MODE_FAUL: - execFaultMode(); + case DG_MODE_FAUL: + currentSubMode = execFaultMode(); break; - case MODE_SERV: - execServiceMode(); + case DG_MODE_SERV: + currentSubMode = execServiceMode(); break; - case MODE_INIT: - execInitAndPOSTMode(); + case DG_MODE_INIT: + currentSubMode = execInitAndPOSTMode(); break; - case MODE_STAN: - execStandbyMode(); + case DG_MODE_STAN: + currentSubMode = execStandbyMode(); break; - case MODE_FILL: - execFillMode(); + case DG_MODE_SOLO: + currentSubMode = execSoloMode(); break; - case MODE_DRAI: - execDrainMode(); + case DG_MODE_CIRC: + currentSubMode = execRecirculateMode(); break; - case MODE_FLUS: - execFlushMode(); + case DG_MODE_FILL: + currentSubMode = execFillMode(); break; - case MODE_DISI: - execDisinfectMode(); + case DG_MODE_DRAI: + currentSubMode = execDrainMode(); break; + case DG_MODE_FLUS: + currentSubMode = execFlushMode(); + break; + + case DG_MODE_HEAT: + currentSubMode = execHeatDisinfectMode(); + break; + + case DG_MODE_CHEM: + currentSubMode = execChemicalDisinfectMode(); + break; + default: - currentMode = MODE_FAUL; // TODO - trigger s/w fault + currentMode = DG_MODE_FAUL; + currentSubMode = 0; break; } // end switch + +#ifndef CAN_TEST + // publish op mode on interval + broadcastOperationMode(); +#endif } -/************************************************************************* +/*********************************************************************//** * @brief requestNewOperationMode - * The requestNewOperationMode function initializes the Operation Modes module. + * The requestNewOperationMode function requests a new operation mode. * @details * Inputs : none - * Outputs : Initializes the Operation Modes module. - * @param none + * Outputs : makes the requested mode "pending". + * @param newMode : requested mode * @return none *************************************************************************/ -void requestNewOperationMode( OP_MODE newMode ) +void requestNewOperationMode( DG_OP_MODE_T newMode ) { // validate requested mode - if ( newMode < MODE_NLEG ) + if ( newMode < DG_MODE_NLEG ) { // make request modeRequest[newMode] = TRUE; @@ -184,100 +231,126 @@ } } -/************************************************************************* +/*********************************************************************//** * @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 ) +DG_OP_MODE_T 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 ) +static DG_OP_MODE_T arbitrateModeRequest( void ) { - OP_MODE reqMode = currentMode; + DG_OP_MODE_T reqMode = currentMode; U32 i; // block additional requests until after mode arbitration - // TODO - disable priority task + _disable_IRQ(); // select highest priority mode request -or- current mode if no requests pending - for ( i = 0; i < MODE_NLEG; i++ ) + for ( i = 0; i < DG_MODE_NLEG; i++ ) { if ( modeRequest[i] != FALSE ) { - reqMode = (OP_MODE)i; + reqMode = (DG_OP_MODE_T)i; break; } } // clear all requests now that an arbitration winner is selected - for ( i = 0; i < MODE_NLEG; i++ ) + for ( i = 0; i < DG_MODE_NLEG; i++ ) { modeRequest[i] = FALSE; } // un-block requests - // TODO - enable priority task + _enable_IRQ(); return reqMode; } -/************************************************************************* +/*********************************************************************//** * @brief transitionToNewOperationMode * The transitionToNewOperationMode function initializes the Operation Modes module. * @details * Inputs : none * Outputs : Initializes the Operation Modes module. - * @param none + * @param newMode : new op mode to transition to * @return none *************************************************************************/ -static void transitionToNewOperationMode( OP_MODE newMode ) +static void transitionToNewOperationMode( DG_OP_MODE_T newMode ) { // setup for new operating mode switch ( newMode ) { - case MODE_FAUL: + case DG_MODE_FAUL: transitionToFaultMode(); break; - case MODE_SERV: + case DG_MODE_SERV: transitionToServiceMode(); break; - case MODE_INIT: + case DG_MODE_INIT: transitionToInitAndPOSTMode(); break; - case MODE_STAN: + case DG_MODE_STAN: transitionToStandbyMode(); break; - case MODE_FILL: + case DG_MODE_SOLO: + transitionToSoloMode(); + break; + case DG_MODE_CIRC: + transitionToRecirculateMode(); + break; + case DG_MODE_FILL: transitionToFillMode(); break; - case MODE_DRAI: + case DG_MODE_DRAI: transitionToDrainMode(); break; - case MODE_FLUS: + case DG_MODE_FLUS: transitionToFlushMode(); break; - case MODE_DISI: - transitionToDisinfectMode(); + case DG_MODE_HEAT: + transitionToHeatDisinfectMode(); break; + case DG_MODE_CHEM: + transitionToChemicalDisinfectMode(); + break; default: - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, 0, (U32)newMode ) // TODO - add s/w fault enum to 1st data param break; } } +/*********************************************************************//** + * @brief + * The broadcastOperationMode function sends the current operation mode at \n + * the prescribed interval. + * @details + * Inputs : broadcastModeIntervalCtr + * Outputs : DG operation mode broadcast message sent. + * @return none + *************************************************************************/ +static void broadcastOperationMode( void ) +{ + if ( ++broadcastModeIntervalCtr >= BROADCAST_DG_OP_MODE_INTERVAL ) + { + broadcastModeIntervalCtr = 0; + broadcastDGOperationMode( (U32)currentMode, currentSubMode ); + } +} + +/**@}*/