Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -rd70d93528b59ef7b09032a3bf4128bee0ff6e297 -rf847ac4a7a0a080c4b62886243f5b863c4e7730d --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision d70d93528b59ef7b09032a3bf4128bee0ff6e297) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision f847ac4a7a0a080c4b62886243f5b863c4e7730d) @@ -7,8 +7,8 @@ * * @file OperationModes.c * -* @author (last) Dara Navaei -* @date (last) 17-Jan-2023 +* @author (last) Michael Garthwaite +* @date (last) 18-Sep-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -28,6 +28,7 @@ #include "ModeHeatDisinfect.h" #include "ModeHeatDisinfectActiveCool.h" #include "ModeInitPOST.h" +#include "ModeROPermeateSample.h" #include "ModeService.h" #include "ModeSolo.h" #include "ModeStandby.h" @@ -57,25 +58,26 @@ /// DG operation mode data publish interval. static OVERRIDE_U32_T dgOpModePublishInterval = { BROADCAST_DG_OP_MODE_INTERVAL, BROADCAST_DG_OP_MODE_INTERVAL, 0, 0 }; static U32 dataPublishCounter; ///< Interval counter used to determine when to broadcast operation mode. Initialize to 11 to stagger broadcast. -static U32 priorSubMode; ///< The prior submode state. +static U32 currentSubState; ///< The currently active sub state. /// 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 STBY-SOLO GEN-IDLE FILL DRAIN FLUSH HEAT DIS CHEM DIS CHEM_FLUSH HEAT_COOL - /* 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, 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, 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, DG_MODE_NLEG, DG_MODE_NLEG }, - /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM, DG_MODE_CHFL, DG_MODE_HCOL }, - /* SOLO */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, - /* GENE */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, 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_GENE, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, 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_GENE, DG_MODE_NLEG, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, 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, DG_MODE_NLEG, DG_MODE_NLEG }, - /* HEAT */{ 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_NLEG, DG_MODE_HEAT, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_HCOL }, - /* 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, DG_MODE_CHFL, DG_MODE_NLEG }, - /* CHFL */{ 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_NLEG, DG_MODE_CHFL, DG_MODE_NLEG }, - /* HCOL */{ 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_NLEG, DG_MODE_NLEG, DG_MODE_HCOL }, + // from to-> FAULT SERVICE INIT STANBY STBY-SOLO GEN-IDLE FILL DRAIN FLUSH HEAT DIS CHEM DIS CHEM_FLUSH HEAT_COOL RO_PER_SAMPLE + /* 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, 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, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_ROPS }, + /* 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, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM, DG_MODE_CHFL, DG_MODE_HCOL, DG_MODE_ROPS }, + /* SOLO */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_HCOL, DG_MODE_ROPS }, + /* GENE */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, 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_GENE, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, 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_GENE, DG_MODE_NLEG, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, 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, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, + /* HEAT */{ 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_NLEG, DG_MODE_HEAT, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_HCOL, 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, DG_MODE_CHFL, DG_MODE_NLEG, DG_MODE_NLEG }, + /* CHFL */{ 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_NLEG, DG_MODE_CHFL, DG_MODE_NLEG, DG_MODE_NLEG }, + /* HCOL */{ 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_NLEG, DG_MODE_NLEG, DG_MODE_HCOL, DG_MODE_NLEG }, + /* ROPS */{ 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_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_ROPS }, }; // ********** private function prototypes ********** @@ -84,13 +86,14 @@ static void transitionToNewOperationMode( DG_OP_MODE_T newMode ); static U32 getDGOpModePublishInterval( void ); static void broadcastOperationMode( void ); +static void sendOperationStatusEvent( void ); /*********************************************************************//** * @brief * The initOperationModes function initializes the operation modes module. * @details Inputs: none * @details Outputs: modeRequest, lastMode, currentMode, currentSubMode, - * priorSubMode, dataPublishCounter + * dataPublishCounter * @return none *************************************************************************/ void initOperationModes( void ) @@ -107,7 +110,7 @@ lastMode = DG_MODE_INIT; currentMode = DG_MODE_INIT; currentSubMode = 0; - priorSubMode = 0; + currentSubState = NO_SUB_STATE; dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; transitionToNewOperationMode( DG_MODE_INIT ); @@ -126,25 +129,31 @@ initChemicalDisinfectMode(); initHeatDisinfectActiveCoolMode(); initChemicalDisinfectFlushMode(); + initROPermeateSampleMode(); } /*********************************************************************//** * @brief * The execOperationModes function executes the operation modes state machine. - * @details Inputs: currentMode - * @details Outputs: Operation modes' state machine executed + * @details Inputs: currentMode, currentSubMode + * @details Outputs: currentMode, currentSubMode * @return none *************************************************************************/ void execOperationModes( void ) { DG_OP_MODE_T newMode; + U32 priorSubMode = currentSubMode; + U32 priorSubState = currentSubState; - priorSubMode = currentSubMode; - // any new mode requests? newMode = arbitrateModeRequest(); // will return current mode if no pending requests - newMode = MODE_TRANSITION_TABLE[ currentMode ][ newMode ]; + if ( getTestConfigStatus( TEST_CONFIG_RECOVER_TREATMENT ) != TRUE ) + { + // If the test configuration is not enabled check for the legality of the transition request + newMode = MODE_TRANSITION_TABLE[ currentMode ][ newMode ]; + } + // is requested new mode valid and legal at this time? if ( newMode >= DG_MODE_NLEG ) { @@ -159,6 +168,10 @@ lastMode = currentMode; transitionToNewOperationMode( newMode ); currentMode = newMode; + // Set the last sub mode to 0 + // to ensure events cover the transition from submode 0 -> 1 -> 2 + priorSubMode = 0; + sendOperationStatusEvent(); } // mode specific processing to be done continuously @@ -216,21 +229,24 @@ currentSubMode = execChemicalDisinfectFlushMode(); break; + case DG_MODE_ROPS: + currentSubMode = execROPermeateSampleMode(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_STATE, (U32)currentMode ) currentMode = DG_MODE_FAUL; currentSubMode = 0; break; } - // Send sub-mode change event when appropriate - if ( priorSubMode != currentSubMode ) + // Send operation status event when appropriate + if ( ( priorSubMode != currentSubMode ) || ( priorSubState != currentSubState ) ) { + sendOperationStatusEvent(); SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_SUB_MODE_CHANGE, priorSubMode, currentSubMode ) } - priorSubMode = currentSubMode; - // publish op mode on interval broadcastOperationMode(); } @@ -283,6 +299,18 @@ /*********************************************************************//** * @brief + * The getCurrentOperationSubMode function gets the current operation submode. + * @details Inputs: currentSubMode + * @details Outputs: none + * @return the current operation submode + *************************************************************************/ +U32 getCurrentOperationSubMode( void ) +{ + return currentSubMode; +} + +/*********************************************************************//** + * @brief * The arbitrateModeRequest function selects highest priority mode request * and clear all requests. * @details Inputs: none @@ -323,13 +351,15 @@ * @brief * The transitionToNewOperationMode function undergo the process of transition * to new operation mode. - * @details Inputs: none + * @details Inputs: currentSubMode * @details Outputs: Transition to new mode * @param newMode new op mode to transition to * @return none *************************************************************************/ static void transitionToNewOperationMode( DG_OP_MODE_T newMode ) { + U32 priorSubMode = currentSubMode; + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_OP_MODE_CHANGE, lastMode, newMode ) // setup for new operating mode @@ -374,14 +404,19 @@ case DG_MODE_CHFL: currentSubMode = transitionToChemicalDisinfectFlushMode(); break; + case DG_MODE_ROPS: + currentSubMode = transitionToROPermeateSampleMode(); + break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, (U32)newMode ) break; } - SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_SUB_MODE_CHANGE, priorSubMode, currentSubMode ) - - priorSubMode = currentSubMode; + // Send sub-mode change event when appropriate + if ( priorSubMode != currentSubMode ) + { + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_SUB_MODE_CHANGE, priorSubMode, currentSubMode ) + } } /*********************************************************************//** @@ -401,7 +436,7 @@ data.currentMode = (U32)currentMode; data.currentSubMode = currentSubMode; - broadcastData( MSG_ID_DG_OP_MODE, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( OP_MODES_DATA_T ) ); + broadcastData( MSG_ID_DG_OP_MODE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( OP_MODES_DATA_T ) ); dataPublishCounter = 0; } @@ -427,7 +462,45 @@ return result; } +/*********************************************************************//** + * @brief + * The setCurrentSubState function sets the current subState. + * @details Inputs: subState + * @details Outputs: currentSubState + * @param subState the enumerated sub state. + * @return none + *************************************************************************/ +void setCurrentSubState( U32 subState ) +{ + currentSubState = subState; +} +/*********************************************************************//** + * @brief + * The sendOperationStatusEvent function constructs and sends an DG operation + * status event. + * @details Inputs: currentMode, currentSubMode, currentSubState + * @details Outputs: dat1, dat2. + * @return none + *************************************************************************/ +static void sendOperationStatusEvent() +{ + EVENT_DATA_T dat1; + EVENT_DATA_T dat2; + U32 opData = ( (U08)currentMode + + ( (U08)currentSubMode << SHIFT_8_BITS_FOR_BYTE_SHIFT ) + + ( (U08)currentSubState << SHIFT_16_BITS_FOR_WORD_SHIFT ) ); + + dat2.dataType = EVENT_DATA_TYPE_U32; + dat2.data.uInt.data = 0; + + dat1.dataType = EVENT_DATA_TYPE_U32; + dat1.data.uInt.data = opData; + + sendEvent( DG_EVENT_OPERATION_STATUS, dat1, dat2 ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/